Skip to content

Memcached二进制协议 ​

协议结构 ​

1. 通用消息头 ​

二进制协议的所有消息都以一个24字节的固定头开始:

字段偏移大小类型说明
Magic01uint8_t消息类型标识:请求=0x80,响应=0x81
Opcode11uint8_t命令操作码
Key Length22uint16_t键的长度(网络字节序)
Extra Length41uint8_t额外数据的长度
Data Type51uint8_t数据类型,当前固定为0x00
Reserved62uint16_t保留字段,必须为0
Total Body Length84uint32_t总数据长度(网络字节序)
Opaque124uint32_t请求标识,响应中会原样返回
CAS168uint64_t数据版本号,用于CAS操作

2. 消息体结构 ​

消息体紧跟在消息头之后,结构如下:

[额外数据] [键] [值]
  • 额外数据:长度由Extra Length字段指定
  • 键:长度由Key Length字段指定
  • 值:长度 = Total Body Length - Extra Length - Key Length

命令操作码 ​

1. 核心命令 ​

操作码十六进制命令说明
GET0x00Get获取单个键
SET0x01Set设置键值对
ADD0x02Add仅当键不存在时设置
REPLACE0x03Replace仅当键存在时设置
DELETE0x04Delete删除键
INCREMENT0x05Increment递增数值
DECREMENT0x06Decrement递减数值
QUIT0x07Quit关闭连接
FLUSH0x08Flush清空缓存
GETQ0x09Get Quiet安静模式获取,无响应
NOOP0x0aNoop无操作,用于心跳检测
VERSION0x0bVersion获取版本信息
GETK0x0cGet with Key获取键值对并返回键
GETKQ0x0dGet with Key Quiet安静模式获取并返回键
APPEND0x0eAppend追加数据到值末尾
PREPEND0x0fPrependprepend数据到值开头

2. 扩展命令 ​

操作码十六进制命令说明
STAT0x10Stats获取统计信息
SETQ0x11Set Quiet安静模式设置,无响应
ADDQ0x12Add Quiet安静模式添加,无响应
REPLACEQ0x13Replace Quiet安静模式替换,无响应
DELETEQ0x14Delete Quiet安静模式删除,无响应
INCREMENTQ0x15Increment Quiet安静模式递增,无响应
DECREMENTQ0x16Decrement Quiet安静模式递减,无响应
QUITQ0x17Quit Quiet安静模式退出,无响应
FLUSHQ0x18Flush Quiet安静模式清空,无响应
APPENDQ0x19Append Quiet安静模式追加,无响应
PREPENDQ0x1aPrepend Quiet安静模式 prepend,无响应
TOUCH0x1cTouch更新键的过期时间
GAUGE0x21Gauge设置数值(类似SET)
GAUGEQ0x22Gauge Quiet安静模式设置数值,无响应

响应状态码 ​

状态码十六进制描述ASCII等价
SUCCESS0x00操作成功-
KEY_NOT_FOUND0x01键不存在NOT_FOUND
KEY_EXISTS0x02键已存在EXISTS
VALUE_TOO_LARGE0x03值过大VALUE
INVALID_ARGUMENTS0x04参数无效ERROR
ITEM_NOT_STORED0x05数据未存储NOT_STORED
INCR_DECR_ON_NON_NUMERIC0x06对非数值进行增减操作CLIENT_ERROR
VBUCKET_BELONGS_TO_ANOTHER_SERVER0x07桶属于其他服务器-
AUTHENTICATION_ERROR0x20认证错误AUTH ERROR
AUTHENTICATION_CONTINUE0x21认证继续AUTH CONTINUE
UNKNOWN_COMMAND0x81未知命令ERROR
OUT_OF_MEMORY0x82内存不足-

命令示例 ​

1. SET命令示例 ​

请求格式:

字段值
Magic0x80
Opcode0x01 (SET)
Key Length0x0003 (3)
Extra Length0x08 (8)
Data Type0x00
Total Body Length0x0000000B (11)
Opaque0x00000001 (请求标识)
CAS0x0000000000000000 (无)
额外数据[过期时间(4字节)][标志(4字节)]
键"key"
值"value"

二进制表示:

80 01 00 03 08 00 00 00 00 00 00 0B 00 00 00 01 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 6B 65 79 76 61 6C 75 65

响应格式:

字段值
Magic0x81
Opcode0x01 (SET)
Key Length0x0000 (0)
Extra Length0x00 (0)
Data Type0x00
Status0x0000 (SUCCESS)
Total Body Length0x00000000 (0)
Opaque0x00000001 (与请求相同)
CAS0x0000000000000001 (新的CAS值)

二进制表示:

81 01 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 01

2. GET命令示例 ​

请求格式:

字段值
Magic0x80
Opcode0x00 (GET)
Key Length0x0003 (3)
Extra Length0x00 (0)
Data Type0x00
Total Body Length0x00000003 (3)
Opaque0x00000002 (请求标识)
CAS0x0000000000000000 (无)
键"key"

二进制表示:

80 00 00 03 00 00 00 00 00 00 00 03 00 00 00 02 00 00 00 00 00 00 00 00
6B 65 79

响应格式:

字段值
Magic0x81
Opcode0x00 (GET)
Key Length0x0000 (0)
Extra Length0x04 (4)
Data Type0x00
Status0x0000 (SUCCESS)
Total Body Length0x00000009 (9)
Opaque0x00000002 (与请求相同)
CAS0x0000000000000001 (当前CAS值)
额外数据[标志(4字节)]
值"value"

二进制表示:

81 00 00 00 04 00 00 00 00 00 00 09 00 00 00 02 00 00 00 00 00 00 00 01
00 00 00 00 76 61 6C 75 65

性能优势 ​

相比ASCII协议,二进制协议具有以下性能优势:

  1. 固定长度头:减少了解析开销
  2. 高效的错误处理:使用状态码替代字符串错误信息
  3. 更紧凑的表示:减少了网络传输字节数
  4. 更好的类型安全:使用二进制数据类型,避免了字符串转换
  5. 支持更多命令:提供了更丰富的命令集
  6. 安静模式:支持无响应的命令,提高了吞吐量

客户端开发建议 ​

1. 连接管理 ​

  • 使用连接池管理TCP连接
  • 实现连接超时和重试机制
  • 支持TCP_NODELAY选项,减少延迟

2. 命令批处理 ​

  • 支持命令批处理,减少网络往返次数
  • 合理使用安静模式命令
  • 注意命令顺序和依赖关系

3. 错误处理 ​

  • 正确处理各种响应状态码
  • 实现适当的重试逻辑
  • 监控和记录错误情况

4. 性能优化 ​

  • 使用高效的序列化/反序列化库
  • 合理设置缓冲区大小
  • 优化键的设计,减少键长度
  • 避免频繁的小命令,使用批处理

二进制协议vs ASCII协议 ​

特性二进制协议ASCII协议
效率高中
错误处理结构化状态码字符串错误信息
命令集丰富基础
扩展性好差
调试友好差好
客户端支持广泛非常广泛
网络开销小大

工具和库 ​

1. 客户端库 ​

语言支持二进制协议的库
JavaSpyMemcached, Xmemcached
Pythonpymemcache, python-memcached2
PHPphp-memcached (扩展名)
C/C++libmemcached, memcached-client-library
Gogomemcache, memcache
Node.jsmemcached, mc

2. 调试工具 ​

  • telnet:可以手动发送二进制命令,但需要手动构造二进制数据
  • netcat:类似telnet,支持二进制数据传输
  • wireshark:可以捕获和分析二进制协议流量
  • memcached-tool:Memcached自带的工具,支持二进制协议

最佳实践 ​

1. 选择合适的协议 ​

  • 对于性能要求高的场景,使用二进制协议
  • 对于开发和调试阶段,使用ASCII协议
  • 考虑客户端库的支持情况

2. 合理设计键值 ​

  • 键长度不宜过长,建议不超过250字节
  • 值大小不宜过大,建议不超过1MB
  • 考虑数据压缩,减少网络传输量

3. 监控和调优 ​

  • 监控协议层面的指标,如命令吞吐量、响应时间
  • 分析网络流量,优化命令模式
  • 根据业务特点调整协议参数

4. 安全考虑 ​

  • 结合传输层加密(TLS/SSL)
  • 实现适当的认证机制
  • 限制命令访问权限

常见问题(FAQ) ​

Q1: 所有Memcached服务器都支持二进制协议吗? ​

A1: 是的,从Memcached 1.4版本开始,所有官方Memcached服务器都支持二进制协议。

Q2: 二进制协议比ASCII协议快多少? ​

A2: 具体性能提升取决于多种因素,如命令类型、数据大小、网络环境等。一般来说,二进制协议比ASCII协议快10%-30%。

Q3: 如何调试二进制协议? ​

A3: 可以使用以下工具:

  1. Wireshark:捕获和分析网络流量
  2. 客户端库的调试日志
  3. 自定义调试工具,如编写简单的客户端程序打印发送和接收的二进制数据

Q4: 二进制协议支持CAS操作吗? ​

A4: 是的,二进制协议完全支持CAS(Check and Set)操作,通过消息头中的CAS字段实现。

Q5: 如何从ASCII协议迁移到二进制协议? ​

A5: 迁移步骤:

  1. 评估当前客户端库是否支持二进制协议
  2. 如果不支持,选择支持二进制协议的客户端库
  3. 修改客户端代码,使用二进制协议API
  4. 进行充分的测试,确保功能和性能正常
  5. 逐步上线,监控系统表现