ARTICLE / 3 MIN READ
Redis 在高并发系统中的锁、限流与幂等
以订单接口为例,梳理 Redis 分布式锁、滑动窗口限流、幂等键和延迟任务的边界。
Redis 适合做低延迟状态协调,但不应该替代核心数据库。把锁、限流和幂等拆开设计,才能避免一个 Key 的异常拖垮整条链路。
分布式锁的正确边界
锁只保护一段很短的临界区,例如“检查订单状态并创建支付任务”。加锁时要使用唯一 token,释放时通过 Lua 脚本校验 token,不能直接 DEL 别人的锁。
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
end
return 0
锁必须设置过期时间,业务处理时间也要有上限。锁续期不是万能药,续期失败后必须让后续代码停止写入,不能继续使用已经失去保护的资源。
限流比排队更靠前
固定窗口实现简单,但窗口边界会产生突刺。滑动窗口或令牌桶更适合 API 网关和用户级限流。
令牌桶容量 = 100
补充速率 = 50 token/s
请求消耗 = 1 token
没有 token -> 429 + Retry-After
限流维度可以组合为 IP、用户、租户、接口和全局。返回 429 时要让客户端知道等待多久,禁止无脑立即重试。
幂等键解决重复提交
客户端为一次业务操作生成幂等键,服务端将键和业务结果绑定。第一次请求执行并记录结果,重复请求直接返回同一结果。唯一约束仍应在数据库中兜底,Redis 只负责快速拦截。
幂等记录至少包含业务类型、用户、请求摘要、状态、结果引用和过期时间。请求摘要可以防止同一个键被拿来提交另一份参数。
延迟任务的选择
简单的超时提醒可以使用 Redis Sorted Set,以执行时间作为 score;可靠投递要求把任务状态落在数据库或消息队列中。Redis Key 过期事件不保证严格送达,不能直接当作支付、库存等关键业务的唯一触发器。
失败处理
- Redis 超时:读场景可降级,写场景应快速失败并记录告警。
- 主从切换:锁和计数器可能出现短暂不一致,关键事务仍由数据库约束保证。
- 热点 Key:拆分 Key 或增加本地缓存,避免单分片过载。
- 内存不足:设置 maxmemory-policy,并为每类 Key 设定容量预算。
Redis 的价值是把高频、短生命周期、可恢复的状态处理得足够快;最终一致性、审计和不可丢失的数据,必须回到持久化存储。
GITHUB DISCUSSION
评论与回复
评论保存在 GitHub Discussions,登录 GitHub 后即可参与,发布和回复都在本页完成。
评论区进入视口后自动加载。