强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Memcached 完全指南 / 第 1 章:Memcached 简介

第 1 章:Memcached 简介

1.1 历史起源

Memcached 最初由 Brad Fitzpatrick 于 2003 年为 LiveJournal 开发,目的是解决高并发读取场景下的数据库压力问题。

发展时间线

时间 事件
2003 Brad Fitzpatrick 为 LiveJournal 开发初版
2004 开源发布,迅速被 Facebook、YouTube、Twitter 等采用
2008 Facebook 部署超过 28 台 Memcached 服务器,缓存 28TB 数据
2009 Memcached 1.4 发布,引入二进制协议
2012 引入多线程支持(-t 参数)
2017 Memcached 1.5 引入 LRU 维护(lru_maintainer
2020 Memcached 1.6 引入 meta 协议、TLS 支持
2024 持续维护,广泛部署于全球各大互联网公司

核心设计理念

Memcached 的设计哲学可以用三个词概括:简单快速分布式

┌─────────────────────────────────────────────┐
│              Memcached 设计原则              │
├─────────────────────────────────────────────┤
│  1. K/V 存储:只做一件事,做到极致           │
│  2. 内存优先:数据只存在内存中,重启即丢失   │
│  3. 无持久化:不做 RDB/AOF,简化设计         │
│  4. 客户端分片:服务端无中心,客户端路由     │
│  5. O(1) 复杂度:所有操作常数时间            │
│  6. 懒惰删除:过期数据不立即回收,按需清理   │
└─────────────────────────────────────────────┘

1.2 核心特性

特性概览

特性 说明
存储模型 Key-Value,Value 最大 1MB(可配置)
数据类型 仅 String(二进制安全)
持久化 无,纯内存
集群方案 客户端一致性哈希分片
线程模型 多线程(主从 Reactor)
协议 文本协议 / 二进制协议 / Meta 协议
过期策略 惰性删除 + LRU 淘汰
原子操作 incr / decr / CAS
内存管理 Slab Allocator

为什么选择 Memcached?

场景一:纯粹的缓存层

如果你的需求是"查询 → 缓存 → 返回",不需要复杂数据结构,Memcached 是最佳选择:

# 典型缓存流程
Client → 查询 Memcached
  ├── 命中 → 直接返回(< 1ms)
  └── 未命中 → 查数据库 → 写入缓存 → 返回

场景二:大规模分布式缓存

Memcached 的客户端分片架构天然支持水平扩展:

                    ┌─── Memcached Node 1 (2GB)
Client ──哈希路由──┼─── Memcached Node 2 (2GB)
                    ├─── Memcached Node 3 (2GB)
                    └─── Memcached Node N (2GB)

1.3 适用场景

非常适合的场景

场景 说明 示例
数据库查询缓存 缓存 SQL 查询结果,降低 DB 压力 用户信息、商品详情
Session 存储 分布式会话管理 PHP Session Handler
页面片段缓存 缓存渲染后的 HTML 片段 导航栏、侧边栏
计数器/限流 利用 incr/decr 原子操作 API 限流、文章阅读量
Token 缓存 短期 Token 存储 JWT 黑名单、验证码
热点数据 高频读取的小数据 配置项、排行榜快照

不适合的场景

场景 原因 推荐方案
需要持久化 数据重启丢失 Redis / MySQL
复杂数据结构 只支持 String Redis(Hash/List/Set)
大 Value 存储 默认最大 1MB Redis / 本地文件
发布订阅 不支持 Pub/Sub Redis / RabbitMQ
数据分析 无聚合能力 Redis / ClickHouse
事务操作 无 MULTI/EXEC Redis

1.4 Memcached vs Redis

这是最常被问到的问题。两者都是优秀的内存缓存,但定位不同。

架构对比

Memcached 架构:                    Redis 架构:
┌──────────────┐                   ┌──────────────┐
│   Client     │                   │   Client     │
│ (一致性哈希) │                   │              │
└──┬───┬───┬───┘                   └──────┬───────┘
   │   │   │                              │
   ▼   ▼   ▼                              ▼
┌──┐ ┌──┐ ┌──┐                    ┌──────────────┐
│N1│ │N2│ │N3│  ← 无中心          │ Redis Server │ ← 有中心
└──┘ └──┘ └──┘                    │  (主从/集群)  │
                                  └──────────────┘

功能对比表

维度 Memcached Redis
数据结构 String Only String / Hash / List / Set / ZSet / Stream
持久化 RDB + AOF
集群 客户端分片 Redis Cluster / Sentinel
多线程 原生多线程 6.0+ 多线程 I/O
内存效率 更高(Slab 预分配) 较低(jemalloc 碎片)
单 Value 限制 1MB(可调) 512MB
原子操作 incr/decr/CAS 丰富(Lua/Transaction)
发布订阅 不支持 支持
Lua 脚本 不支持 支持
过期策略 惰性 + LRU 惰性 + 定期
协议复杂度 简单 RESP 协议
运维复杂度 中高(集群模式)
内存开销/Key ~70 bytes ~100+ bytes
适用规模 超大规模缓存 中大规模 + 业务逻辑

性能对比(单节点,小 Value)

操作 Memcached Redis 备注
GET (100B) ~200K QPS ~180K QPS 同等硬件
SET (100B) ~180K QPS ~160K QPS 同等硬件
内存效率 1x 1.2-1.5x Memcached 更省
延迟 P99 < 1ms < 1ms 无显著差异
连接数上限 数万 数万 取决于配置

注意:以上数据为参考值,实际性能受硬件、网络、Value 大小、并发量等因素影响。

选型决策树

需要持久化?
  ├── 是 → Redis
  └── 否 → 需要复杂数据结构?
              ├── 是 → Redis
              └── 否 → 需要发布订阅/Lua 脚本?
                          ├── 是 → Redis
                          └── 否 → 纯缓存 + 大规模 + 高吞吐?
                                      ├── 是 → Memcached ✓
                                      └── 否 → 两者均可(团队熟悉度决定)

1.5 谁在使用 Memcached?

大规模部署案例

公司 规模 用途
Facebook 数万台,PB 级缓存 社交图谱、News Feed
Twitter 数千台 Timeline 缓存
YouTube 数千台 视频元数据
Wikipedia 数百台 页面缓存
Slack 数百台 会话与消息缓存
GitHub 内部使用 API 结果缓存

Facebook 的经典架构

Facebook 在 2013 年的 USENIX 论文《Scaling Memcache at Facebook》中描述了其架构:

用户请求
    │
    ▼
┌─────────┐     ┌──────────┐     ┌───────────┐
│ Web 层  │────▶│ McRouter  │────▶│ Memcached │
│ (PHP)   │     │ (代理层)  │     │  集群     │
└─────────┘     └──────────┘     └───────────┘
    │                                  │
    ▼                                  ▼
┌─────────┐                    ┌───────────┐
│ MySQL   │◀────── 失效通知 ───│ 集群间    │
│ 集群    │                    │ 复制      │
└─────────┘                    └───────────┘

1.6 Memcached 的局限性

了解局限性同样重要:

已知限制

限制项 说明 解决方案
无持久化 重启数据丢失 上层补偿(DB 回源)
单线程命令执行 命令串行处理 1.6+ 改进
最大 Key 长度 250 字节 合理设计 Key
最大 Value 1MB(默认) 拆分或外部存储
无集群管理 需客户端/MC Router 使用代理层
LRU 全局 Slab 级别 LRU lru_maintainer
无访问控制 无 ACL SASL / 网络隔离

1.7 本教程路线图

基础篇(第 1-5 章)
  ├── 了解 Memcached(你在这里)
  ├── 安装与部署
  ├── 架构原理
  ├── 核心命令
  └── 数据类型与序列化

进阶篇(第 6-10 章)
  ├── Slab 分配器详解
  ├── LRU 淘汰策略
  ├── 一致性哈希
  ├── 多线程模型
  └── 通信协议

运维篇(第 11-14 章)
  ├── 安全加固
  ├── 监控与告警
  ├── 性能优化
  └── Docker 部署

实战篇(第 15-16 章)
  ├── 多语言客户端
  └── 生产最佳实践

1.8 快速体验

如果等不及看完全部教程,可以先用 Docker 快速体验:

# 启动 Memcached
docker run -d --name mc-test -p 11211:11211 memcached:1.6-alpine

# 安装命令行客户端
sudo apt-get install -y libmemcached-tools  # Debian/Ubuntu
# 或
brew install libmemcached                     # macOS

# 使用 telnet 连接(最简单的方式)
telnet localhost 11211

# 尝试基本操作
set mykey 0 3600 5       # 设置 Key,Flags=0,TTL=3600秒,5字节
hello                     # 值
STORED                    # 返回结果

get mykey                 # 获取
VALUE mykey 0 5           # 返回
hello
END

quit                      # 退出

扩展阅读

小结

要点 内容
本质 简单、快速的分布式内存 K/V 缓存
最大优势 极致简单 + 极致性能 + 原生多线程
最大局限 无持久化、仅 String、无集群管理
选型建议 纯缓存场景优先考虑 Memcached