Memcached gets 命令详解(2025 版)
gets 是 get 的增强版,唯一区别是:
gets会额外返回一个cas_token(版本号),用于 CAS 乐观锁。
1. 核心区别:get vs gets
| 命令 | 返回 cas_token | 用途 |
|---|---|---|
get | 否 | 普通读取 |
gets | 是 | 并发更新、乐观锁 |
2. 语法
gets <key> [<key> ...]\r\n
支持 批量,最多 100 个 key(建议 ≤ 50)
3. 响应格式
VALUE <key> <flags> <bytes> <cas_token>\r\n
<value>\r\n
...
END\r\n
| 字段 | 说明 |
|---|---|
<cas_token> | 64 位整数,每次写入递增 |
END | 结束标志 |
4. telnet 完整示例
telnet 127.0.0.1 11211
# 1. 写入数据
set user:1001 0 0 8
zhangsan
STORED
# 2. gets 读取(带 cas_token)
gets user:1001
VALUE user:1001 0 8 1
zhangsan
END
1= 当前cas_token
# 3. 修改后再次 gets
replace user:1001 0 0 5
lisi
STORED
gets user:1001
VALUE user:1001 0 5 2
lisi
END
cas_token从1→2
5. 客户端使用 gets
Python(pymemcache)
from pymemcache.client.base import Client
client = Client(('127.0.0.1', 11211))
# 初始化
client.set('counter:likes', '100')
# gets 返回 (value, cas_token)
value, cas_token = client.gets('counter:likes')
print(value, cas_token) # b'100' 1
# 批量 gets
results = client.gets_many(['counter:likes', 'config:db'])
# {b'counter:likes': (b'100', 1), b'config:db': (b'127.0.0.1', 3)}
PHP
$mc = new Memcached();
$mc->addServer('127.0.0.1', 11211);
$mc->set('visits', 100);
// gets + cas
$result = $mc->get('visits', null, $cas_token);
echo "Value: $result, CAS: $cas_token\n";
// 批量 gets
$keys = ['visits', 'users'];
$cas_tokens = [];
$data = $mc->getMulti($keys, $cas_tokens);
print_r($data);
print_r($cas_tokens);
Java(XMemcached)
CASValue<String> casValue = client.gets("counter");
String value = casValue.getValue();
long cas = casValue.getCas();
System.out.println("Value: " + value + ", CAS: " + cas);
6. CAS 完整流程(gets + cas)
1. gets key
→ VALUE key flags bytes cas_token
→ 修改 value
2. cas key flags exptime bytes cas_token
→ STORED(成功)
→ EXISTS(冲突,需重试)
Python CAS 示例
def cas_increment(key, delta=1, max_retries=5):
for _ in range(max_retries):
result = client.gets(key)
if not result:
return False
value_bytes, cas_token = result
try:
old_value = int(value_bytes)
except:
return False
new_value = old_value + delta
if client.cas(key, str(new_value), cas_token):
return True # 成功
return False # 重试失败
7. 经典应用场景
| 场景 | 为什么用 gets |
|---|---|
| 点赞计数器 | 多线程并发 +1 |
| 库存扣减 | 防止超卖 |
| 购物车修改 | 并发添加商品 |
| 订单状态流转 | 待支付 → 已支付 |
| 配置热更新 | 多节点同步 |
8. cas_token 变化规则
| 操作 | cas_token 变化 |
|---|---|
set / add / replace | +1 |
append / prepend | +1 |
incr / decr | +1 |
delete | 失效 |
get / gets | 不变 |
9. 批量 gets 注意事项
# 推荐:批量 gets + 批量 cas
keys = ['user:1', 'user:2', 'user:3']
results = client.gets_many(keys) # {key: (value, cas)}
# 批量更新
for key, (value, cas) in results.items():
new_value = modify(value)
client.cas(key, new_value, cas)
避免:单个
gets+cas循环(性能差)
10. 性能与监控
echo "stats" | nc 127.0.0.1 11211
| 指标 | 说明 |
|---|---|
cmd_gets | gets 总次数 |
get_hits | 命中次数 |
cas_hits | cas 成功次数 |
cas_badval | cas 失败(版本冲突) |
高并发下
cas_badval增多 → 说明冲突严重
11. 常见错误
| 错误 | 原因 | 解决 |
|---|---|---|
EXISTS | cas 时版本不一致 | 重新 gets → 修改 → cas |
NOT_FOUND | key 不存在 | 初始化 |
cas_token 错误 | 使用了 get 的结果 | 必须用 gets |
12. 小结:gets 速查
gets key1 [key2 ...]
└─> VALUE key flags bytes cas_token
<value>
END
| 项目 | 推荐 |
|---|---|
| 用途 | 并发写场景 |
| 配合 | cas 命令 |
| 批量 | ≤ 50 个 key |
| 重试 | EXISTS 时循环 |
练习建议
- 用 telnet 实现 两个客户端并发点赞
- 用 Python 实现 库存扣减(支持 1000 并发)
- 实现 配置中心热更新(多节点同步)
需要 cas 命令详解、incr/decr 原子操作、delete 失效?继续问我!