Memcached 详解:高性能分布式内存缓存系统
Memcached 是一个开源的、高性能的、分布式的 内存对象缓存系统,最初由 LiveJournal 在 2003 年开发,用于缓解数据库负载。它被广泛应用于 Web 应用中,作为数据库前的“第一道防线”,显著提升系统响应速度和并发能力。
尽管近年来 Redis 更为流行,但 Memcached 依然在许多大型互联网公司(如 Facebook、Twitter、Wikipedia)中稳定运行,尤其在纯缓存场景下具有独特优势。
一、Memcached 的定位与核心价值
🚀 纯内存缓存 | 数据仅存储在内存中,不支持持久化 |
🔌 简单高效 | 协议简单,只支持字符串键值对,性能极高 |
🌐 分布式架构 | 客户端通过一致性哈希决定数据存放到哪个节点 |
🧩 LAMP/LEMP 栈标配 | 与 PHP、MySQL 深度集成 |
💡 缓存加速 | 主要用途:缓存数据库查询结果、会话、页面片段等 |
✅ 一句话总结:
Memcached 是一个专注于“极速缓存”的轻量级分布式内存 KV 存储,适合高并发、低延迟的只读缓存场景。
二、Memcached 的核心特性
⚡ 极致性能 | 单机 QPS 可达 10万+,延迟微秒级 |
🧱 基于内存 | 所有数据存储在 RAM 中,重启后丢失 |
🔗 无持久化 | 不支持 RDB/AOF,不是数据库替代品 |
📦 键值结构 | Key-Value 存储,Value 最大 1MB |
🧼 LRU 自动淘汰 | 内存满时自动淘汰最近最少使用数据 |
🌐 分布式设计 | 多节点集群,客户端决定数据分布 |
🔄 一致性哈希 | 减少节点增减时的数据迁移量 |
🛠 二进制协议 | 支持高效通信(可选) |
📡 TCP/UDP 支持 | UDP 用于高吞吐、容忍丢包场景 |
三、工作原理与架构
1. 架构图
+————+ +———————+
| Application | → | Memcached Client | → 路由(一致性哈希)
+————+ +———————+
↓
+———–+ +———–+ +———–+
| Node 1 | | Node 2 | | Node 3 |
| (10.0.0.1)| | (10.0.0.2)| | (10.0.0.3)|
+———–+ +———–+ +———–+
- 客户端负责路由:根据 key 的哈希值选择目标节点
- 服务端无集群通信:各节点独立运行,不互相通信(与 Redis Cluster 不同)
2. 数据存储机制
✅ Slab Allocation( slab 分配器)
Memcached 使用 Slab Allocator 管理内存,避免内存碎片。
工作流程:
Slab 1: chunk_size=96B → 存储 50B~96B 的数据
Slab 2: chunk_size=128B → 存储 97B~128B 的数据
…
⚠️ 缺点:内存浪费(如存 97B 数据会占用 128B)
3. 过期与淘汰机制
✅ 过期(Expiration)
- 支持设置 TTL(秒级)
- 过期是惰性删除:get 时检查是否过期
- 也可通过 LRU crawler 主动清理
set mykey 0 3600 6 # 3600秒后过期,value长度6
value data
✅ 淘汰(Eviction)
- 使用 LRU(Least Recently Used) 策略
- 当内存不足时,淘汰最久未使用的数据
- 可配置 maxmemory 限制内存使用
四、Memcached vs Redis 对比
📦 数据结构 | 仅 String | String, Hash, List, Set, ZSet, Stream 等 |
💾 持久化 | ❌ 不支持 | ✅ RDB/AOF |
🔐 多线程 | ✅ 支持 | ❌ 单线程(命令处理) |
🌐 分布式 | 客户端分片 | 支持 Cluster 模式 |
🧩 原子操作 | ✅ incr/decr | ✅ 更丰富的原子命令 |
🧠 内存管理 | Slab Allocation | 动态分配 + LRU |
📏 Value 大小 | ≤ 1MB | ≤ 512MB |
🔄 数据淘汰 | LRU | 支持多种策略(LRU, LFU, TTL) |
🧰 用途 | 纯缓存 | 缓存、消息队列、分布式锁、实时计算等 |
✅ 选择建议:
- 纯缓存、高并发读 → Memcached
- 多功能、需持久化、复杂数据结构 → Redis
五、安装与配置(以 Linux 为例)
1. 安装
# Ubuntu/Debian
sudo apt-get install memcached
# CentOS/RHEL
sudo yum install memcached
# 或使用 dnf
sudo dnf install memcached
2. 启动服务
# 基本启动
memcached -d -m 64 -p 11211 -u nobody
# 参数说明:
# -d: 守护进程
# -m: 内存大小(MB)
# -p: 端口
# -u: 运行用户
# -c: 最大连接数
# -t: 线程数(提升并发)
3. 配置文件(可选)
通常通过命令行参数配置,也可使用 /etc/memcached.conf
六、客户端使用示例(Python)
1. 安装客户端
pip install python-memcached
2. 基本操作
import memcache
# 连接多个节点(客户端自动分片)
mc = memcache.Client(['10.0.0.1:11211', '10.0.0.2:11211'], debug=0)
# 设置缓存(key, value, expire)
mc.set("user:1001", "{'name': 'Alice'}", 3600)
# 获取缓存
data = mc.get("user:1001")
print(data)
# 删除
mc.delete("user:1001")
# 原子增减(适用于计数器)
mc.incr("counter:page_view", 1)
mc.decr("counter:stock", 1)
七、典型应用场景
1. 数据库查询缓存
data = mc.get("sql:select_user_1001")
if not data:
data = db.query("SELECT * FROM users WHERE id=1001")
mc.set("sql:select_user_1001", data, 600) # 缓存10分钟
2. 会话存储(Session)
session = mc.get(f"session:{token}")
if session:
login_user(session['user_id'])
3. 页面片段缓存
html = mc.get("fragment:sidebar")
if not html:
html = render_sidebar()
mc.set("fragment:sidebar", html, 1800)
4. 计数器(原子操作)
incr page:view:counter
八、Memcached 的局限性
❌ 无持久化 | 重启即丢数据,不能做数据库 |
❌ 无主从复制 | 不支持高可用自动故障转移 |
❌ 无数据结构 | 无法存储对象、列表等复杂结构 |
❌ 无认证机制 | 默认无密码,需靠网络隔离 |
❌ 最大 value 1MB | 不适合大对象缓存 |
💡 注意:这些“缺点”也是其“简单高效”的代价。
九、最佳实践建议
✅ 合理设置 TTL | 避免数据长期不更新 |
✅ 控制 value 大小 | 尽量 < 100KB,避免网络阻塞 |
✅ 使用连接池 | 减少连接开销 |
✅ 监控内存使用 | `echo “stats” |
✅ 避免缓存雪崩 | 设置随机过期时间 |
✅ 多节点部署 | 提升容量和可用性 |
✅ 结合 CDN/本地缓存 | 多层缓存架构 |
十、运维常用命令(通过 telnet 或 nc)
# 连接
telnet 127.0.0.1 11211
# 查看状态
stats
# 查看内存统计
stats items
# 清空所有缓存
flush_all
# 退出
quit
📌 stats 输出关键字段:
- curr_items: 当前 item 数量
- bytes: 已使用内存
- get_hits / get_misses: 命中率
- evictions: 被淘汰次数(越大说明内存不足)
十一、总结:Memcached 的适用场景
✅ 适合使用 Memcached 的场景:
- 纯缓存加速(如数据库查询结果)
- 高并发读、低并发写的场景
- 对延迟极度敏感的应用
- 已有成熟一致性哈希路由的系统
❌ 不适合的场景:
- 需要持久化的数据
- 需要复杂数据结构(如排行榜)
- 需要分布式锁、消息队列等功能
- 要求高可用自动故障转移
✅ 结语:
Memcached 虽然“古老”,但其 简单、稳定、高效 的设计哲学,使其在特定场景下依然不可替代。理解它的定位与限制,才能在技术选型中做出正确决策。
🔗 推荐组合:
Memcached(缓存层) + MySQL(持久层) + Redis(功能层) = 完整的现代 Web 架构。
评论前必须登录!
注册