Memcached基础语法 #

一、键命名规范 #

1.1 键的基本规则 #

text
键的规则:

1. 长度限制:最大250字节
2. 字符限制:不能包含空格和控制字符
3. 命名建议:使用有意义的前缀和分隔符

示例:
✓ user:1001
✓ session:abc123
✓ page:home:header
✓ api:weather:beijing
✗ key with spaces
✗ key\nwith\nnewlines

1.2 命名空间设计 #

text
命名空间设计模式:

<namespace>:<type>:<id>

示例:
user:info:1001          # 用户信息
user:profile:1001       # 用户资料
session:web:abc123      # Web会话
session:api:xyz789      # API会话
cache:db:users:1001     # 数据库缓存
page:html:home          # 页面缓存
api:response:weather    # API响应缓存

1.3 键命名最佳实践 #

text
推荐做法:

1. 使用统一前缀
   app:user:1001
   app:product:2001

2. 使用层级结构
   user:1001:profile
   user:1001:settings

3. 包含过期信息(可选)
   cache:5min:api:data
   cache:1h:page:home

4. 使用哈希缩短
   长键名 → MD5/SHA1哈希
   user:very:long:path:to:data → user:md5hash

二、数据类型 #

2.1 支持的数据类型 #

text
Memcached只支持一种数据类型:字符串

但可以存储:
- 文本数据
- JSON数据
- 序列化对象
- 二进制数据
- 数字(作为字符串)

示例:
set key1 0 0 5
hello        # 文本

set key2 0 0 27
{"name":"John","age":25}  # JSON

set key3 0 0 3
100        # 数字(字符串形式)

2.2 Flags标志 #

text
Flags是一个32位的整数,用于标识数据类型:

常用Flags值:
0      - 默认(字符串)
1      - 序列化对象
2      - JSON
3      - 压缩数据
4      - 二进制数据

示例:
# 存储JSON数据
set user:1001 2 3600 27
{"name":"John","age":25}

# 客户端可以根据Flags解析数据类型

2.3 数据大小限制 #

text
数据大小限制:

默认最大:1MB
可配置最大:128MB(需要重新编译)

建议:
- 单个Item不超过1MB
- 大数据分片存储
- 使用压缩减少大小

三、命令格式 #

3.1 文本协议格式 #

text
基本格式:
<command> <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

参数说明:
command  - 命令名称
key      - 键名
flags    - 标志位(32位整数)
exptime  - 过期时间(秒)
bytes    - 数据字节数
noreply  - 可选,不返回响应
data     - 数据内容

示例:
set user:1001 0 3600 23
{"name":"John","age":25}

3.2 存储命令 #

text
存储命令列表:

set      - 存储,存在则覆盖
add      - 添加,存在则失败
replace  - 替换,不存在则失败
append   - 追加到末尾
prepend  - 添加到开头
cas      - 检查并设置

示例:
# set命令
set key 0 3600 5
hello
STORED

# add命令
add key 0 3600 5
world
NOT_STORED  # 已存在,存储失败

# replace命令
replace key 0 3600 5
world
STORED

3.3 读取命令 #

text
读取命令列表:

get      - 获取数据
gets     - 获取数据和CAS ID

示例:
# get命令
get key
VALUE key 0 5
hello
END

# gets命令
gets key
VALUE key 0 5 123
hello
END
# 123是CAS ID

3.4 删除命令 #

text
删除命令:

delete <key> [noreply]

示例:
delete key
DELETED

delete notexist
NOT_FOUND

3.5 计数器命令 #

text
计数器命令:

incr <key> <value> [noreply]
decr <key> <value> [noreply]

示例:
# 初始化计数器
set counter 0 0 1
0
STORED

# 递增
incr counter 1
1

incr counter 5
6

# 递减
decr counter 2
4

四、过期时间 #

4.1 过期时间格式 #

text
过期时间格式:

exptime = 0        - 永不过期
exptime > 0        - 相对时间(秒)
exptime < 0        - Unix时间戳

示例:
# 1小时后过期
set key 0 3600 5
hello

# 永不过期
set key 0 0 5
hello

# Unix时间戳过期(2024-01-01 00:00:00)
set key 0 1704067200 5
hello

4.2 过期时间计算 #

text
过期时间计算规则:

1. Unix时间戳(小于30天)
   exptime < 60*60*24*30
   解释为相对时间(秒)

2. Unix时间戳(大于等于30天)
   exptime >= 60*60*24*30
   解释为绝对时间(Unix时间戳)

示例:
# 30天 = 2592000秒
# 2591999秒 → 相对时间
# 2592000秒 → 绝对时间

# 1小时后过期
set key 0 3600 5
hello

# 指定日期过期
set key 0 1704067200 5
hello

4.3 过期策略 #

text
Memcached过期策略:

1. 惰性删除
   - 访问时检查是否过期
   - 过期则删除并返回不存在

2. LRU淘汰
   - 内存满时淘汰最近最少使用的数据
   - 不区分是否过期

3. 后台清理
   - 不主动清理过期数据
   - 依赖惰性删除和LRU

五、响应状态 #

5.1 存储命令响应 #

text
存储命令响应状态:

STORED       - 存储成功
NOT_STORED   - 存储失败(add/replace条件不满足)
EXISTS       - cas命令时,CAS ID不匹配
NOT_FOUND    - cas命令时,键不存在

示例:
set key 0 0 5
hello
STORED

add key 0 0 5
world
NOT_STORED

cas key 0 0 5 999
hello
EXISTS

5.2 读取命令响应 #

text
读取命令响应格式:

VALUE <key> <flags> <bytes> [<cas unique>]
<data block>
END

示例:
get key
VALUE key 0 5
hello
END

gets key
VALUE key 0 5 123
hello
END

get notexist
END

5.3 删除命令响应 #

text
删除命令响应状态:

DELETED      - 删除成功
NOT_FOUND    - 键不存在

示例:
delete key
DELETED

delete notexist
NOT_FOUND

5.4 计数器命令响应 #

text
计数器命令响应:

成功:返回新值
失败:NOT_FOUND(键不存在)
      ERROR(值不是数字)

示例:
incr counter 1
5

incr notexist 1
NOT_FOUND

set str 0 0 5
hello
STORED
incr str 1
ERROR

六、二进制协议 #

6.1 二进制协议优势 #

text
二进制协议优势:

1. 更高效
   - 二进制格式,解析更快
   - 更少的字符串处理

2. 更安全
   - 不需要转义特殊字符
   - 支持二进制键名

3. 功能更全
   - 支持更多操作
   - 支持SASL认证

6.2 二进制协议格式 #

text
请求头格式(24字节):

Byte/     0       |       1       |       2       |       3       |
   /              |               |               |               |
  |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
  +---------------+---------------+---------------+---------------+
  | Magic         | Opcode        | Key length                    |
  +---------------+---------------+---------------+---------------+
  | Extras length | Data type     | vbucket id                    |
  +---------------+---------------+---------------+---------------+
  | Total body length                                             |
  +---------------+---------------+---------------+---------------+
  | Opaque                                                        |
  +---------------+---------------+---------------+---------------+
  | CAS                                                           |
  +---------------+---------------+---------------+---------------+

响应头格式(24字节):
  | Magic         | Opcode        | Key length                    |
  +---------------+---------------+---------------+---------------+
  | Extras length | Data type     | Status                        |
  +---------------+---------------+---------------+---------------+
  | Total body length                                             |
  +---------------+---------------+---------------+---------------+
  | Opaque                                                        |
  +---------------+---------------+---------------+---------------+
  | CAS                                                           |
  +---------------+---------------+---------------+---------------+

七、命令规范 #

7.1 命令大小写 #

text
命令不区分大小写:

set = SET = Set
get = GET = Get

建议:统一使用小写

7.2 空格分隔 #

text
命令参数使用空格分隔:

set key flags exptime bytes

注意:
- 多个空格视为一个
- 数据块中的空格保留

7.3 换行符 #

text
换行符规范:

命令行:\r\n
数据块:\r\n

注意:
- 不同系统可能只有\n
- 建议统一使用\r\n

八、错误处理 #

8.1 错误响应 #

text
错误响应类型:

ERROR       - 命令不存在
CLIENT_ERROR <error> - 客户端错误
SERVER_ERROR <error> - 服务器错误

示例:
unknowncommand
ERROR

set key 0 0 abc
CLIENT_ERROR bad command line format

set key 0 0 999999999999999999999999999
SERVER_ERROR out of memory

8.2 常见错误 #

text
常见错误及解决:

1. CLIENT_ERROR bad command line format
   原因:命令格式错误
   解决:检查命令语法

2. CLIENT_ERROR bad data chunk
   原因:数据长度不匹配
   解决:检查bytes参数

3. SERVER_ERROR out of memory
   原因:内存不足
   解决:增加内存或清理数据

4. SERVER_ERROR object too large for cache
   原因:数据超过最大限制
   解决:减小数据大小或增大配置

九、最佳实践 #

9.1 键命名规范 #

text
键命名规范:

1. 使用有意义的前缀
   user:1001
   product:2001

2. 使用分隔符
   user:1001:profile
   user:1001:settings

3. 避免特殊字符
   ✓ user_1001
   ✗ user-1001 (可能引起歧义)

4. 控制长度
   键名不要太长,影响性能

9.2 数据序列化 #

text
数据序列化建议:

1. JSON格式
   优点:可读性好,跨语言
   缺点:体积较大

2. MessagePack
   优点:体积小,速度快
   缺点:需要额外库

3. Protobuf
   优点:体积最小
   缺点:需要定义schema

示例:
# JSON
set user:1001 0 3600 27
{"name":"John","age":25}

# MessagePack(二进制)
set user:1001 0 3600 18
<binary data>

9.3 过期时间设置 #

text
过期时间设置建议:

1. 根据数据更新频率设置
   - 静态数据:较长过期时间
   - 动态数据:较短过期时间

2. 避免缓存雪崩
   - 过期时间加随机值
   - base_time + random(0, 300)

3. 预热缓存
   - 系统启动时加载热点数据
   - 避免大量请求同时击穿

示例:
# 1小时过期,加随机值
exptime = 3600 + random(0, 300)

十、总结 #

Memcached语法要点:

要点 说明
键长度 最大250字节
数据大小 默认最大1MB
数据类型 仅字符串
过期时间 0=永不过期
协议 文本/二进制

下一步,让我们学习Memcached CLI的使用!

最后更新:2026-03-27