Skip to content

Memcached - 替换数据

Memcached 的 replace 命令更新现有键的值。其主要特点是,只有当键已存在于缓存中时,该操作才会成功。这使得它成为 set 命令的一个更安全的替代方案,当您的意图是严格地更新而非创建时。

replace 命令的基本语法如下:

replace key flags exptime bytes [noreply]
value

这些参数与 set 命令相同。key 是目标键,exptime 是新的过期时间,value 是新数据。

  • STORED(已存储)表示值已成功替换。
  • NOT_STORED(未存储)表示操作失败,因为键不存在。
  • ERROR(错误)表示语法错误。

此示例显示 replace 在不存在的键上会失败,但在使用 add 命令设置初始值后会成功。

# 1. 尝试替换一个不存在的键。
replace config:feature_flag 0 900 4
true
NOT_STORED
# 2. 为该键添加一个初始值。'add' 仅在键不存在时成功。
add config:feature_flag 0 900 5
false
STORED
# 3. 检索初始值。
get config:feature_flag
VALUE config:feature_flag 0 5
false
END
# 4. 现在,替换现有键的值。
replace config:feature_flag 0 900 4
true
STORED
# 5. 验证新值。
get config:feature_flag
VALUE config:feature_flag 0 4
true
END

这里是一个在 Python 应用程序中使用 pymemcache 库执行 replace 操作的实际示例。

确保 pymemcache 已安装:

pip install pymemcache
from pymemcache.client.base import Client
MEMCACHED_SERVER = ('127.0.0.1', 11211)
def run_replace_example():
"""演示 replace 操作的行为。"""
client = Client(MEMCACHED_SERVER)
key = 'user:session:abc-123'
# 确保我们有一个干净的环境
client.delete(key)
try:
# 1. 尝试替换一个不存在的键
# 如果成功,replace 方法返回 True;否则返回 False。
was_replaced = client.replace(key, '{"status": "active"}', expire=3600)
print(f"-> REPLACE 到不存在的键 '{key}'... 成功: {was_replaced}")
# 2. 设置初始值
client.set(key, '{"status": "pending"}', expire=3600)
initial_value = client.get(key).decode('utf-8')
print(f"-> SET: 初始化键 '{key}',值为: {initial_value}")
# 3. 现在,替换现有值
new_value = '{"status": "active", "last_seen": "2023-10-27T11:00:00Z"}'
was_replaced = client.replace(key, new_value, expire=3600)
print(f"-> REPLACE 到现有键... 成功: {was_replaced}")
# 4. 验证新值
final_value = client.get(key).decode('utf-8')
print(f"-> GET: 最终值为: {final_value}")
except Exception as e:
print(f"发生意外错误: {e}")
finally:
client.close()
if __name__ == "__main__":
run_replace_example()
-> REPLACE 到不存在的键 'user:session:abc-123'... 成功: False
-> SET: 初始化键 'user:session:abc-123',值为: {"status": "pending"}
-> REPLACE 到现有键... 成功: True
-> GET: 最终值为: {"status": "active", "last_seen": "2023-10-27T11:00:00Z"}
  • 有意更新: 当您的代码逻辑假定缓存中已存在某个项时,请使用 replace。这可以防止在某些原因(如过期或逐出)导致缓存项消失时,意外地创建一个新的缓存条目。这有助于暴露错误或逻辑问题。
  • 会话管理: 一个很好的用例是更新用户的会话数据。当用户执行某个操作时,您可以使用更新的信息(例如,新的 last_seen 时间戳)replace 其会话键。如果会话不存在(可能是他们超时了),replace 将会失败,您的应用程序可以正确地提示他们再次登录。
  • replace 与 set: 当您想存储一个值,无论它是否已存在(创建或更新)时,请使用 set。当您只想更新一个现有值时,请使用 replace。
  • replace 与 cas: replace 比 cas 简单。对于简单的、非并发的更新,使用 replace。当您需要执行读-修改-写操作且必须防止竞态条件时,请使用 cas。