Redis分布式锁,CMS高并发场景防重复提交

在CMS高并发场景中,用户快速点击或网络重试常导致同一请求被多次提交,产生重复订单或脏数据。
Redis分布式锁利用其原子操作,能有效拦截并发重复请求。
本文从零开始,教你用原生命令和Redisson框架两种方式实现防重,并给出完整的验证与避坑步骤。

准备条件

  • 一台已安装Redis的服务器(本地或远程均可),推荐Redis 5.0以上版本。
  • 开发环境:Java项目(示例使用Spring Boot),PHP或其他语言逻辑类似。
  • 能连接Redis的客户端,如redis-cli或项目依赖的Jedis/Lettuce。
  • 对CMS中需要防重的接口路径有清晰认识,例如提交文章、发布评论、下单等。

用原生Redis命令实现锁

核心思路:利用SET key value NX PX milliseconds命令,仅当key不存在时才能设置成功,并自动过期避免死锁。

加锁步骤

  1. 生成唯一value(如UUID),用于标识锁的持有者。
  2. 执行命令:
   SET lock:submit:12345 uuid NX PX 10000

其中lock:submit:12345是锁键(建议用业务前缀+用户ID或请求ID),uuid是随机值,NX表示不存在才设置,PX 10000表示10秒后自动释放。

  1. 若返回OK,表示加锁成功,继续执行业务逻辑;返回nil则加锁失败,直接返回“请勿重复提交”。

释放锁步骤
不能简单DEL,否则可能误删他人锁。必须用Lua脚本保证原子性:

if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
else
    return 0
end

在代码中调用该脚本,传入锁键和之前设置的uuid。

注意:业务执行时间若超过锁过期时间,锁会自动释放,其他请求可能乘虚而入。
建议根据业务耗时合理设置PX,或在业务内部续期(复杂场景推荐Redisson)。

Redisson更省心的锁方案

Redisson是Redis的Java客户端,提供了看门狗自动续期、可重入锁等特性,适合生产环境。

引入依赖(Maven):


    org.redisson
    redisson-spring-boot-starter
    3.23.0

配置连接(application.yml):

spring:
  redis:
    host: 127.0.0.1
    port: 6379

加锁代码示例:

@Autowired
private RedissonClient redissonClient;

public void submitArticle(Long articleId) {
    String lockKey = "lock:article:" + articleId;
    RLock lock = redissonClient.getLock(lockKey);
    try {
        // 尝试加锁,最多等待3秒,锁自动释放时间10秒
        boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
        if (!locked) {
            throw new RuntimeException("操作过于频繁,请稍后再试");
        }
        // 执行业务逻辑
        doSubmit(articleId);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

看门狗:若未指定锁释放时间(tryLock不带leaseTime),Redisson默认加锁30秒,并启动后台线程每10秒续期,直到业务结束。
这能有效避免业务未完成锁提前释放。

避坑指南

  • 锁粒度要细:不要用全局锁,应针对具体资源(如用户ID+操作类型)加锁,否则并发性能急剧下降。
  • 锁超时时间:设置太短会导致业务未完成锁被释放;太长则故障时影响恢复。建议根据压测结果调整。
  • Redis单点故障:若Redis宕机,所有锁失效。生产环境建议使用Redis哨兵或集群模式,并考虑Redisson的联锁(RedLock)实现。
  • 不要用DEL直接删锁:必须验证value再删除,避免误解锁。
  • 异常处理:确保unlock在finally中执行,防止死锁。

效果验证

  1. 启动两个终端,同时用ab或wrk压测同一接口,观察是否只有一个请求成功。
  2. 查看Redis中锁键是否存在:redis-cli keys 'lock:*',正常业务结束后键应消失。
  3. 模拟业务超时:在业务中sleep超过锁过期时间,观察第二个请求是否被拦截。
  4. 检查日志:加锁失败的请求应返回友好提示,无重复数据写入。

常见疑问

锁过期了业务还没执行完怎么办?
使用Redisson的看门狗机制自动续期,或手动在业务中定期重置过期时间。

Redis主从切换时锁会丢失吗?
可能丢失。主从异步复制下,主节点故障时锁可能未同步到从节点。对一致性要求极高的场景,考虑RedLock或改用ZooKeeper。

能否用SETNX+Lua替代Redisson?
可以,但需要自行处理续期、可重入等逻辑,维护成本较高。Redisson更推荐。

按照以上步骤,你就能在CMS高并发场景中有效防止重复提交。
建议先在测试环境验证锁行为,再逐步上线。
遇到异常时,优先检查锁键、过期时间和释放逻辑。

分享到:
上一篇
MySQL数据库备份恢复测试,定期演练恢复流程
下一篇
Redis内存淘汰策略,maxmemory
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意