Redis计数器防重机制详解,避免重复请求,提升系统稳定性

文章导读
Redis计数器防重机制的核心是通过原子递增操作(如INCR)和设置过期时间(EXPIRE)来实现幂等性校验,避免重复请求。具体实现步骤:1. 为每个请求生成唯一key(如用户ID+业务ID);2. 使用INCR key检查计数,若返回1则首次请求正常处理,否则拒绝;3. 设置key过期时间防止内存泄漏。代码示例:redis.incr('counter:' + request_id); if (r
📋 目录
  1. 来源1
  2. 来源2
  3. 来源3
  4. 来源4
  5. 来源5
  6. 来源6
A A

Redis计数器防重机制的核心是通过原子递增操作(如INCR)和设置过期时间(EXPIRE)来实现幂等性校验,避免重复请求。具体实现步骤:1. 为每个请求生成唯一key(如用户ID+业务ID);2. 使用INCR key检查计数,若返回1则首次请求正常处理,否则拒绝;3. 设置key过期时间防止内存泄漏。代码示例:redis.incr('counter:' + request_id); if (result == 1) { redis.expire('counter:' + request_id, 60); processRequest(); } else { return '重复请求'; }

来源1

在高并发场景下,用户可能因网络抖动或重复点击导致相同请求多次到达服务器。为防止重复处理造成数据不一致,可使用Redis作为计数器实现防重。关键命令:INCR原子自增,若首次为1则通过,后续大于1则拦截。同时结合EXPIRE避免key无限累积占用内存。例如,下单接口中key='order:'+userId+orderId,计数超过1即返回"重复下单"。

来源2

防重机制利用Redis单线程原子性,确保计数准确无竞态。完整流程:生成业务唯一ID存入Redis,INCR后判断返回值,首次1则执行业务并SETEX延长生存,重复则直接返回错误码。示例Lua脚本:local count = redis.call('INCR', KEYS[1]); if count == 1 then redis.call('EXPIRE', KEYS[1], 300); return 1; else return 0; end。这样既防重又提升性能,避免数据库压力。

来源3

实际案例:在秒杀活动中,用Redis计数器控制每个用户只能抢购一次。key设计为'kill:'+userId+goodsId,INCR返回1时扣库存并生成订单,否则提示"重复抢购"。过期时间设为活动时长+缓冲,如3600秒。监控内存使用,定时清理无效key。测试并发1w/s下,误杀率为0,系统稳定。

Redis计数器防重机制详解,避免重复请求,提升系统稳定性

来源4

结合布隆过滤器优化Redis防重:先查布隆是否存在,若存在跳过INCR直接拒;不存在则INCR确认。减少Redis访问,提升QPS。但布隆有小概率误判,INCR作为最终校验。适用于超大规模请求,如短视频点赞接口。

来源5

问题排查:如果INCR返回非1但实际是首次,可能是分布式时钟不一致导致key冲突。解决:用雪花算法生成全局唯一ID作为key后缀。过期时间不宜过长,避免热点key过多影响命中率,建议30-300秒根据业务调优。

Redis计数器防重机制详解,避免重复请求,提升系统稳定性

来源6

Node.js实现:const redis = require('redis'); client.incr('dup:' + req.body.id, (err, res) => { if (res === 1) { client.expire('dup:' + req.body.id, 60); // 处理业务 } else { res.json({code: 400, msg: '重复操作'}); } });简单高效,适用于REST API。

Q: 为什么用Redis而不是MySQL防重?
A: Redis内存操作速度快,支持原子INCR,适合高并发;MySQL锁开销大易成瓶颈。

Q: key如何设计避免冲突?
A: 业务前缀+用户ID+时间戳或UUID,确保唯一性。

Redis计数器防重机制详解,避免重复请求,提升系统稳定性

Q: 过期时间怎么设置?
A: 根据业务周期,如支付异步通知30分钟,验证码5分钟。

Q: 多实例Redis集群怎么保证一致?
A: 用Redisson分布式锁或统一key空间,全集群共享计数器。