Memcached 完全指南 / 第 4 章:核心命令
第 4 章:核心命令
4.1 协议概览
Memcached 支持两种协议:文本协议(ASCII)和二进制协议(Binary)。文本协议更易调试,二进制协议更高效。
本章以文本协议为主,所有命令均可通过 telnet 或 nc 直接执行。
# 连接 Memcached
nc localhost 11211
# 或
telnet localhost 11211
通用命令格式
| 类别 | 命令 | 说明 |
|---|---|---|
| 存储 | set, add, replace, append, prepend, cas | 写入/修改数据 |
| 检索 | get, gets, gat, gats | 读取数据 |
| 删除 | delete | 删除数据 |
| 计数 | incr, decr | 原子增减 |
| 统计 | stats, stats items, stats slabs | 查看统计信息 |
| 管理 | flush_all, version, quit, verbosity | 管理命令 |
4.2 存储命令
SET — 设置值
SET 是最常用的命令,无论 Key 是否存在都会写入。
格式:
set <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n
| 参数 | 说明 |
|---|---|
key | 缓存 Key,最长 250 字节 |
flags | 客户端标志,0-65535,Memcached 不使用,由客户端解释 |
exptime | 过期时间。0=永不过期;≤2592000(30天)=相对秒数;>2592000=Unix 时间戳 |
bytes | Value 的字节数(不含 \r\n) |
noreply | 可选,不返回响应 |
示例:
# 设置一个简单值
set mykey 0 60 5
hello
# STORED
# 使用 flags
set user:1001 3 3600 27
{"name":"Alice","age":30}
# STORED
# 设置不过期
set config 0 0 13
{"debug":true}
# STORED
# 使用 noreply(不等待响应)
set batch:1 0 60 4 noreply
data
# 写入过期时间戳
set session:abc 0 1735689600 4
test
# STORED
响应:
| 响应 | 含义 |
|---|---|
STORED | 成功存储 |
NOT_STORED | add/replace 条件不满足 |
EXISTS | CAS 操作时版本不匹配 |
NOT_FOUND | CAS 操作时 Key 不存在 |
ADD — 仅在 Key 不存在时设置
# Key 不存在,添加成功
add newkey 0 60 5
world
# STORED
# Key 已存在,添加失败
add newkey 0 60 5
other
# NOT_STORED
业务场景: 分布式锁、防止重复处理。
# 简单分布式锁
add lock:order:12345 0 30 1
1
# STORED — 获取锁成功
# 其他进程尝试获取
add lock:order:12345 0 30 1
1
# NOT_STORED — 获取锁失败
# 使用后删除
delete lock:order:12345
# DELETED
REPLACE — 仅在 Key 存在时替换
# 先设置
set counter 0 60 1
0
# STORED
# 替换成功
replace counter 0 60 1
1
# STORED
# 删除后替换失败
delete counter
# DELETED
replace counter 0 60 1
2
# NOT_STORED
APPEND — 追加数据到 Value 末尾
set log 0 0 5
hello
# STORED
append log 0 0 6
world
# STORED
get log
# VALUE log 0 11
# hello world
# END
业务场景: 日志拼接、消息队列。
PREPEND — 在 Value 前面插入数据
set html 0 0 15
</div></body>
# STORED
prepend html 0 0 32
<html><body><div>
# STORED
get html
# VALUE html 0 47
# <html><body><div></div></body>
# END
CAS — Check And Set(乐观锁)
CAS 提供乐观并发控制:只有当 Item 自上次读取后未被修改,才能更新。
格式:
cas <key> <flags> <exptime> <bytes> <cas_unique> [noreply]\r\n
<data block>\r\n
cas_unique 是通过 gets 命令获取的唯一版本号。
# 第一步:使用 gets 获取(带 CAS 版本号)
set balance 0 0 3
100
# STORED
gets balance
# VALUE balance 0 3 123456789 ← 最后一个数字是 CAS 唯一值
# 100
# END
# 第二步:使用 cas 更新(带上 CAS 值)
cas balance 0 0 3 123456789
200
# STORED ← 成功:CAS 值匹配
# 第三步:再次尝试用旧 CAS 值更新
cas balance 0 0 3 123456789
300
# EXISTS ← 失败:CAS 值已改变
# 第四步:重新获取新的 CAS 值
gets balance
# VALUE balance 0 3 987654321
# 200
# END
cas balance 0 0 3 987654321
300
# STORED ← 成功
业务场景: 防止并发写覆盖。
# Python 伪代码:CAS 更新余额
def transfer(user_id, amount):
while True:
data = mc.gets(f"balance:{user_id}")
current = int(data["value"])
new_balance = current + amount
# CAS 更新
result = mc.cas(f"balance:{user_id}", str(new_balance), cas=data["cas"])
if result == "STORED":
return new_balance
# EXISTS → 重试(其他客户端已修改)
4.3 检索命令
GET — 获取单个/多个值
# 获取单个 Key
get mykey
# VALUE mykey 0 5
# hello
# END
# 批量获取多个 Key(原子操作,单次网络往返)
get key1 key2 key3
# VALUE key1 0 5
# hello
# VALUE key3 0 5
# world
# END
批量 GET 的重要性: 一次
get key1 key2 ... keyN只需一次网络往返,N 次单独get需要 N 次往返。在高并发场景下,批量获取能显著降低延迟。
GETS — 获取值 + CAS 版本号
gets mykey
# VALUE mykey 0 5 123456
# hello
# END
返回值末尾多了一个 cas_unique 数字,用于 CAS 操作。
GAT / GATS — 获取并更新 TTL
Memcached 1.6+ 的 meta 协议支持获取的同时更新过期时间:
# gat <exptime> <key> — 获取并重置 TTL
gat 3600 mykey
# VALUE mykey 0 5
# hello
# END
业务场景: 热点数据每次访问时续期(滑动过期)。
4.4 删除命令
DELETE — 删除 Key
# 删除存在的 Key
set deltest 0 0 5
hello
# STORED
delete deltest
# DELETED
# 删除不存在的 Key
delete deltest
# NOT_FOUND
# 带 noreply
delete deltest noreply
带 CAS 的删除(条件删除):
# 只有当 Key 的 CAS 值匹配时才删除
set lockkey 0 30 1
1
# STORED
gets lockkey
# VALUE lockkey 0 1 112233
# 1
# END
delete lockkey 112233
# DELETED — CAS 匹配,删除成功
4.5 计数命令
INCR — 原子自增
# 初始化计数器
set counter 0 0 1
0
# STORED
# 自增 1
incr counter 1
# 1
# 自增指定值
incr counter 10
# 11
# 自增 1
incr counter 1
# 12
特性:
- 原子操作,线程安全
- 无符号 64 位整数
- Key 不存在时返回
NOT_FOUND - 溢出时回绕到 0
DECR — 原子自减
set tickets 0 0 2
100
# STORED
decr tickets 1
# 99
decr tickets 50
# 49
# 不会减到负数,最小为 0
decr tickets 100
# 0
业务场景:
# 限流计数器
# 每分钟最多 100 次请求
add rate:user:123 0 60 3
100
# STORED
# 每次请求递减
decr rate:user:123 1
# 99(还有余量)
decr rate:user:123 1
# 98
# 当返回 0 时,表示限流
decr rate:user:123 1
# 0 — 达到限制
# 库存扣减
set stock:item:5001 0 0 3
500
# STORED
decr stock:item:5001 1
# 499
decr stock:item:5001 10
# 489
4.6 管理命令
FLUSH_ALL — 清空所有数据
# 立即清空
flush_all
# OK
# 延迟清空(10秒后生效)
flush_all 10
# OK
危险操作: 生产环境慎用!会清空所有缓存,导致大量回源请求(缓存雪崩)。
VERSION — 查看版本
version
# VERSION 1.6.31
QUIT — 退出连接
quit
VERBOSITY — 设置日志级别
# 设置日志级别(0-2)
verbosity 2
# OK
STATS — 查看统计信息
# 基本统计
stats
# STAT pid 1234
# STAT uptime 86400
# STAT time 1735689600
# STAT version 1.6.31
# STAT curr_connections 50
# ...
# END
# Item 统计
stats items
# STAT items:1:number 523
# STAT items:1:age 1234
# STAT items:1:evicted 0
# ...
# Slab 统计
stats slabs
# STAT 1:chunk_size 96
# STAT 1:total_chunks 10922
# STAT 1:used_chunks 523
# ...
# 重置统计
stats reset
# OK
4.7 Meta 协议命令(1.6+)
Meta 协议是 1.6 引入的新协议,一条命令可以完成多项操作:
Meta Set (ms)
# ms <key> <datalen> <flags>...
# T<seconds> — 设置 TTL
# F<flags> — 设置客户端 flags
# N — noreply
# c — 返回 CAS 值
# k — 返回 key
# O<token> — opaque 原样返回
ms mykey 5 T3600 F0
hello
# ST
# 返回 CAS 值
ms mykey 5 T3600 c
hello
# ST 123456789
Meta Get (mg)
# mg <key> <flags>...
# T — 返回 TTL
# f — 返回 flags
# v — 返回 value
# k — 返回 key
# s — 返回 size
# c — 返回 CAS
# h — 返回是否命中(不返回 value)
# l — 返回 lru position
# t — 返回 item type
# 只检查是否存在
mg mykey h
# HD
# 获取全部元数据
mg mykey v k s f t c T
# VA 5 k mykey s 5 f 0 t 0 c 123456789 T 3500
# hello
Meta Delete (md)
# md <key> [flags]
# E<cas> — CAS 删除
# N — noreply
# T<ttl> — 将 TTL 设置为极小值(软删除)
md mykey
# DE ← 成功删除
md mykey E123456
# NF ← CAS 不匹配
Meta Arithmetic (ma)
# ma <key> <flags>...
# N<delta> — 增量值
# J — 初始化(create if not found)
# T<seconds> — TTL
# 原子自增,不存在则创建
ma counter N1 J0 T3600
# VA 1
# 1
ma counter N10
# VA 11
# 11
4.8 命令对比速查表
| 命令 | 用途 | 原子性 | 返回 CAS | Key 不存在 |
|---|---|---|---|---|
set | 无条件写入 | ✓ | — | 创建 |
add | Key 不存在时写入 | ✓ | — | 创建 |
replace | Key 存在时覆盖 | ✓ | — | NOT_STORED |
append | 追加到末尾 | ✓ | — | NOT_STORED |
prepend | 插入到开头 | ✓ | — | NOT_STORED |
cas | CAS 写入 | ✓ | ✓ | NOT_FOUND |
get | 获取值 | ✓ | — | 不返回 |
gets | 获取值+CAS | ✓ | ✓ | 不返回 |
delete | 删除 | ✓ | — | NOT_FOUND |
incr | 原子自增 | ✓ | — | NOT_FOUND |
decr | 原子自减 | ✓ | — | NOT_FOUND |
flush_all | 清空全部 | ✓ | — | — |
4.9 错误响应码
| 响应 | 含义 |
|---|---|
STORED | 存储成功 |
NOT_STORED | add/replace 条件不满足 |
EXISTS | CAS 版本不匹配 |
NOT_FOUND | Key 不存在 |
DELETED | 删除成功 |
ERROR | 未知命令 |
CLIENT_ERROR <msg> | 客户端错误(参数错误等) |
SERVER_ERROR <msg> | 服务端错误(内存不足等) |
扩展阅读
小结
| 要点 | 内容 |
|---|---|
| 最常用 | set / get / delete / incr / decr |
| 批量获取 | get key1 key2 ... 减少网络往返 |
| 并发控制 | cas + gets 实现乐观锁 |
| 过期时间 | 0=不过期;≤30天=相对秒数;>30天=Unix 时间戳 |
| Meta 协议 | 1.6+ 推荐,单条命令完成多操作 |