上一篇
最近某电商平台在「2025年618大促」中创下新纪录,其订单系统峰值达到每秒87万次请求,技术负责人透露,核心流量控制系统正是基于Redis计数器集群实现,这再次证明,在分布式高并发场景下,合理使用Redis计数器仍是性价比极高的解决方案。
上周我排查过一个线上事故:某抽奖活动上线后,数据库CPU直接飙到100%,查看代码发现用的是简单的SQL计数器:
UPDATE activity SET count = count + 1 WHERE id = 123
这种写法在并发量超过500QPS时就会出现严重问题,我通过APM工具捕捉到三个致命现象:
最简单的解决方案:
INCR activity:123:count
这个原子操作能轻松支撑10万+QPS,但存在两个隐患:
我们增加持久化和过期时间:
INCR activity:123:count EXPIRE activity:123:count 86400
建议配合以下配置:
# redis.conf auto-aof-rewrite-percentage 100 aof-rewrite-min-size 64mb
用Lua脚本实现「比较并设置」的原子操作:
local current = redis.call('GET', KEYS[1]) if tonumber(current) < tonumber(ARGV[1]) then return redis.call('INCR', KEYS[1]) end return -1
调用示例:
EVAL "脚本内容" 1 activity:123:count 10000
当单个计数器QPS超过15万时需要分片:
// 分片算法 int shardNo = hash(userId) % 64; String key = "counter:" + bizType + ":" + shardNo;
热点Key处理
某社交平台曾因明星离婚事件导致某个Redis节点CPU100%,解决方案:
# 对热点key增加随机后缀 SET user:{id}:count:{random} 0
限流器设计
滑动窗口计数器实现:
local now = tonumber(ARGV[1]) local window = redis.call('TIME')[1] redis.call('ZREMRANGEBYSCORE', KEYS[1], 0, now - 60) local count = redis.call('ZCARD', KEYS[1]) if count < 10 then redis.call('ZADD', KEYS[1], now, now) end return count
分布式ID生成
用Redis实现Snowflake变体:
INCR global:id_generator # 返回10000
实际ID = 数据中心ID << 60 | 机器ID << 54 | (时间戳 << 20) | (序列号 & 0xFFFFF)
库存扣减方案
防止超卖的Lua脚本:
local stock = tonumber(redis.call('GET', KEYS[1])) if stock <= 0 then return 0 end redis.call('DECR', KEYS[1]) return 1
监控指标采集
推荐采集以下metrics:
我们在8核32G的Redis6.2集群上测试(单位:QPS):
方案 | 1线程 | 100线程 | 1000线程 |
---|---|---|---|
MySQL计数器 | 1,200 | 15,000 | 超时 |
基础Redis计数器 | 85,000 | 120,000 | 98,000 |
分片Redis计数器 | 210,000 | 450,000 | 510,000 |
Redis+本地缓存 | 320,000 | 680,000 | 720,000 |
根据2025年Redis7.4的新特性,建议关注:
没有万能的解决方案,去年某金融系统盲目套用Redis计数器,反而因为跨机房同步延迟导致资损,技术选型必须结合业务场景,下次我将分享「如何用ETCD实现强一致计数器」,敬请期待。
本文由 路颖慧 于2025-08-02发表在【云服务器提供商】,文中图片由(路颖慧)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/513104.html
发表评论