Memcached 完全指南 / 第 10 章:通信协议
第 10 章:通信协议
10.1 协议总览
Memcached 支持三种协议:
| 协议 |
版本 |
状态 |
说明 |
| 文本协议 (ASCII) |
1.0+ |
稳定 |
人类可读,调试方便 |
| 二进制协议 (Binary) |
1.4+ |
稳定 |
效率更高,1.6+ 可能移除 |
| Meta 协议 |
1.6+ |
推荐 |
精简高效,功能最强 |
# 启动时指定协议
memcached -B auto # 自动检测(默认)
memcached -B ascii # 只支持文本协议
memcached -B binary # 只支持二进制协议
10.2 文本协议 (ASCII Protocol)
协议格式
请求格式:
<命令> <参数1> <参数2> ... <参数N>\r\n
[数据块]\r\n
响应格式:
<响应码> [数据长度]\r\n
[数据块]\r\n
行终止符: \r\n (CRLF)
命令分类
存储命令:
set <key> <flags> <exptime> <bytes> [noreply]\r\n
add <key> <flags> <exptime> <bytes> [noreply]\r\n
replace <key> <flags> <exptime> <bytes> [noreply]\r\n
append <key> <flags> <exptime> <bytes> [noreply]\r\n
prepend <key> <flags> <exptime> <bytes> [noreply]\r\n
cas <key> <flags> <exptime> <bytes> <cas_unique> [noreply]\r\n
检索命令:
get <key> [key ...]\r\n
gets <key> [key ...]\r\n
删除命令:
delete <key> [noreply]\r\n
计数命令:
incr <key> <value> [noreply]\r\n
decr <key> <value> [noreply]\r\n
管理命令:
flush_all [delay] [noreply]\r\n
version\r\n
verbosity <level> [noreply]\r\n
quit\r\n
统计命令:
stats [settings|items|slabs|sizes|conns|reset]\r\n
stats cachedump <slab_id> <limit>\r\n
完整交互示例
客户端 → 服务端:
set user:1001 3 3600 27\r\n
{"name":"Alice","age":30}\r\n
服务端 → 客户端:
STORED\r\n
客户端 → 服务端:
get user:1001 user:1002\r\n
服务端 → 客户端:
VALUE user:1001 3 27\r\n
{"name":"Alice","age":30}\r\n
VALUE user:1002 3 25\r\n
{"name":"Bob","age":25}\r\n
END\r\n
10.3 二进制协议 (Binary Protocol)
协议头
请求包结构 (24 字节头部 + Body):
Byte 0: Magic (0x80 = Request)
Byte 1: Opcode (命令码)
Byte 2-3: Key 长度 (网络字节序)
Byte 4: Extras 长度
Byte 5: 数据类型 (0x00 = Raw Bytes)
Byte 6-7: 保留/状态码
Byte 8-11: Body 长度 (Key + Extras + Value)
Byte 12-15: Opaque (客户端自定义,原样返回)
Byte 16-23: CAS (8字节)
响应包结构 (24 字节头部 + Body):
Byte 0: Magic (0x81 = Response)
Byte 1: Opcode
Byte 2-3: Key 长度
Byte 4: Extras 长度
Byte 5: 数据类型
Byte 6-7: 状态码
Byte 8-11: Body 长度
Byte 12-15: Opaque
Byte 16-23: CAS
命令码 (Opcode)
| Opcode |
名称 |
说明 |
| 0x00 |
GET |
获取 |
| 0x01 |
SET |
设置 |
| 0x02 |
ADD |
添加 |
| 0x03 |
REPLACE |
替换 |
| 0x04 |
DELETE |
删除 |
| 0x05 |
INCREMENT |
自增 |
| 0x06 |
DECREMENT |
自减 |
| 0x07 |
QUIT |
退出 |
| 0x08 |
FLUSH |
清空 |
| 0x09 |
GETQ |
安静获取 |
| 0x0A |
NO-OP |
空操作 |
| 0x0B |
VERSION |
版本 |
| 0x0C |
GETK |
获取 Key |
| 0x0D |
GETKQ |
安静获取 Key |
| 0x0E |
APPEND |
追加 |
| 0x0F |
PREPEND |
前置 |
| 0x10 |
STAT |
统计 |
| 0x11 |
SETQ |
安静设置 |
| 0x12 |
ADDQ |
安静添加 |
| 0x13 |
REPLACEQ |
安静替换 |
| 0x14 |
DELETEQ |
安静删除 |
| 0x15 |
INCREMENTQ |
安静自增 |
| 0x16 |
DECREMENTQ |
安静自减 |
| 0x17 |
QUITQ |
安静退出 |
| 0x18 |
FLUSHQ |
安静清空 |
| 0x19 |
APPENDQ |
安静追加 |
| 0x1A |
PREPENDQ |
安静前置 |
状态码
| 状态码 |
名称 |
说明 |
| 0x0000 |
SUCCESS |
成功 |
| 0x0001 |
KEY_ENOENT |
Key 不存在 |
| 0x0002 |
KEY_EEXISTS |
Key 已存在(CAS 失败) |
| 0x0003 |
E2BIG |
Value 过大 |
| 0x0004 |
EINVAL |
无效参数 |
| 0x0005 |
NOT_STORED |
未存储 |
| 0x0006 |
DELTA_BADVAL |
自增值非法 |
| 0x0007 |
AUTH_ERROR |
认证错误 |
| 0x0008 |
AUTH_CONTINUE |
认证继续 |
| 0x0020 |
AUTH_REQUIRED |
需要认证 |
| 0x0081 |
UNKNOWN_COMMAND |
未知命令 |
| 0x0082 |
ENOMEM |
内存不足 |
二进制 vs 文本协议性能
| 维度 |
文本协议 |
二进制协议 |
| 解析速度 |
较慢(字符串解析) |
较快(固定偏移) |
| 网络效率 |
较差(数值转文本) |
较好(原生二进制) |
| 可调试性 |
极好(人类可读) |
差(需工具) |
| 安静命令 |
不支持 |
支持(Q 后缀) |
| Opaque |
不支持 |
支持 |
| 批量操作 |
批量 get |
批量 get/getq |
Meta 协议是 Memcached 1.6 引入的新一代协议,旨在替代文本和二进制协议。
设计目标
Meta 协议设计原则:
1. 一条命令完成多项操作(减少往返)
2. 精简的命令格式(减少网络数据量)
3. 向后兼容文本协议
4. 支持更丰富的元数据操作
ms <key> <datalen> [flags...]\r\n ← Meta Set
<data>\r\n
mg <key> [flags...]\r\n ← Meta Get
md <key> [flags...]\r\n ← Meta Delete
ma <key> [flags...]\r\n ← Meta Arithmetic
| 标志 |
说明 |
示例 |
T<ttl> |
设置 TTL |
T3600 = 3600 秒 |
F<flags> |
客户端标志 |
F3 |
I<cas> |
CAS 唯一值(条件写入) |
I123456789 |
N |
noreply |
N |
c |
返回 CAS 值 |
c |
k |
返回 Key |
k |
q |
安静模式(不返回 STORED) |
q |
O<opaque> |
Opaque 标记 |
O1234 |
M<mode> |
模式(S=set, A=add, R=replace, E=cas, A=append, P=prepend) |
MA |
| 标志 |
说明 |
示例 |
v |
返回 Value |
v |
k |
返回 Key |
k |
f |
返回 flags |
f |
s |
返回大小 |
s |
c |
返回 CAS |
c |
T |
返回剩余 TTL |
T |
h |
命中检查(不返回 Value) |
h |
l |
返回 LRU 位置 |
l |
t |
返回 Item 类型 |
t |
N<ttl> |
更新 TTL(滑动过期) |
N3600 |
G<token> |
通过 Token 获取指定字节 |
G0-100 |
# 存储(带 TTL,返回 CAS)
ms user:1001 27 T3600 c\r\n
{"name":"Alice","age":30}\r\n
→ ST 123456789\r\n
# 获取(返回 Value、CAS、TTL、大小)
mg user:1001 v c T s\r\n
→ VA 27 c 123456789 T 3500 s 27\r\n
→ {"name":"Alice","age":30}\r\n
# 仅检查存在性
mg user:1001 h\r\n
→ HD\r\n ← 存在
mg user:9999 h\r\n
→ NF\r\n ← 不存在
# 条件删除(CAS 匹配)
md user:1001 E123456789\r\n
→ DE\r\n ← 删除成功
# 原子自增(不存在则创建)
ma counter N1 J0 T3600 c\r\n
→ VA 1 c 987654321\r\n
→ 1\r\n
# 批量获取(安静 + 批量)
mg key1 v q\r\n
→ VA 5\r\nhello\r\n
mg key2 v q\r\n
→ VA 5\r\nworld\r\n
mg key3 h q\r\n
→ HD\r\n
mg key4 h q\r\n
→ EN\r\n ← 所有命令已发送
10.5 libmemcached
libmemcached 是最完善的 C/C++ Memcached 客户端库。
安装
# Ubuntu/Debian
sudo apt-get install -y libmemcached-dev
# CentOS/RHEL
sudo yum install -y libmemcached-devel
# macOS
brew install libmemcached
# 源码编译
git clone https://github.com/memcached/libmemcached.git
cd libmemcached
./configure --enable-sasl
make -j$(nproc)
sudo make install
C 语言示例
#include <stdio.h>
#include <string.h>
#include <libmemcached/memcached.h>
int main() {
// 创建客户端实例
memcached_st *mc = memcached_create(NULL);
// 配置服务器
memcached_server_st *servers = memcached_servers_parse("mc1:11211,mc2:11211");
memcached_server_push(mc, servers);
memcached_server_list_free(servers);
// 配置一致性哈希
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_DISTRIBUTION,
MEMCACHED_DISTRIBUTION_CONSISTENT);
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_HASH,
MEMCACHED_HASH_MURMUR);
// SET 操作
memcached_return_t rc;
rc = memcached_set(mc, "user:1001", 9,
"{\"name\":\"Alice\"}", 18,
(time_t)3600, (uint32_t)0);
if (rc == MEMCACHED_SUCCESS) {
printf("SET 成功\n");
}
// GET 操作
size_t value_length;
uint32_t flags;
char *value = memcached_get(mc, "user:1001", 9,
&value_length, &flags, &rc);
if (rc == MEMCACHED_SUCCESS) {
printf("GET: %.*s\n", (int)value_length, value);
free(value);
}
// 批量 GET
const char *keys[] = {"user:1001", "user:1002", "user:1003"};
size_t key_lengths[] = {9, 9, 9};
rc = memcached_mget(mc, keys, key_lengths, 3);
char return_key[MEMCACHED_MAX_KEY];
size_t return_key_length;
while ((value = memcached_fetch(mc, return_key, &return_key_length,
&value_length, &flags, &rc)) != NULL) {
printf("KEY: %s, VALUE: %.*s\n",
return_key, (int)value_length, value);
free(value);
}
// CAS 操作
uint64_t cas_value;
value = memcached_get_by_key(mc, NULL, 0, "balance", 7,
&value_length, &flags, &cas_value, &rc);
// 使用 CAS 更新
rc = memcached_cas(mc, "balance", 7, "200", 3,
(time_t)0, (uint32_t)0, cas_value);
if (rc == MEMCACHED_SUCCESS) {
printf("CAS 更新成功\n");
} else if (rc == MEMCACHED_DATA_EXISTS) {
printf("CAS 冲突,需要重试\n");
}
// 清理
memcached_free(mc);
return 0;
}
# 编译
gcc -o mc_example mc_example.c -lmemcached
./mc_example
libmemcached 行为配置
// 常用行为配置
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1); // 非阻塞 I/O
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1); // 禁用 Nagle
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE, 1024*1024); // 发送缓冲区
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE, 1024*1024); // 接收缓冲区
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 1000); // 连接超时(ms)
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, 1000); // 轮询超时(ms)
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 5); // 重试超时(s)
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, 3); // 失败阈值
memcached_behavior_set(mc, MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS, 1); // 自动移除故障节点
memcached CLI 工具
libmemcached 自带的命令行工具:
# 设置
memcset --servers=localhost:11211 --key=test --value=hello --expire=60
# 获取
memcget --servers=localhost:11211 --key=test
# 删除
memcdelete --servers=localhost:11211 --key=test
# 批量操作
memcslap --servers=localhost:11211 --concurrency=50 --initial-load=1000
# 性能测试
memcping --servers=localhost:11211
10.6 协议选型建议
选择协议:
需要调试 / 开发环境?
└── 文本协议 ✓
需要最高性能 / 生产环境?
└── Meta 协议(1.6+)✓
需要兼容旧客户端?
└── 二进制协议 ✓
不确定?
└── 文本协议(最通用)✓
扩展阅读
小结
| 要点 |
内容 |
| 文本协议 |
人类可读,调试方便,通用性最强 |
| 二进制协议 |
效率更高,支持安静命令和 Opaque |
| Meta 协议 |
1.6+ 推荐,一条命令完成多项操作 |
| libmemcached |
最完善的 C/C++ 客户端库,内置一致性哈希 |
| noreply |
批量写入时使用 noreply 减少往返 |