Memcached set 命令详解(2025 版)
set 是 Memcached 最核心、最常用 的写命令,用于 存储或覆盖 一个 Key-Value 数据项。
1. 基本语法
set <key> <flags> <exptime> <bytes> [noreply]\r\n
<value>\r\n
| 参数 | 说明 |
|---|---|
<key> | 键名(≤ 250 字节,不能含空格或控制字符) |
<flags> | 客户端自定义标志(16 位整数,0~65535) |
<exptime> | 过期时间(秒)0 = 永不过期>0 = 相对时间≤ 2592000 (30天) = 相对时间> 2592000 = 绝对 Unix 时间戳 |
<bytes> | Value 的字节数(不含 \r\n) |
[noreply] | 可选,不等待服务端响应(提升性能) |
<value> | 实际数据(二进制安全) |
响应:
STORED\r\n→ 成功NOT_STORED\r\n→ 失败(内存不足等)
2. 实际操作示例(telnet)
telnet 127.0.0.1 11211
示例 1:基础 set(永不过期)
set user:1001 0 0 9
zhangsan
STORED
user:1001:键0:flags(可用于版本控制)0:永不过期9:value 长度 9 字节(zhangsan是 8 字节 + 1 个换行?注意:实际输入时不含换行)
注意:
<bytes>是 value 内容的字节数,不包括最后的\r\n
示例 2:设置 5 分钟过期
set session:abc123 8 300 36
{"uid":1001,"login_time":1739431200}
STORED
exptime=300→ 5 分钟后过期flags=8→ 自定义标记(例如表示 JSON)
示例 3:noreply 异步写入(高并发推荐)
set counter:hits 0 0 1 noreply
1
# 没有 STORED 响应,直接继续
3. 客户端使用 set
Python(pymemcache)
from pymemcache.client.base import Client
client = Client(('127.0.0.1', 11211))
# 基础 set
client.set('user:1', '李四', expire=3600) # 1小时过期
# 复杂对象(自动序列化)
import json
user = {"id": 1, "name": "王五", "roles": ["admin"]}
client.set('user:1', json.dumps(user), expire=1800)
# noreply(异步)
client.set('log:event', 'click', noreply=True)
PHP
$mc = new Memcached();
$mc->addServer('127.0.0.1', 11211);
$mc->set('key1', 'value1', 3600); // 1小时
$mc->set('key2', ['a' => 1], time() + 300); // 绝对时间
$mc->set('key3', 'async', 0, true); // noreply = true
Java(XMemcached)
client.set("key1", 3600, "hello"); // 1小时
client.setWithNoReply("key2", 0, "async"); // 异步
4. set vs add vs replace
| 命令 | 行为 |
|---|---|
set | 存在则覆盖,不存在则创建(最常用) |
add | 仅当 key 不存在时创建,存在则失败 |
replace | 仅当 key 存在时覆盖,不存在则失败 |
# set:无论是否存在都成功
set key1 0 0 5
hello
STORED
# add:key 已存在 → 失败
add key1 0 0 3
bye
NOT_STORED
# replace:key 不存在 → 失败
replace key999 0 0 3
abc
NOT_STORED
5. 高级用法
5.1 使用 flags 做版本控制(CAS 替代)
# 第一次写入
set user:1 1 0 8 # flags=1 表示版本1
zhangsan
STORED
# 更新时检查 flags
get user:1
VALUE user:1 1 8
zhangsan
END
# 只有 flags 匹配才更新(模拟乐观锁)
# 实际需配合 get + set 逻辑
更推荐使用 CAS(check and set) 命令实现乐观锁
5.2 大 Value 存储(≤ 1MB)
set page:home 0 3600 102400
<100KB 的 HTML 内容...>
STORED
默认最大 1MB,可用
-I 2m启动参数调整
5.3 批量 set(客户端实现)
# Python 批量
data = {
'user:1': '张三',
'user:2': '李四',
'user:3': '王五'
}
for k, v in data.items():
client.set(k, v, expire=3600)
Memcached 原生无批量 set,需客户端循环
6. 过期时间 exptime 详解
| 值 | 含义 |
|---|---|
0 | 永不过期 |
1 ~ 2592000 | 相对当前时间 N 秒后过期 |
> 2592000 | 绝对 Unix 时间戳(秒) |
# 过期时间:2025-12-01 00:00:00
set event:2025 0 1767225600 5
hello
STORED
7. 常见错误
| 错误 | 原因 | 解决 |
|---|---|---|
CLIENT_ERROR bad command line format | 参数格式错误 | 检查空格、换行 |
SERVER_ERROR out of memory | 内存不足 | 增加 -m 或启用 LRU |
NOT_STORED | add 时 key 已存在 | 改用 set |
| 数据被提前删除 | 内存压力导致 LRU 淘汰 | 增加内存或缩短过期时间 |
8. 最佳实践
| 建议 | 说明 |
|---|---|
优先使用 set | 简单可靠 |
| 热点数据设短过期 | 5~30 分钟 |
| 冷数据长过期 + 手动失效 | delete 主动清除 |
| 使用 noreply 提升吞吐 | 高并发写入 |
| key 命名规范 | 模块:业务:ID 如 user:profile:1001 |
| 避免大 key/value | >100KB 建议用 Redis 或拆分 |
9. 调试命令
# 查看 key 是否存在
get user:1
# 查看统计
echo "stats items" | nc 127.0.0.1 11211
echo "stats slabs" | nc 127.0.0.1 11211
# 清理(慎用)
flush_all
小结:set 命令速查
set key flags exptime bytes [noreply]
└─> STORED
| 项目 | 推荐值 |
|---|---|
flags | 0 或业务标记(如 1=JSON) |
exptime | 300 ~ 3600(5~60分钟) |
bytes | < 100 * 1024(< 100KB) |
noreply | 高并发时启用 |
练习建议:
- 用 telnet 手动
set一个用户数据 - 用 Python 实现「登录缓存」:
set session:{token} {uid} 1800 - 模拟缓存更新:
get→ 修改 →set
需要 CAS 乐观锁、incr/decr 计数器、批量操作优化?继续问我!