Article

键值型数据库Memcached

更新于:2026-07-16

第一章:Memcached 概述

1.1 什么是 Memcached

概念名称说明注意事项
Memcached一个开源的高性能分布式内存对象缓存系统,用于通过在内存中缓存数据和对象来减少数据库负载,提升动态 Web 应用速度。不支持持久化,重启后数据丢失。
键值存储(Key-Value Store)Memcached 以简单的 key-value 形式存储数据,key 为字符串,value 为任意二进制数据(最大 1MB)。key 长度限制通常为 250 字节。
分布式架构Memcached 本身无内置集群协议,依赖客户端实现分布式(如一致性哈希)。多个 Memcached 实例独立运行,互不通信。服务端无主从、无复制机制。
协议基础基于文本协议(也可使用二进制协议),可通过 telnet 或 netcat 直接交互。默认监听 TCP 11211 端口。

1.2 Memcached 的特点与优势

特点/优势名称说明注意事项
高性能纯内存操作,C 语言编写,单线程事件驱动模型(早期版本),延迟极低。多核利用率依赖多实例部署。
简单轻量API 极简,仅支持基本的 set/get/delete/incr/decr 等操作,无复杂数据结构。不适合需要列表、集合等结构的场景。
分布式友好客户端可轻松实现跨多节点的数据分片,扩展性好。需自行处理节点增减时的数据迁移。
内存高效管理使用 Slab Allocator 机制分配内存,避免内存碎片。预分配 slab class,可能造成内部碎片。
广泛语言支持几乎所有主流编程语言均有成熟客户端库(Python、Java、PHP、Node.js 等)。各客户端功能和稳定性略有差异。
无认证与加密默认无身份验证和传输加密机制,需部署在可信内网。公网暴露存在安全风险。

1.3 Memcached 与其他缓存系统对比(如 Redis)

对比维度MemcachedRedis注意事项
数据结构支持仅支持字符串(二进制安全)支持字符串、哈希、列表、集合、有序集合、位图、流等Redis 功能更丰富,适合复杂场景。
持久化不支持支持 RDB 快照和 AOF 日志两种持久化方式Memcached 仅用于临时缓存。
内存管理Slab Allocator,固定大小块分配简单动态分配(jemalloc),更灵活Memcached 可能浪费内存(slab 内部碎片)。
多线程传统版本为单线程;新版(1.6+)支持多线程 I/ORedis 6.0+ 引入 I/O 多线程,核心命令仍单线程执行高并发下新版 Memcached 性能更优。
集群能力无内置集群,依赖客户端分片支持 Redis Cluster(自动分片、故障转移)Redis 集群运维更自动化。
事务与 Lua 脚本不支持支持 MULTI/EXEC 事务及 Lua 脚本Redis 可实现原子复合操作。
发布/订阅不支持支持 Pub/Sub 模式Redis 可用于消息传递场景。
最大值大小默认 1MB(可调,但不推荐超过)默认 512MB(可配置)Memcached 不适合大对象缓存。
社区与生态成熟稳定,但近年发展缓慢活跃社区,云厂商广泛支持,工具链丰富新项目更倾向选择 Redis。

第二章:Memcached 安装与配置

2.1 在 Linux 系统中安装 Memcached

步骤名称操作细节注意事项
更新系统包执行 sudo apt update(Debian/Ubuntu)或 sudo yum update(CentOS/RHEL)确保系统为最新状态,避免依赖冲突。
安装 MemcachedUbuntu/Debian: sudo apt install memcached
CentOS/RHEL: sudo yum install memcached
部分旧版本需启用 EPEL 仓库(如 CentOS 7)。
安装 libmemcached(可选)sudo apt install libmemcached-toolssudo yum install libmemcached提供额外工具如 memstat、memcp 等。
验证安装执行 memcached -h 查看帮助信息,确认版本号若命令未找到,检查 PATH 或重新安装。
设置开机自启sudo systemctl enable memcached默认配置文件通常位于 /etc/memcached.conf

2.2 在 Windows 系统中安装 Memcached

步骤名称操作细节注意事项
下载 Windows 版本从可信第三方源(如 https://github.com/memcached/memcached/wiki/Install)下载预编译的 .exe 文件(如 memcached-win64.zip)官方不提供 Windows 支持,需使用社区维护版本。
解压到目标目录例如解压到 C:\memcached路径不要包含空格或中文字符。
注册为系统服务以管理员身份运行 CMD,执行:C:\memcached\memcached.exe -d install需要管理员权限,否则注册失败。
启动服务执行 net start memcached 或通过”服务”管理界面启动默认监听 11211 端口。
验证运行状态执行 telnet localhost 11211,若连接成功则服务正常若 telnet 未启用,需在”启用或关闭 Windows 功能”中开启。
卸载服务(可选)执行 C:\memcached\memcached.exe -d uninstall卸载前需先停止服务。

2.3 启动与停止 Memcached 服务

操作名称操作细节注意事项
手动前台启动直接运行 memcached -p 11211 -m 64 -u memcached(Linux)适合调试,关闭终端即终止进程。
后台启动(Linux)使用 systemd:sudo systemctl start memcached
或使用 -d 参数:memcached -d -m 64
-d 表示 daemon 模式(部分版本支持)。
停止服务(Linux)sudo systemctl stop memcachedkillall memcached避免直接 kill -9,可能导致资源未释放。
启动服务(Windows)net start memcached仅适用于已注册为服务的情况。
停止服务(Windows)net stop memcached停止后所有缓存数据立即丢失。
检查端口监听ss -tuln | grep 11211(Linux)或 netstat -ano | findstr 11211(Windows)确认服务是否真正监听。

2.4 常用启动参数详解

参数名称语法示例用途说明注意事项
-p-p 11211指定监听的 TCP 端口,默认为 11211需确保端口未被占用。
-U-U 11211指定监听的 UDP 端口(可设为 0 禁用 UDP)UDP 不可靠,生产环境建议禁用(-U 0)。
-l-l 127.0.0.1指定监听的 IP 地址,限制访问来源默认监听所有接口(0.0.0.0),存在安全风险。
-m-m 512分配给 Memcached 的最大内存(MB),默认 64MB实际使用可能略超,因 slab 元数据开销。
-c-c 1024最大并发连接数,默认 1024连接数过高可能耗尽文件描述符。
-t-t 4使用的线程数(Memcached 1.6+ 支持多线程 I/O)旧版本忽略此参数。
-d-d以守护进程(daemon)方式运行Windows 版使用 -d install 注册服务。
-u-u nobody指定运行用户(Linux 下需 root 启动后切换)不能以 root 用户运行(安全限制)。
-f-f 1.25slab 增长因子(chunk size 每级增长倍数),默认 1.25调整影响内存利用率和碎片率。
-n-n 48单个 item 最小空间(字节),包含 key/value/header 开销默认 48 字节,过小会浪费内存。
-M-M内存耗尽时返回错误(而非驱逐旧数据)默认行为是 LRU 淘汰,慎用 -M
-o-o modern-o lru_crawler启用高级选项(如 LRU crawler、slab automove 等)需 Memcached 1.5+ 支持。
-v / -vv / -vvv-vv输出详细日志(-v: 普通, -vv: 详细, -vvv: 最详细)调试用,生产环境避免高 verbose 级别。

第三章:Memcached 命令行操作基础

3.1 连接 Memcached 服务器(telnet/nc)

步骤名称操作细节注意事项
使用 telnet 连接在终端执行:telnet 127.0.0.1 11211若提示”command not found”,需安装 telnet 客户端(如 sudo apt install telnet)。
使用 nc(netcat)连接执行:nc 127.0.0.1 11211nc 更轻量,适合脚本自动化;部分系统需安装 netcat 或 ncat。
验证连接成功成功连接后无提示符,可直接输入 Memcached 命令若连接被拒绝,检查 Memcached 是否运行及监听地址/端口。
退出连接输入 quit 并回车,或按 Ctrl+] 后输入 quit(telnet)直接关闭终端可能导致连接未正常释放。
连接远程服务器127.0.0.1 替换为远程 IP,如 telnet 192.168.1.100 11211确保防火墙开放 11211 端口,且 Memcached 监听非 127.0.0.1 地址。

3.2 存储类命令(set/add/replace/prepend/append)

方法名称语法用途说明代码示例(在 telnet/nc 中输入)注意事项
setset <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n无条件存储 key-value,存在则覆盖set username 0 0 5
alice
flags 通常设为 0;exptime=0 表示永不过期(实际受内存淘汰影响)。
addadd <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n仅当 key 不存在时存储add token 0 3600 10
abc123def
若 key 已存在,返回 NOT_STORED。
replacereplace <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n仅当 key 存在时替换其值replace username 0 0 6
bob
若 key 不存在,返回 NOT_STORED。
appendappend <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n在现有 value 后追加数据(二进制安全)append username 0 0 1
e
key 必须存在,否则失败;flags 和 exptime 被忽略(但必须提供)。
prependprepend <key> <flags> <exptime> <bytes> [noreply]\r\n<value>\r\n在现有 value 前插入数据prepend username 0 0 1
A
同 append,flags/exptime 仅占位,不生效。

注:所有命令末尾需以 \r\n(回车换行)结束,但在 telnet/nc 交互中直接按 Enter 即可。[noreply] 为可选参数,若指定则服务器不返回 STORED/NOT_STORED。

3.3 获取类命令(get/gets)

方法名称语法用途说明代码示例注意事项
getget <key>获取指定 key 的 valueget username可一次获取多个 key:get k1 k2 k3
getsgets <key>获取 key 的 value 及其 CAS 唯一标识符gets username用于实现 check-and-set 乐观锁机制

返回格式示例(get):

VALUE username 0 5
alice
END

返回格式示例(gets):

VALUE username 0 5 12345
alice
END

其中 12345 为 CAS token。

3.4 删除类命令(delete)

方法名称语法用途说明代码示例注意事项
deletedelete <key> [noreply]删除指定 keydelete username若 key 不存在,返回 NOT_FOUND;添加 noreply 可抑制响应。

成功删除返回 DELETED,失败返回 NOT_FOUND

3.5 计数类命令(incr/decr)

方法名称语法用途说明代码示例注意事项
incrincr <key> <value> [noreply]对 key 对应的数值原子递增incr counter 5key 必须已存在且为纯数字字符串(0-9),否则返回 ERROR。
decrdecr <key> <value> [noreply]对 key 对应的数值原子递减(最小为 0)decr counter 2递减不会低于 0;不能用于负数。

示例流程:

set counter 0 0 1
3
incr counter 2
→ 5
decr counter 10
→ 0

3.6 其他实用命令(stats/flush_all/version/quit)

方法名称语法用途说明代码示例注意事项
statsstats获取服务器统计信息(连接数、命中率、内存等)stats可加子命令如 stats itemsstats slabs 查看详细信息。
flush_allflush_all [delay] [noreply]立即或延迟清空所有缓存数据flush_all 10delay 单位为秒;数据立即不可见,但内存回收依赖 LRU。
versionversion返回 Memcached 版本号version返回如 VERSION 1.6.12
quitquit关闭当前连接quit客户端应主动调用以释放资源。

stats 常见输出字段:

  • get_hits / get_misses:用于计算命中率
  • curr_items:当前缓存项数量
  • bytes:当前使用内存量(字节)
  • total_connections:历史总连接数

第四章:Memcached 数据管理机制

4.1 内存分配机制(Slab Allocator)

概念名称说明注意事项
SlabMemcached 将内存划分为多个 Slab Class,每个 Slab 是 1MB 的连续内存块。启动时预分配,总内存由 -m 参数控制。
Slab Class按数据大小分组,每个 Class 对应一个固定的 chunk size(如 96B、120B…)。chunk size = previous_size × growth_factor(默认 1.25)。
ChunkSlab 被进一步划分为等长的 Chunk,用于存储单个 item(key + value + 元数据)。一个 item 只能放入 chunk size ≥ item 总大小的 Slab Class。
Item 结构包含 key(字符串)、value(二进制)、flags(整数)、exptime(过期时间)、CAS token 等元数据。实际占用空间 = key_len + value_len + 固定头部(约 32–48 字节)。
内存碎片(内部)若 item 大小小于 chunk size,剩余空间浪费,称为”内部碎片”。小对象缓存效率高,大对象易造成浪费。
Slab Reassignment(可选)新版 Memcached 支持 -o slab_reassign 动态迁移空闲 Slab 到更需 Class。需显式启用,避免某些 Class 内存耗尽而其他闲置。

4.2 LRU 淘汰策略

概念名称说明注意事项
LRU(Least Recently Used)当内存满且需插入新 item 时,优先淘汰最久未被访问的 item。默认全局 LRU,新版支持 per-slab-class LRU。
淘汰触发条件所有 Slab Class 的可用 chunk 耗尽,且无法分配新 chunk。即使总内存未满,若某 Class 满而 item 属于该 Class,仍会淘汰。
evictions 统计stats 命令中的 evictions 字段记录因内存不足被驱逐的 item 数量。高 evictions 表示缓存容量不足或热点不均。
LRU Crawler后台线程定期扫描 Slab,清理已过期但未被访问的 item(需 -o lru_crawler 启用)。减少内存浪费,提升命中率。
不淘汰的情况若启动时加 -M 参数,则内存满时直接返回错误,不执行 LRU 淘汰。适用于不允许缓存污染的关键场景。

4.3 键的命名规范与限制

限制项说明注意事项
最大长度key 最大 250 字节(部分客户端限制为 255,但服务端强制截断至 250)。超长 key 会被拒绝或静默截断,导致数据错乱。
字符集支持任意二进制安全字符串(包括 null 字节),但建议使用 ASCII 或 UTF-8。避免控制字符(如换行、回车),可能干扰文本协议解析。
命名建议使用有意义的前缀(如 user:123:profile),便于管理和调试。避免纯数字 key(某些客户端可能混淆类型)。
唯一性key 在整个 Memcached 实例中必须唯一,相同 key 会覆盖旧值。分布式环境下,key 哈希到哪个节点由客户端决定。
特殊字符处理空格、冒号、下划线等均可使用,但避免使用 \r\n(协议分隔符)。推荐使用字母、数字、连字符、下划线组合。

4.4 值的大小与过期时间限制

限制项说明注意事项
最大值大小单个 value 最大为 1MB(1,048,576 字节),包含 key 和元数据总和 ≤ 1MB。超限将返回 SERVER_ERROR object too large for cache
实际可用 value 空间≈ 1MB - key_len - 头部开销(通常 ≥ 48 字节)存储 1MB value 时,key 应尽量短。
过期时间(exptime)支持两种格式:
• 相对秒数(如 3600 表示 1 小时后过期)
• Unix 时间戳(≥ 30 天秒数,如 1735689600)
若设为 0,表示”永不过期”(但仍可能被 LRU 淘汰)。
最大过期时间相对时间最大支持约 30 天(2,592,000 秒);超过则视为时间戳。误将小时间戳(如 1000)当作相对时间会导致立即过期。
过期行为过期 item 不会立即删除,仅在 get 访问或 LRU Crawler 扫描时清理。内存不会实时释放,可能短暂占用资源。
二进制安全value 可为任意二进制数据(图片、序列化对象等),无字符集限制。客户端需自行处理序列化/反序列化。

第五章:Memcached 客户端使用(语言集成)

5.1 Python 客户端(python-memcached / pymemcache)

方法/组件名称语法 / 安装方式用途说明代码示例注意事项
安装 python-memcachedpip install python-memcached老牌客户端,基于文本协议from memcache import Client
mc = Client(['127.0.0.1:11211'])
已停止维护,不支持二进制协议,线程不安全。
安装 pymemcachepip install pymemcache现代客户端,支持文本/二进制协议,性能更好from pymemcache.client import base
mc = base.Client(('localhost', 11211))
推荐新项目使用;支持连接池、哈希环等。
setclient.set(key, value, time=0, min_compress_len=0)存储键值对mc.set('user:1001', {'name': 'Alice'}, time=3600)time 为过期时间(秒);value 需可序列化(如 str、bytes、dict)。
getclient.get(key)获取单个值data = mc.get('user:1001')未命中返回 None。
getsclient.gets(key)获取值和 CAS tokenvalue, cas = mc.gets('counter')用于配合 cas 实现乐观锁。
casclient.cas(key, value, cas, time=0)仅当 CAS 匹配时更新mc.cas('counter', 42, cas_token, time=0)返回 True/False 表示是否成功。
add / replaceclient.add(key, value, time=0)
client.replace(key, value, time=0)
条件写入mc.add('lock', 'held', time=10)add 仅在 key 不存在时成功;replace 仅在存在时成功。
deleteclient.delete(key, noreply=False)删除键mc.delete('temp_data')noreply=True 可提升性能但无确认。
incr / decrclient.incr(key, delta=1)
client.decr(key, delta=1)
原子计数mc.incr('page_views', 1)key 必须已存在且为数字字符串。
多节点支持from pymemcache.client.hash import HashClient
client = HashClient([('h1',11211), ('h2',11211)])
一致性哈希分片client.set('user:1002', data)自动路由到对应节点。

5.2 Java 客户端(SpyMemcached / XMemcached)

方法/组件名称语法 / 安装方式用途说明代码示例注意事项
SpyMemcached(Maven)<dependency><groupId>net.spy</groupId><artifactId>spymemcached</artifactId><version>2.12.3</version></dependency>异步、高性能,但已归档MemcachedClient mc = new MemcachedClient(new InetSocketAddress("localhost", 11211));不再积极维护,建议迁移到其他方案。
XMemcached(Maven)<dependency><groupId>com.googlecode.xmemcached</groupId><artifactId>xmemcached</artifactId><version>2.4.8</version></dependency>支持连接池、高并发、协议灵活XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses("localhost:11211"));
XMemcachedClient mc = builder.build();
推荐生产使用;支持权重、故障转移。
setmc.set(String key, int exp, Object value)存储mc.set("session:abc", 1800, sessionData);exp=0 表示永不过期;value 需实现 Serializable。
getObject mc.get(String key)获取Session s = (Session) mc.get("session:abc");未命中返回 null。
getsGetsResponse<Object> mc.gets(String key)获取带 CASGetsResponse r = mc.gets("counter");通过 r.getCas() 获取 token。
casboolean mc.cas(String key, long casId, int exp, Object value)CAS 更新boolean ok = mc.cas("counter", casId, 0, newValue);返回是否成功。
deleteboolean mc.delete(String key)删除mc.delete("temp_key");返回是否删除成功。
incr / decrlong mc.incr(String key, long by)
long mc.decr(String key, long by)
计数long views = mc.incr("views", 1);若 key 不存在,incr 可能失败(部分版本支持初始化)。
异步操作Future<Boolean> future = mc.set("key", 0, "val");非阻塞调用Boolean result = future.get();SpyMemcached 默认异步;XMemcached 可选。

5.3 Node.js 客户端(memjs / memcached)

方法/组件名称语法 / 安装方式用途说明代码示例注意事项
安装 memjsnpm install memjs简洁、支持二进制协议const memjs = require('memjs');
const client = memjs.Client.create();
默认连接 localhost:11211;支持多节点。
安装 memcachednpm install memcached功能丰富,支持连接池、哈希const Memcached = require('memcached');
const client = new Memcached('localhost:11211');
更成熟,但配置复杂。
setclient.set(key, value, ttl, callback)存储client.set('user:1', JSON.stringify(user), 3600, (err) => { ... });ttl=0 表示永不过期;value 通常为字符串或 Buffer。
getclient.get(key, callback)获取client.get('user:1', (err, data) => { console.log(data); });未命中时 data 为 false。
getsclient.gets(key, callback)获取带 CASclient.gets('counter', (err, data, cas) => { ... });memjs 支持;memcached 模块需查文档。
casclient.cas(key, value, cas, ttl, callback)CAS 更新client.cas('counter', '42', casToken, 0, (err, success) => { ... });仅 memjs 明确支持。
delclient.del(key, callback)删除client.del('old_key', (err) => { ... });别名为 delete,但部分模块用 del 避免关键字冲突。
incr / decrclient.incr(key, amount, callback)
client.decr(key, amount, callback)
计数client.incr('hits', 1, (err, newCount) => { ... });amount 必须为正整数。
多节点配置memjs.Client.create('host1:11211,host2:11211')分布式缓存const client = memjs.Client.create('192.168.1.10:11211,192.168.1.11:11211');自动使用一致性哈希。

5.4 PHP 客户端(Memcached 扩展)

方法/组件名称语法 / 安装方式用途说明代码示例注意事项
安装扩展sudo apt install php-memcached(Linux)或通过 PECL 安装高性能 C 扩展,支持二进制协议$mc = new Memcached();
$mc->addServer('localhost', 11211);
需启用 memcached 扩展(非 memcache)。
set$mc->set(string $key, mixed $value, int $expiration = 0)存储$mc->set('token', 'abc123', 3600);$value 可为任意可序列化类型(自动 serialize)。
get$mc->get(string $key)获取$data = $mc->get('token');未命中返回 false。
getMulti$mc->getMulti(array $keys)批量获取$results = $mc->getMulti(['k1', 'k2']);返回关联数组。
add / replace$mc->add($key, $value, $exp)
$mc->replace($key, $value, $exp)
条件写入$mc->add('lock', true, 10);成功返回 true,否则 false。
delete$mc->delete(string $key, int $time = 0)删除$mc->delete('temp');$time > 0 表示延迟删除(不常用)。
increment / decrement$mc->increment($key, $offset = 1)
$mc->decrement($key, $offset = 1)
计数$mc->increment('counter', 5);若 key 不存在,increment 可能初始化为 offset(依赖配置)。
getCasToken$mc->get($key, null, Memcached::GET_EXTENDED)获取 CAS token$result = $mc->get('counter', null, Memcached::GET_EXTENDED);
$cas = $result['cas'];
需配合 cas() 使用。
cas$mc->cas(float $cas_token, string $key, mixed $value, int $exp = 0)CAS 更新$mc->cas($cas, 'counter', 100);返回 bool 表示是否成功。
多服务器$mc->addServers([['host1',11211], ['host2',11211]]);分布式部署$mc->addServers([['192.168.1.10',11211], ['192.168.1.11',11211]]);自动使用一致性哈希。

第六章:Memcached 高可用与集群

6.1 客户端一致性哈希(Consistent Hashing)

概念/操作名称说明注意事项
一致性哈希目的在多节点 Memcached 集群中,当节点增减时,最小化 key 重映射比例(理想为 1/N)。传统取模哈希在节点变化时会导致几乎所有 key 重新分配。
虚拟节点(Virtual Node)每个物理节点映射多个虚拟节点(如 100~200 个),均匀分布在哈希环上。提高负载均衡性,避免数据倾斜。
哈希环(Hash Ring)将 0 ~ 2³²-1 的整数空间首尾相连形成环,key 和节点均通过哈希函数映射到环上。常用哈希函数:MD5、CRC32、MurmurHash。
key 路由规则对 key 哈希后,顺时针查找第一个虚拟节点,其所属物理节点即为目标服务器。所有客户端必须使用相同哈希算法和虚拟节点策略。
客户端实现示例Python pymemcache.HashClient、PHP Memcached::addServers、Java XMemcached不同语言客户端的虚拟节点数量和哈希算法可能不同,跨语言需统一。
优势节点扩容/缩容时,仅影响相邻虚拟节点的数据,缓存命中率波动小。无法自动复制数据,故障节点数据完全丢失。
局限性不提供高可用(无副本),单点故障导致部分缓存失效。需配合应用层重试或降级策略。

6.2 多节点部署与故障转移

操作/机制名称操作细节注意事项
多节点独立部署在多台服务器分别启动 Memcached 实例,监听各自 IP:11211各实例无通信,完全独立;总容量为各节点内存之和。
客户端配置多地址在客户端初始化时传入所有节点地址列表(如 ['node1:11211', 'node2:11211']必须启用一致性哈希(而非随机或轮询)。
节点故障表现故障节点上的 key 无法访问,客户端 get 返回 miss,触发回源数据库缓存雪崩风险:大量请求穿透到后端。
故障检测客户端通常无主动健康检查;依赖 TCP 连接失败或超时判断节点不可用可通过连接池或自定义 wrapper 实现简单探活。
自动剔除故障节点部分高级客户端(如 XMemcached)支持权重置零或临时移除故障节点需谨慎处理,避免误判导致容量骤降。
数据恢复策略无自动恢复;依赖应用层在 get miss 时从数据库加载并重新 set 到新节点热点 key 可能造成数据库瞬时压力。
扩容操作步骤1. 新增 Memcached 实例
2. 客户端更新节点列表
3. 重启或热加载配置
扩容后仅新写入的 key 分布到新节点,旧数据仍留在原节点。
缩容操作步骤1. 从客户端移除节点
2. 停止该 Memcached 实例
缩容节点上的数据立即不可用,需接受短暂命中率下降。

6.3 与代理方案结合(如 mcrouter)

组件/操作名称说明注意事项
mcrouter 简介Facebook 开源的 Memcached 协议代理,支持路由、复制、故障转移、多集群等高级功能。用 C++ 编写,高性能,支持百万级 QPS。
核心功能• Prefix 路由(如 prod.* → 集群 A)
• 同步/异步复制
• 自动故障转移
• 请求日志与统计
配置灵活,适合大规模生产环境。
部署架构应用 → mcrouter(本地或独立集群) → Memcached 节点组mcrouter 本身无状态,可水平扩展。
安装方式官方提供 RPM/DEB 包或源码编译(依赖 folly、wangle 等)推荐使用官方 Docker 镜像快速部署。
基础配置示例`{ “pools”: { “A”: { “servers”: [“10.0.1.10:11211”, “10.0.1.11:11211”] } }, “route”: “PoolRouteA” }`
复制模式(Replicated)写操作同步发送到多个池,读操作从主池获取提升可用性,但增加写延迟和带宽消耗。
Miss Error Routing当主集群 miss 时,自动 fallback 到备份集群用于多级缓存或异地容灾。
客户端连接方式应用连接 mcrouter(默认端口 11211),如同连接普通 Memcached无需修改应用代码,仅改连接地址。
监控与运维支持 stats 命令、JSON API、Prometheus exporter可集成到 Grafana 实现可视化监控。
替代方案• twemproxy(nutcracker):较老,功能较少
• AWS ElastiCache(托管服务)
mcrouter 功能最全面,但运维复杂度高。

第七章:Memcached 性能调优与监控

7.1 性能指标解读(stats 命令输出)

指标名称说明注意事项
pidMemcached 进程 ID用于进程管理。
uptime服务已运行秒数判断是否近期重启。
time当前 Unix 时间戳用于日志对齐。
versionMemcached 版本号确认是否为支持新特性的版本(如多线程)。
curr_connections当前活跃连接数突增可能表示连接泄漏或 DDoS。
total_connections历史总连接数结合 uptime 可估算平均连接速率。
connection_structures当前分配的连接结构体数量通常等于 curr_connections。
cmd_get / cmd_setget / set 命令总次数用于计算读写比例。
get_hits / get_missesget 命中 / 未命中次数缓存命中率 = get_hits / (get_hits + get_misses);理想 > 90%。
evictions因内存不足被 LRU 淘汰的 item 数量高值表示内存不足或热点不均;应结合 curr_items 分析。
bytes当前缓存数据占用的总字节数接近 -m 设置值时需扩容。
curr_items当前缓存中的 item 总数与 bytes 共同反映数据密度。
total_items历史存储过的 item 总数用于估算写入吞吐。
bytes_read / bytes_written网络收发总字节数监控带宽使用。
limit_maxbytes内存上限(字节),由 -m 参数决定例如 -m 512 → limit_maxbytes = 536870912。
threads工作线程数(Memcached 1.6+)应 ≤ CPU 核心数。
rusage_user / rusage_system进程累计 CPU 用户态/内核态时间(秒)用于性能分析。
auth_cmds / auth_errors认证命令数 / 失败数(若启用 SASL)默认未启用,值为 0。

关键健康指标判断:

  • 高 evictions + 低命中率 → 内存不足,需扩容或优化 key 生命周期。
  • curr_connections 接近 maxconns(默认 1024) → 需调大 -c 参数。
  • bytes ≈ limit_maxbytes 且 evictions 持续增长 → 缓存容量已达瓶颈。

7.2 内存碎片与 slab 调优

调优项说明注意事项
查看 slab 信息执行 stats slabs 获取每个 slab class 的 chunk size、chunks per page、used chunks 等关注 mem_requested(实际数据大小)与 total_malloced(分配内存)之比。
查看 items 信息执行 stats items 查看各 slab class 中 item 数量、age、LRU 信息number_hot/number_warm/number_cold 反映访问热度(需启用 LRU maintainer)。
调整增长因子(-f)启动参数 -f 1.2(默认 1.25)控制 slab class 间 chunk size 增长倍数减小 f → 更多 class,减少内部碎片,但增加元数据开销;增大 f → 相反。
调整最小 item 大小(-n)-n 64(默认 48)设置最小 chunk size(含头部)若大量存储小对象(<48B),适当减小可节省内存。
启用 slab_automove启动参数 -o slab_automove=1 自动迁移空闲 slab 到繁忙 class需 Memcached ≥ 1.5;缓解某些 class 内存耗尽问题。
启用 slab_reassign-o slab_reassign 允许后台线程回收完全空闲的 slab 并重分配与 slab_automove 配合使用效果更佳。
监控内部碎片率内部碎片率 ≈ 1 - (mem_requested / total_malloced)>20% 表示碎片严重,需调整 -f-n
预分配大对象专用 class通过 -o use_memdup 或客户端预分片,避免大对象挤占小对象内存不推荐存储接近 1MB 的对象。
避免频繁 set 大小变化的 key同一 key 反复 set 不同大小 value 会导致跨 slab 移动,产生垃圾尽量保持 value 大小稳定。

典型调优场景:若 stats slabs 显示 class 1(chunk_size=96)的 total_malloced=100MB 但 mem_requested=60MB,则内部碎片率达 40%,可尝试 -f 1.1 增加 class 密度。

7.3 监控工具(如 memcached-top、Prometheus + Exporter)

工具名称安装/使用方式用途说明注意事项
memcached-toppip install memcached-top
运行:memcached-top --host=127.0.0.1 --port=11211
实时终端监控,类似 top 命令显示命中率、连接数、item 数等动态指标;适合快速诊断。
Prometheus Exporter使用官方或社区 exporter(如 memcached_exporter
启动:memcached_exporter --memcached.address=localhost:11211
将 stats 指标暴露给 Prometheus 抓取需配合 Prometheus + Grafana 实现长期监控与告警。
Grafana Dashboard导入 ID 为 5035 的官方 Memcached dashboard可视化展示命中率、内存、evictions 等趋势需提前配置 Prometheus 数据源。
stats 命令脚本化编写 shell 脚本定期执行 echo stats | nc localhost 11211 并解析输出自定义监控逻辑,集成到 Zabbix/Nagios注意处理连接超时和格式变化。
mcrouter stats若使用 mcrouter,可通过其 /stats HTTP 接口获取聚合指标监控代理层性能与后端节点状态支持 JSON 输出,便于自动化。
日志分析启用 -v-vv 输出请求日志,结合 ELK 分析慢操作或异常模式适用于深度性能剖析生产环境慎用高 verbose 级别,影响性能。
netdata安装 netdata 后自动发现 Memcached 实例开箱即用的 Web 监控面板适合中小规模部署,资源占用低。

Exporter 关键指标示例(Prometheus):

  • memcached_commands_total{command="get"} → get 总次数
  • memcached_current_bytes → 当前内存使用
  • memcached_items_evicted_total → 累计驱逐数
  • memcached_current_connections → 当前连接数

第八章:典型应用场景与最佳实践

8.1 Web 应用会话缓存

操作/概念名称说明注意事项
会话存储原理将用户会话数据(如登录状态、权限)序列化后存入 Memcached,key 为 session_id替代文件或数据库存储,提升读写速度。
Key 设计session:{session_id},如 session:abc123xyz避免 key 冲突;建议加命名空间前缀。
过期时间设置与会话超时一致(如 30 分钟),通过 -m 控制内存,避免长期堆积必须设置 exptime,否则依赖 LRU 可能提前淘汰活跃会话。
存储内容用户 ID、角色、最后活动时间等轻量数据;避免存大对象单个 session 建议 < 10KB。
安全性Memcached 无认证,需部署在内网;session_id 需强随机(如 UUID)防止会话劫持;不可暴露 Memcached 到公网。
失效处理用户登出时主动 delete session:xxx;过期自动失效主动删除可立即释放资源。
故障影响Memcached 宕机 → 所有用户强制重新登录属于可接受降级(回源重建会话)。
适用框架示例PHP:session.save_handler = memcached
Node.js:express-session + connect-memjs
需配置客户端连接池和重试机制。

8.2 数据库查询结果缓存

操作/概念名称说明注意事项
缓存键设计使用 SQL 哈希或语义化 key,如 user:profile:1001query:md5(SELECT * FROM users WHERE id=1001)避免 SQL 注入影响 key;推荐语义化 key 更易管理。
缓存流程1. 应用查缓存
2. miss → 查 DB → set 缓存
3. hit → 直接返回
需处理 DB 查询失败时的缓存策略(如空值缓存)。
过期策略设置合理 TTL(如 5~60 秒),或结合业务事件主动失效高频更新表不宜缓存;静态数据可设长 TTL。
空结果缓存对 DB 返回空的结果也缓存(如 set notfound:user:9999 "" exptime=10防止缓存穿透;TTL 应较短(如 10 秒)。
更新一致性数据变更时同步删除或更新缓存(Cache-Aside 模式)Memcached 无事务,无法保证强一致;最终一致即可。
大结果集处理避免缓存 > 500KB 的结果;可分页缓存或仅缓存 ID 列表接近 1MB 限制易触发 SERVER_ERROR。
性能收益减少 80%+ 的重复 DB 查询,尤其适用于读多写少场景需监控命中率,低于 70% 需重新评估。
局限性不支持复杂查询(如模糊搜索、聚合)的缓存仅适用于主键或唯一索引查询。

8.3 分布式锁的替代方案讨论

方案名称实现方式在 Memcached 中的可行性注意事项
基于 add 的简单锁add lock_key 0 10 1,成功表示获取锁;处理完后 delete lock_key✅ 可行无自动续期;进程 crash 会导致死锁(依赖 exptime 释放)。
CAS 乐观锁先 gets 获取 CAS token,再 cas 更新✅ 可行(用于数据更新)不适用于互斥执行场景,仅用于数据版本控制。
Redlock(Redis 方案)多节点多数派加锁❌ 不可行Memcached 无内置集群,无法实现跨节点共识。
带续期的锁后台线程定期 replace 延长 exptime⚠️ 脆弱网络分区或 GC pause 可能导致锁失效。
锁持有者标识value 存放唯一标识(如 UUID),释放时校验✅ 推荐防止误删其他进程的锁。
适用场景低并发、短任务、允许偶尔失效的场景(如防重复提交)不适用于金融级强一致锁。
根本局限Memcached 无原子复合操作(如 Lua 脚本)、无持久化、无 Watch 机制分布式锁应优先考虑 Redis、ZooKeeper、etcd。

结论:Memcached 可实现”尽力而为”的轻量级锁,但不推荐用于关键业务互斥控制。

8.4 缓存穿透/雪崩/击穿的应对策略(在 Memcached 中的局限性)

问题类型定义Memcached 应对策略局限性
缓存穿透查询大量不存在的 key,请求直达 DB1. 空值缓存:对 DB 返回 null 的 key 缓存短 TTL(如 10 秒)
2. 布隆过滤器(应用层实现)
Memcached 本身无布隆过滤器;空值缓存增加内存压力。
缓存雪崩大量 key 同时过期,瞬间高并发打垮 DB1. 随机 TTL:基础 TTL + 随机偏移(如 3600 ± 300 秒)
2. 永不过期 + 后台更新(应用层维护)
Memcached 无自动后台更新机制;需应用自行实现。
缓存击穿热点 key 过期瞬间,大量并发请求争抢重建1. 互斥重建:首个线程重建,其余等待(需分布式锁)
2. 逻辑过期:value 中嵌入过期时间,异步更新
Memcached 无原子”get+set if miss”操作;互斥锁可靠性低(见 8.3)。
通用缓解措施• 限流(如令牌桶)
• 降级(返回默认值)
• 监控 evictions 和 miss rate
Memcached 本身不提供限流/降级能力,需应用层或网关实现。
根本缺陷Memcached 无以下能力:
• 自动过期回调
• 发布/订阅通知
• 持久化保障
相比 Redis,应对复杂缓存问题的能力显著受限。

最佳实践建议:

  • 对于高可靠缓存场景,优先选用 Redis;
  • 若使用 Memcached,必须在应用层实现完整的缓存治理逻辑;
  • 严格限制 Memcached 用于非关键、可降级、读密集型数据缓存。