Memcached replace 命令

Memcached replace 命令详解(2025 版)

replace 是 Memcached 的 “仅当 key 存在时更新” 命令,是 防止误创建 的原子操作。

set 区别:

  • set存在覆盖,不存在创建
  • replace存在才更新,不存在则失败

1. 基本语法

replace <key> <flags> <exptime> <bytes> [noreply]\r\n
<value>\r\n
参数说明
<key>键名(≤ 250 字节)
<flags>客户端自定义标志(0~65535)
<exptime>过期时间(秒)
<bytes>Value 字节数
[noreply]可选,异步写入
<value>实际数据

响应:

  • STORED\r\n成功(key 已存在)
  • NOT_STORED\r\n失败(key 不存在)

2. telnet 实际操作示例

telnet 127.0.0.1 11211

示例 1:key 存在 → replace 成功

# 先 set 一个 key
set user:1001 0 0 8
zhangsan
STORED

# 再 replace
replace user:1001 0 0 5
lisi
STORED

示例 2:key 不存在 → replace 失败

replace user:9999 0 0 5
wangwu
NOT_STORED

3. 客户端使用 replace

Python(pymemcache)

from pymemcache.client.base import Client

client = Client(('127.0.0.1', 11211))

# 先确保存在
client.set('config:version', 'v1.0.0')

# replace 返回 True/False
result = client.replace('config:version', 'v1.0.1', expire=3600)
print(result)  # True

result = client.replace('config:unknown', 'v2.0.0')
print(result)  # False(key 不存在)

PHP

$mc = new Memcached();
$mc->addServer('127.0.0.1', 11211);

$mc->set('counter:views', 100);

// 仅当存在时更新
if ($mc->replace('counter:views', 101)) {
    echo "更新成功";
} else {
    echo "key 不存在";
}

Java(XMemcached)

client.set("user:1", 0, "old");

// 仅当存在时替换
boolean ok = client.replace("user:1", 3600, "new");
System.out.println(ok); // true

4. replace vs set vs add

命令key 不存在key 存在用途
addSTOREDNOT_STORED初始化
setSTOREDSTORED通用写入
replaceNOT_STOREDSTORED仅更新
# 演示对比
add     newkey 0 0 3     → STORED
set     newkey 0 0 3     → STORED(覆盖)
replace newkey 0 0 3     → STORED
replace missing 0 0 1    → NOT_STORED

5. 经典应用场景

5.1 防止误覆盖初始化数据

# 启动时只初始化一次
if not client.get('app:initialized'):
    client.add('app:initialized', 'yes', expire=0)
    init_database()

# 后续只能 replace,不能 add
client.replace('app:initialized', 'reloaded', expire=0)

5.2 缓存更新(防穿透)

def get_user(uid):
    key = f'user:{uid}'
    data = client.get(key)
    if data is None:
        data = db.query(uid)
        client.add(key, data, 3600)  # 首次写入
    else:
        # 已有缓存,可安全更新
        client.replace(key, fresh_data, 3600)
    return data

5.3 计数器更新(配合 incr)

# 初始化
add counter:page 0 0 1
0
STORED

# 后续只能 replace 或 incr
replace counter:page 0 0 1
5
STORED

# 推荐用 incr
incr counter:page 1
6

5.4 热点数据刷新

# 定时任务:仅当缓存存在时刷新
if client.get('hot:news'):
    fresh = fetch_latest_news()
    client.replace('hot:news', fresh, expire=300)

6. 高级技巧

6.1 replace + get 实现“存在即更新”

value = client.get('cache:key')
if value is not None:
    new_value = update_value(value)
    client.replace('cache:key', new_value, expire=3600)

6.2 noreply 异步 replace

client.replace('log:count', new_count, noreply=True)

7. 过期时间 exptime 详解

含义
0永不过期
3005 分钟后过期
1739431200绝对时间戳

8. 常见错误

错误原因解决
NOT_STOREDkey 不存在setadd
CLIENT_ERROR参数错误检查格式
SERVER_ERROR内存不足增加 -m

9. 最佳实践

建议说明
replace 防止误创建适合配置、状态更新
配合 add初始化 + 更新完整生命周期
热点数据用 replace 刷新避免缓存穿透
不要用 replace 做首次写入会失败
key 命名清晰state:job:xxcache:config:xx

10. 调试与统计

# 查看 replace 统计
echo "stats" | nc 127.0.0.1 11211 | grep cmd_replace
# cmd_replace: 15
# replace_hits: 12
# replace_misses: 3

小结:replace 命令速查

replace key flags exptime bytes [noreply]
└─> STORED(仅当 key 存在)
   └─> NOT_STORED(key 不存在)
项目推荐值
flags与原值一致
exptime300 ~ 3600
bytes< 100KB
noreply高并发启用

练习建议

  1. 用 telnet 实现“只能更新已有 key”
  2. 用 Python 实现 配置热更新
  3. 模拟缓存重建:add → 正常运行 → replace 刷新

需要 CAS 乐观锁、append/prepend、或 flush_all 命令?继续问我!

文章已创建 2481

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部