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

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

10.4 Meta 协议 (Meta Protocol)

Meta 协议是 Memcached 1.6 引入的新一代协议,旨在替代文本和二进制协议。

设计目标

Meta 协议设计原则:
1. 一条命令完成多项操作(减少往返)
2. 精简的命令格式(减少网络数据量)
3. 向后兼容文本协议
4. 支持更丰富的元数据操作

Meta 命令格式

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

Meta Set 标志

标志 说明 示例
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

Meta Get 标志

标志 说明 示例
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

Meta 协议交互示例

# 存储(带 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 减少往返