Memcached存储命令 #

一、存储命令概述 #

1.1 存储命令列表 #

text
Memcached提供以下存储命令:

set      - 存储,存在则覆盖
add      - 添加,存在则失败
replace  - 替换,不存在则失败
append   - 追加到末尾
prepend  - 添加到开头
cas      - 检查并设置(Compare And Swap)

1.2 命令格式 #

text
基本格式:
<command> <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

参数说明:
command  - 命令名称
key      - 键名(最大250字节)
flags    - 标志位(32位整数,客户端自定义)
exptime  - 过期时间(秒,0表示永不过期)
bytes    - 数据字节数
noreply  - 可选,不返回响应
data     - 数据内容

二、set命令 #

2.1 命令说明 #

text
set命令:
- 存储数据
- 键存在则覆盖
- 键不存在则创建

语法:
set <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

响应:
STORED      - 存储成功
NOT_STORED  - 存储失败(一般不会出现)

2.2 基本使用 #

bash
# 存储简单字符串
set greeting 0 3600 5
hello
STORED

# 获取验证
get greeting
VALUE greeting 0 5
hello
END

# 覆盖已存在的数据
set greeting 0 3600 5
world
STORED
get greeting
VALUE greeting 0 5
world
END

2.3 存储JSON数据 #

bash
# 存储JSON对象
set user:1001 0 3600 45
{"id":1001,"name":"John","email":"john@example.com"}
STORED

# 存储JSON数组
set users:list 0 3600 95
[{"id":1001,"name":"John"},{"id":1002,"name":"Jane"}]
STORED

# 使用flags标识JSON
set user:1001 2 3600 45
{"id":1001,"name":"John","email":"john@example.com"}
STORED

2.4 设置过期时间 #

bash
# 1小时后过期
set key1 0 3600 5
hello

# 永不过期
set key2 0 0 5
hello

# Unix时间戳过期(2024-01-01 00:00:00)
set key3 0 1704067200 5
hello

# 30天后过期(作为Unix时间戳)
set key4 0 2592000 5
hello

2.5 使用noreply #

bash
# 不等待响应,提高性能
set key 0 3600 5 noreply
hello

# 适用于批量操作
set key1 0 3600 5 noreply
hello
set key2 0 3600 5 noreply
world
set key3 0 3600 5 noreply
!

三、add命令 #

3.1 命令说明 #

text
add命令:
- 添加数据
- 键不存在时才成功
- 键存在则失败

语法:
add <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

响应:
STORED      - 存储成功(键不存在)
NOT_STORED  - 存储失败(键已存在)

3.2 基本使用 #

bash
# 添加新数据
add newkey 0 3600 5
hello
STORED

# 键已存在,添加失败
add newkey 0 3600 5
world
NOT_STORED

3.3 应用场景 #

bash
# 分布式锁
add lock:resource:1001 0 30 1
1
STORED

# 锁已被占用
add lock:resource:1001 0 30 1
1
NOT_STORED

# 防止重复创建
add user:1001:profile 0 3600 45
{"name":"John","age":25}
STORED

# 重复创建失败
add user:1001:profile 0 3600 45
{"name":"Jane","age":28}
NOT_STORED

3.4 实现幂等性 #

bash
# 使用add实现幂等操作
add request:order:12345 0 3600 1
1
STORED

# 重复请求被拒绝
add request:order:12345 0 3600 1
1
NOT_STORED

四、replace命令 #

4.1 命令说明 #

text
replace命令:
- 替换数据
- 键存在时才成功
- 键不存在则失败

语法:
replace <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

响应:
STORED      - 替换成功(键存在)
NOT_STORED  - 替换失败(键不存在)

4.2 基本使用 #

bash
# 先存储数据
set user:1001 0 3600 27
{"name":"John","age":25}
STORED

# 替换数据
replace user:1001 0 3600 27
{"name":"John","age":26}
STORED

# 键不存在,替换失败
replace user:9999 0 3600 5
hello
NOT_STORED

4.3 应用场景 #

bash
# 更新用户信息
set user:1001 0 3600 45
{"id":1001,"name":"John","email":"john@example.com"}
STORED

replace user:1001 0 3600 55
{"id":1001,"name":"John","email":"john@example.com","age":25}
STORED

# 更新配置
set config:app 0 0 32
{"theme":"light","lang":"en"}
STORED

replace config:app 0 0 32
{"theme":"dark","lang":"zh"}
STORED

五、append命令 #

5.1 命令说明 #

text
append命令:
- 追加数据到末尾
- 键不存在则失败

语法:
append <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

响应:
STORED      - 追加成功
NOT_STORED  - 追加失败(键不存在)

5.2 基本使用 #

bash
# 存储初始数据
set message 0 3600 5
hello
STORED

# 追加数据
append message 0 3600 6
 world
STORED

# 查看结果
get message
VALUE message 0 11
hello world
END

5.3 应用场景 #

bash
# 日志追加
set log:app 0 0 20
2024-01-01 INFO: Start
STORED

append log:app 0 0 25
\n2024-01-01 INFO: Running
STORED

# 列表追加(需要自行处理分隔符)
set list:items 0 3600 3
one
STORED

append list:items 0 3600 4
,two
STORED

append list:items 0 3600 6
,three
STORED

get list:items
VALUE list:items 0 13
one,two,three
END

六、prepend命令 #

6.1 命令说明 #

text
prepend命令:
- 添加数据到开头
- 键不存在则失败

语法:
prepend <key> <flags> <exptime> <bytes> [noreply]\r\n
<data block>\r\n

响应:
STORED      - 添加成功
NOT_STORED  - 添加失败(键不存在)

6.2 基本使用 #

bash
# 存储初始数据
set message 0 3600 5
world
STORED

# 添加到开头
prepend message 0 3600 6
hello 
STORED

# 查看结果
get message
VALUE message 0 11
hello world
END

6.3 应用场景 #

bash
# 添加前缀
set path 0 3600 8
/bin/bash
STORED

prepend path 0 3600 1
/
STORED

get path
VALUE path 0 9
//bin/bash
END

# 链表头部插入(需要自行处理分隔符)
set list:items 0 3600 5
three
STORED

prepend list:items 0 3600 4
two,
STORED

prepend list:items 0 3600 4
one,
STORED

get list:items
VALUE list:items 0 13
one,two,three
END

七、cas命令 #

7.1 命令说明 #

text
cas命令(Compare And Swap):
- 检查并设置
- 需要提供CAS ID
- CAS ID匹配才更新

语法:
cas <key> <flags> <exptime> <bytes> <cas unique> [noreply]\r\n
<data block>\r\n

响应:
STORED      - 更新成功
EXISTS      - CAS ID不匹配
NOT_FOUND   - 键不存在

7.2 基本使用 #

bash
# 先获取数据和CAS ID
gets user:1001
VALUE user:1001 0 27 123
{"name":"John","age":25}
END

# 使用CAS更新
cas user:1001 0 3600 27 123
{"name":"John","age":26}
STORED

# 再次获取新的CAS ID
gets user:1001
VALUE user:1001 0 27 124
{"name":"John","age":26}
END

# 使用旧的CAS ID更新失败
cas user:1001 0 3600 27 123
{"name":"John","age":27}
EXISTS

7.3 实现乐观锁 #

bash
# 场景:更新商品库存

# 1. 获取当前库存和CAS ID
gets product:1001:stock
VALUE product:1001:stock 0 2 100
50
END

# 2. 计算新库存(客户端处理)
new_stock = 50 - 1  # 减1

# 3. 使用CAS更新
cas product:1001:stock 0 3600 2 100
49
STORED

# 如果其他客户端同时更新,CAS会失败
cas product:1001:stock 0 3600 2 100
48
EXISTS

# 需要重新获取最新的CAS ID
gets product:1001:stock
VALUE product:1001:stock 0 2 101
49
END

# 使用新的CAS ID重试
cas product:1001:stock 0 3600 2 101
48
STORED

7.4 并发更新示例 #

bash
# 客户端A
gets counter
VALUE counter 0 1 10
5
END

# 客户端B
gets counter
VALUE counter 0 1 10
5
END

# 客户端A更新成功
cas counter 0 3600 1 10
6
STORED

# 客户端B更新失败(CAS ID已变)
cas counter 0 3600 1 10
6
EXISTS

八、存储命令对比 #

8.1 命令对比表 #

命令 键存在 键不存在 用途
set 覆盖 创建 通用存储
add 失败 创建 分布式锁、幂等
replace 替换 失败 条件更新
append 追加 失败 日志追加
prepend 前置 失败 添加前缀
cas 检查CAS 失败 乐观锁

8.2 响应状态对比 #

text
响应状态说明:

STORED      - 操作成功
NOT_STORED  - 操作失败(条件不满足)
EXISTS      - CAS ID不匹配
NOT_FOUND   - 键不存在
ERROR       - 命令格式错误

九、最佳实践 #

9.1 选择合适的命令 #

text
场景选择:

1. 简单缓存
   使用 set 命令

2. 分布式锁
   使用 add 命令

3. 条件更新
   使用 replace 命令

4. 并发安全更新
   使用 cas 命令

5. 日志追加
   使用 append 命令

9.2 键命名规范 #

bash
# 使用命名空间
set user:info:1001 0 3600 45
{"id":1001,"name":"John"}

set user:profile:1001 0 3600 55
{"id":1001,"name":"John","age":25}

# 使用层级结构
set cache:db:users:1001 0 3600 45
{"id":1001,"name":"John"}

# 包含过期信息
set session:web:abc123 0 1800 64
{"user_id":1001,"login_time":1704067200}

9.3 flags使用建议 #

bash
# 标识数据类型
set key 0 0 5        # 默认(字符串)
set key 1 0 5        # 序列化对象
set key 2 0 5        # JSON
set key 3 0 5        # 压缩数据
set key 4 0 5        # 二进制数据

# 客户端根据flags解析

9.4 过期时间设置 #

bash
# 根据数据特性设置
set static:config 0 0 100        # 永不过期
set session:user:1001 0 1800 64  # 30分钟
set cache:api:weather 0 3600 128 # 1小时
set temp:code:abc123 0 300 6     # 5分钟

# 避免缓存雪崩
base_time = 3600
random_time = random(0, 300)
exptime = base_time + random_time

十、错误处理 #

10.1 常见错误 #

bash
# 数据长度不匹配
set key 0 0 5
hello world
CLIENT_ERROR bad data chunk

# 键名过长
set aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 0 0 5
hello
CLIENT_ERROR bad command line format

# 数据过大
set key 0 0 2000000
<2MB data>
SERVER_ERROR object too large for cache

10.2 错误处理建议 #

bash
# 1. 检查数据长度
data = "hello"
length = len(data)
command = f"set key 0 3600 {length}"

# 2. 处理响应
response = send_command(command, data)
if response == "STORED":
    # 成功
    pass
elif response == "NOT_STORED":
    # 失败
    pass
elif response == "EXISTS":
    # CAS冲突
    pass

# 3. 重试机制
max_retries = 3
for i in range(max_retries):
    response = cas_with_retry(key, value)
    if response == "STORED":
        break

十一、总结 #

存储命令要点:

命令 说明 典型场景
set 存储覆盖 通用缓存
add 仅新增 分布式锁
replace 仅替换 条件更新
append 追加 日志追加
prepend 前置 添加前缀
cas 检查更新 并发安全

下一步,让我们学习Memcached的读取命令!

最后更新:2026-03-27