Redis计数到底咋整才快又准,别光用命令得讲技巧和思路
- 问答
- 2026-01-23 22:52:21
- 1
快 vs 准
首先你得明白,计数问题的核心就是“快”和“准”之间的权衡,Redis之所以快,一个重要原因是它经常把数据放在内存里,并且为了性能有时会牺牲一部分数据安全性(比如默认情况下,每隔一秒才把数据刷到磁盘上),这就引出了我们第一个,也是最重要的技巧。
根据对“准”的要求,选择持久化策略
这个思路来源于Redis官方文档关于持久化的说明(参考来源:Redis Persistence),Redis提供了两种主要的持久化方式:RDB(快照)和AOP(追加日志)。
-
场景A:允许少量丢失,追求极致性能(比如点赞数、页面浏览量) 这种计数丢几个无所谓,今天文章10001个赞和10005个赞没本质区别,这时候,就用Redis默认的RDB持久化或者调整AOF策略为每秒同步一次,即使服务器突然宕机,最多丢失一秒内增加的计数,对业务影响微乎其微,但性能最高。
-
场景B:要求绝对准确,不能丢(比如扣库存、交易笔数) 这就不能靠默认配置了,你必须“牺牲”一点速度来换“准”,思路是:启用AOF持久化,并且设置
appendfsync always,这个配置的意思是,每执行一条写命令(比如INCR),Redis都会立刻把命令刷到磁盘里再返回成功,这样即使宕机,也能从日志里恢复所有操作,保证计数绝对准确,这么干会让Redis的写性能急剧下降,因为每个写操作都变成了磁盘IO。关键思路是:根据业务对数据准确性的容忍度,来配置合适的持久化级别。
避免大Key,化整为零
这个思路是处理海量计数的经典技巧(参考来源:Redis官方文档关于使用模式的建议),比如你要给一个热门直播节目计数,同时在线人数可能上千万,如果你只用一个大Key,比如live:show123:viewers,这个Key会被频繁读写,它所在的Redis单线程实例就会成为瓶颈,速度肯定快不起来。
那咋整?思路是分片(Sharding),把一个大计数拆成很多个小计数。 你可以:
- 按时间分片: 创建多个Key,
live:show123:viewers:minute1,live:show123:viewers:minute2... 每分钟换一个Key来计数,最后要总数?把过去N分钟的各个Key值加起来就行了,这特别适合实时性要求高但不需要绝对实时总数的场景。 - 按逻辑分片: 比如根据用户ID的哈希值,把计数分散到10个Key上,
live:show123:viewers:0到live:show123:viewers:9,增加计数时,根据用户ID决定往哪个小Key里加,要总数时,用MGET命令一次性取出10个值,然后在客户端求和,这样就把对一个Key的巨大压力,分摊到了10个Key上,并行处理,速度自然就上去了。核心思路是:用空间(多个Key)和最终的计算(客户端求和)来换取单点的读写性能。
批量操作,减少网络往返
这是所有Redis优化的黄金法则(参考来源:Redis官方文档关于管道的说明),比如有个场景:用户每完成一个操作,你需要给他的多个统计项计数,今日完成数”、“总完成数”、“任务积分”。
菜鸟的做法是连发三个命令:
INCR user:123:today_count
INCR user:123:total_count
INCR user:123:points
这会产生3次网络往返时间(RTT),非常慢。
高手的做法是使用管道(Pipeline),把三个命令打包成一个数据包一次性发给Redis,再一次性读回所有结果,这几乎只消耗1次网络往返的时间,速度提升数倍。思路是:与其一个个地请求,不如攒一拨儿一起发,极大减少网络开销。
原子性脚本应对复杂逻辑
有时候计数不是简单的加1减1,而是有条件的,比如经典的“扣库存”场景:库存数量必须大于0才能减。
你先GET stock_key,判断大于0,再DECR stock_key,这在并发环境下会出大问题,因为两个客户端可能同时读到库存为1,都判断通过,然后都执行了扣减,结果库存变成了-1。
解决这个问题,光用命令组合不行,必须保证原子性。思路是使用Lua脚本(参考来源:Redis官方文档关于Lua脚本的说明),Redis会单线程执行整个Lua脚本,中间不会被其他命令打断,你可以把判断和扣减的逻辑写成一个脚本:
local current = redis.call('GET', KEYS[1])
if current and tonumber(current) > 0 then
return redis.call('DECR', KEYS[1])
else
return -1 -- 表示库存不足
end
这样就把一个可能出错的“读-判断-写”非原子流程,变成了一个不可分割的原子操作,既快(因为脚本在服务端执行,省网络)又准(保证数据一致)。
总结一下核心思路:
- 要准,就在持久化配置上做文章,用性能换数据安全。
- 要快,就把压力分摊,拆解大Key,避免单点热点。
- 要更快,就减少聊天次数,多用管道批量操作。
- 要又快又准地处理复杂逻辑,就上原子脚本,避免并发竞争。
Redis计数玩得好不好,全看你能不能根据实际业务,灵活组合这些技巧和思路,而不是死记硬背几个命令。

本文由符海莹于2026-01-23发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/84725.html
