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. 逐步上线,监控系统表现