Memcached计数器操作 #
一、计数器概述 #
1.1 计数器命令 #
text
Memcached提供以下计数器命令:
incr - 递增计数器
decr - 递减计数器
1.2 计数器特点 #
text
计数器特点:
1. 原子操作
- 线程安全
- 无需加锁
2. 只能操作数字
- 值必须是数字字符串
- 非数字值会返回错误
3. 64位无符号整数
- 范围:0 ~ 18446744073709551615
- 溢出后回绕
4. 键不存在返回NOT_FOUND
- 需要先初始化计数器
二、incr命令 #
2.1 命令说明 #
text
incr命令:
- 递增计数器
- 原子操作
- 返回递增后的值
语法:
incr <key> <value> [noreply]\r\n
响应:
<value> - 递增后的新值
NOT_FOUND - 键不存在
ERROR - 值不是数字
2.2 基本使用 #
bash
# 初始化计数器
set counter 0 0 1
0
STORED
# 递增1
incr counter 1
1
# 递增5
incr counter 5
6
# 递增10
incr counter 10
16
# 查看当前值
get counter
VALUE counter 0 0 2
16
END
2.3 递增任意值 #
bash
# 初始化
set views 0 0 1
0
STORED
# 递增100
incr views 100
100
# 递增1000
incr views 1000
1100
# 递增1
incr views 1
1101
2.4 键不存在 #
bash
# 键不存在时返回NOT_FOUND
incr notexist 1
NOT_FOUND
# 需要先初始化
set notexist 0 0 1
0
STORED
incr notexist 1
1
2.5 非数字值 #
bash
# 存储非数字值
set text 0 0 5
hello
STORED
# 尝试递增
incr text 1
ERROR
# 需要先删除再初始化
delete text
DELETED
set text 0 0 1
0
STORED
incr text 1
1
三、decr命令 #
3.1 命令说明 #
text
decr命令:
- 递减计数器
- 原子操作
- 返回递减后的值
语法:
decr <key> <value> [noreply]\r\n
响应:
<value> - 递减后的新值
NOT_FOUND - 键不存在
ERROR - 值不是数字
3.2 基本使用 #
bash
# 初始化计数器
set counter 0 0 2
10
STORED
# 递减1
decr counter 1
9
# 递减3
decr counter 3
6
# 递减5
decr counter 5
1
# 查看当前值
get counter
VALUE counter 0 0 1
1
END
3.3 递减边界 #
bash
# 初始化为5
set counter 0 0 1
5
STORED
# 递减3
decr counter 3
2
# 递减10(超过当前值)
decr counter 10
0
# Memcached不会出现负数
# 递减到0为止
3.4 递减任意值 #
bash
# 初始化
set stock 0 0 3
100
STORED
# 递减10
decr stock 10
90
# 递减50
decr stock 50
40
# 递减1
decr stock 1
39
四、计数器溢出 #
4.1 上溢 #
bash
# 64位无符号整数最大值
# 18446744073709551615
# 设置接近最大值
set counter 0 0 20
18446744073709551615
STORED
# 递增后溢出回绕
incr counter 1
0
# 继续递增
incr counter 1
1
4.2 下溢 #
bash
# 设置为0
set counter 0 0 1
0
STORED
# 递减(已经是0)
decr counter 1
0
# 不会出现负数
decr counter 100
0
五、应用场景 #
5.1 页面访问计数 #
bash
# 初始化页面访问计数
set page:views:home 0 0 1
0
STORED
# 每次访问递增
incr page:views:home 1
1
incr page:views:home 1
2
incr page:views:home 1
3
# 获取当前访问量
get page:views:home
VALUE page:views:home 0 0 1
3
END
5.2 API调用统计 #
bash
# 初始化API调用计数
set api:calls:weather 0 86400 1
0
STORED
# 每次调用递增
incr api:calls:weather 1
1
incr api:calls:weather 1
2
# 统计每日调用量(设置24小时过期)
set api:calls:weather:20240101 0 86400 1
0
STORED
incr api:calls:weather:20240101 1
1
5.3 点赞/踩统计 #
bash
# 初始化点赞数
set article:1001:likes 0 0 1
0
STORED
# 点赞
incr article:1001:likes 1
1
# 取消点赞
decr article:1001:likes 1
0
# 初始化踩数
set article:1001:dislikes 0 0 1
0
STORED
# 踩
incr article:1001:dislikes 1
1
5.4 库存管理 #
bash
# 初始化库存
set product:1001:stock 0 0 3
100
STORED
# 扣减库存
decr product:1001:stock 1
99
# 批量扣减
decr product:1001:stock 10
89
# 补充库存
incr product:1001:stock 50
139
# 检查库存
get product:1001:stock
VALUE product:1001:stock 0 0 3
139
END
5.5 限流计数 #
bash
# 用户限流(每分钟最多100次)
set rate:user:1001 0 60 1
0
STORED
# 每次请求递增
incr rate:user:1001 1
1
# 检查是否超过限制
get rate:user:1001
VALUE rate:user:1001 0 0 2
50
END
# 如果超过100,拒绝请求
5.6 分布式ID生成 #
bash
# 初始化ID序列
set global:user:id 0 0 1
0
STORED
# 生成新ID
incr global:user:id 1
1
incr global:user:id 1
2
incr global:user:id 1
3
# 批量生成ID
incr global:user:id 100
103
# 返回的值是递增后的值
# 所以ID范围是 4-103
5.7 在线人数统计 #
bash
# 初始化在线人数
set online:count 0 0 1
0
STORED
# 用户上线
incr online:count 1
1
# 用户下线
decr online:count 1
0
# 获取当前在线人数
get online:count
VALUE online:count 0 0 1
5
END
六、高级用法 #
6.1 批量计数器 #
bash
# 初始化多个计数器
set counter:page:home 0 0 1
0
STORED
set counter:page:about 0 0 1
0
STORED
set counter:page:contact 0 0 1
0
STORED
# 批量递增
incr counter:page:home 1
1
incr counter:page:about 1
1
incr counter:page:contact 1
1
6.2 时间窗口计数 #
bash
# 按小时统计
set counter:hour:2024010110 0 86400 1
0
STORED
incr counter:hour:2024010110 1
1
# 按天统计
set counter:day:20240101 0 604800 1
0
STORED
incr counter:day:20240101 1
1
# 按月统计
set counter:month:202401 0 2592000 1
0
STORED
incr counter:month:202401 1
1
6.3 多维度统计 #
bash
# 按用户统计
set counter:user:1001:views 0 0 1
0
STORED
incr counter:user:1001:views 1
1
# 按类型统计
set counter:type:article:views 0 0 1
0
STORED
incr counter:type:article:views 1
1
# 按地区统计
set counter:region:beijing:views 0 0 1
0
STORED
incr counter:region:beijing:views 1
1
七、计数器初始化 #
7.1 使用set初始化 #
bash
# 标准初始化方法
set counter 0 0 1
0
STORED
incr counter 1
1
7.2 使用add初始化 #
bash
# 使用add避免覆盖已存在的计数器
add counter 0 0 1
0
STORED
# 如果已存在,add失败
add counter 0 0 1
0
NOT_STORED
# 然后直接incr
incr counter 1
1
7.3 自动初始化代码 #
python
def init_counter(key, default=0):
# 尝试初始化
result = client.add(key, str(default), noreply=True)
# 无论如何都可以递增
return client.incr(key, 1)
def safe_incr(key, delta=1, default=0):
# 先尝试递增
result = client.incr(key, delta)
if result is None:
# 键不存在,初始化后再递增
client.set(key, str(default))
result = client.incr(key, delta)
return result
八、计数器最佳实践 #
8.1 键命名规范 #
bash
# 好的命名
counter:page:views:home
counter:api:calls:weather
counter:user:1001:likes
# 不好的命名
counter1
page_views
api-calls
8.2 过期时间设置 #
bash
# 永久计数器(不过期)
set counter:total:users 0 0 1
0
# 临时计数器(设置过期时间)
set counter:rate:user:1001 0 60 1
0
# 按时间窗口设置过期
set counter:hour:2024010110 0 86400 1
0
8.3 数值范围检查 #
python
def safe_decr(key, delta=1):
# 先获取当前值
value = client.get(key)
if value is None:
return 0
current = int(value)
# 检查是否会递减到负数
if current < delta:
# 设置为0
client.set(key, "0")
return 0
# 正常递减
return client.decr(key, delta)
8.4 并发安全 #
bash
# incr/decr是原子操作,天然支持并发
# 多个客户端同时递增
# 客户端A
incr counter 1
101
# 客户端B
incr counter 1
102
# 结果正确,不会丢失更新
九、性能优化 #
9.1 使用noreply #
bash
# 不等待响应,提高性能
incr counter 1 noreply
decr counter 1 noreply
# 适用于不需要立即获取结果的场景
9.2 批量操作 #
bash
# 使用Pipeline批量操作
# 客户端支持Pipeline时
pipeline = client.pipeline()
pipeline.incr("counter1", 1)
pipeline.incr("counter2", 1)
pipeline.incr("counter3", 1)
results = pipeline.execute()
9.3 本地缓存 #
python
# 对于频繁读取的计数器,可以使用本地缓存
class CachedCounter:
def __init__(self, client, key, ttl=1):
self.client = client
self.key = key
self.ttl = ttl
self.cache = None
self.last_update = 0
def get(self):
now = time.time()
if now - self.last_update > self.ttl:
self.cache = self.client.get(self.key)
self.last_update = now
return self.cache
def incr(self, delta=1):
result = self.client.incr(self.key, delta)
self.cache = result
self.last_update = time.time()
return result
十、错误处理 #
10.1 常见错误 #
bash
# 1. 键不存在
incr notexist 1
NOT_FOUND
# 2. 值不是数字
set text 0 0 5
hello
STORED
incr text 1
ERROR
# 3. 递增值不是数字
incr counter abc
ERROR
10.2 错误处理代码 #
python
def safe_incr(key, delta=1, default=0):
try:
result = client.incr(key, delta)
if result is None:
# 键不存在,初始化
client.set(key, str(default))
result = client.incr(key, delta)
return result
except Exception as e:
# 处理其他错误
print(f"Error: {e}")
return None
def safe_decr(key, delta=1):
try:
result = client.decr(key, delta)
if result is None:
return 0
return result
except Exception as e:
print(f"Error: {e}")
return None
十一、总结 #
计数器命令要点:
| 命令 | 说明 | 响应 |
|---|---|---|
| incr | 递增 | 新值/NOT_FOUND/ERROR |
| decr | 递减 | 新值/NOT_FOUND/ERROR |
计数器特点:
- 原子操作,线程安全
- 64位无符号整数
- 溢出后回绕
- 递减不会出现负数
应用场景:
- 访问计数
- API统计
- 点赞/踩
- 库存管理
- 限流
- 分布式ID
下一步,让我们学习Memcached的高级特性!
最后更新:2026-03-27