当前位置: 首页 > news >正文

分布式锁在支付关闭订单场景下的思考

背景:

为何需要分布式锁?

在我们的内部支付系统中,存在一个典型的并发问题场景:支付单既可能因为到期而自动关闭,也可能被用户主动取消。这两种关闭操作在某些情况下会同时发生,导致重复关单和重复向下游发送消息,最终造成下游处理失败。

注:其实这种并发问题本质上是因为多个线程或进程同时操作同一份数据但缺乏有效的互斥机制就会出现并发问题。但是在分布式系统中,由于服务器实例基本会有很多节点部署,单机部署的锁机制没办法满足需求,这就需要引入分布式锁来解决跨进程的这种互斥的问题。

技术选型:

为什么要选择Redis和Redisson?

分布式锁的实现通常需要借助第三方系统来协调互斥性,一版的主流方案有:

1. 基于数据库实现

通过创建锁表,利用唯一性约束防止重复插入

这种方式实现起来比较简单,但是缺点也比较明显,对数据的压力会比较大,性能也会比较差
,对业务也会产生影响,这边不建议用悲观锁,可能导致锁表线程阻塞,所以不采用

2. 基于Zookeeper实现

利用顺序节点实现锁机制,优点是可靠性高,具备强一致性,但是需要引入新组件,增加了系统的复杂度

3. 基于Redis实现
通过SETNX命令实现锁获取,优点 性能高,拿来即用Redis。缺点的话就是需要处理锁超时和自动续期问题

我们最后是考虑到系统已使用Redis且无Zookeeper集群,我们选择了Redis,避免引入新组件成本。但原生SETNX方案存在锁提前释放的问题,最终我们采用了Redisson,主要是他提供了看门狗机制能实现自动续期

扩展实践:

从SETNX到Redisson的演进的过程:

一、我们最初使用Redis的SETNX命令实现分布式锁:

public boolean tryLock(String key, long expireTime) {String result = jedis.set(key, "1", "NX", "PX", expireTime);return "OK".equals(result);
}public void unlock(String key) {jedis.del(key);
}

这个方案在实际运行中经常出现并发问题,原因是:

  • 业务处理时间超过锁超时时间,导致锁提前释放
  • 拉长超时时间又降低了系统吞吐量,然后就比较尴尬

二、Redisson看门狗机制

Redisson提供了自动续期机制(看门狗),解决了锁超时问题:

public void processWithLock(String orderId) {RLock lock = redissonClient.getLock("order_lock:" + orderId);try {// 尝试加锁,最多等待100秒,上锁后30秒自动解锁if (lock.tryLock(100, 30, TimeUnit.SECONDS)) {try {// 此处省略业务processOrder(orderId);} finally {lock.unlock();}}} catch (InterruptedException e) {Thread.currentThread().interrupt();}
}

看门狗机制会在锁即将过期时自动续期,避免了业务处理时间过长导致锁超时

三、风险

虽然Redisson解决了并发和锁超时的问题,但是仍然存在一些潜在风险:

  • Redis主节点故障:在主从的这种架构下,主节点故障可能导致锁信息丢失
  • 脑裂:网络分区可能导致多个客户端同时持有锁

四、优化

RedLock算法


public void processWithRedLock(String orderId) {RLock lock1 = redissonClient1.getLock("order_lock:" + orderId);RLock lock2 = redissonClient2.getLock("order_lock:" + orderId);RLock lock3 = redissonClient3.getLock("order_lock:" + orderId);RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);try {if (redLock.tryLock(100, 30, TimeUnit.SECONDS)) {// 此处省略业务processOrder(orderId);}} finally {redLock.unlock();}
}

原理:RedLock通过多个独立的Redis节点协同工作,需要超过一半节点加锁成功才算真正获取到锁,大大提高了可靠性

总结

-Redisson单节点:适用于业务量不大、可用性要求不是很高的场景
-RedLock多节点方案:适用于金融行业等对一致性要求较高的核心业务

-分布式锁:适用于并发量不大且已具备数据库能力的简单场景
-Zookeeper:适用于已经有ZK集群且对可靠性要求较高的系统

一般情况下,我们需要先评估业务场景,不是所有并发场景都需要分布式锁,先考虑是否可以通过业务设计避免并发冲突,还要考虑锁超时问题,要根据业务处理时间合理设置锁超时时间,避免设置过长影响系统可用性,还有一个重点,必须要明确释放锁的动作,确保获取锁后用完释放锁,防止死锁


http://www.dtcms.com/a/357811.html

相关文章:

  • Product Hunt 每日热榜 | 2025-08-29
  • 逻辑漏洞 跨站脚本漏洞(xss)
  • 早期人类奴役AI实录:用Comate Zulu 10min做一款Chrome插件
  • nacos登录认证
  • 【算法】15. 三数之和
  • 学习做动画7.跳跃
  • UCIE Specification详解(十)
  • 快速深入理解zookeeper特性及核心基本原理
  • 【拍摄学习记录】06-构图、取景
  • Docker03-知识点整理
  • TypeScript:map和set函数
  • 2025 DDC系统选型白皮书:构建高效低碳智慧楼宇的核心指南
  • 【python开发123】三维地球应用开发方案
  • python 解码 视频解码
  • 打工人日报#20250829
  • 人工智能-python-深度学习-批量标准化与模型保存加载详解
  • OpenTenBase 技术解读与实战体验:从架构到行业落地
  • 2024年06月 Python(四级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • c++标准模板库
  • 轨道交通场景下设备状态监测与智能润滑预测性维护探索
  • 动态环境下的人员感知具身导航!HA-VLN:具备动态多人互动的视觉语言导航基准与排行榜
  • Free Subtitles-免费AI在线字幕生成工具,支持111种语言
  • 【ChatMemory聊天记忆】
  • STM32F4系列单片机如何修改主频
  • 从世界人形机器人大会看人形机器人如何实现复杂人类动作的精准复现?
  • 【论文简读】MuGS
  • 【拍摄学习记录】05-对焦、虚化、景深
  • 2025年06月 Python(四级)真题解析#中国电子学会#全国青少年软件编程等级考试
  • Golang 面试题「中级」
  • 四旋翼飞行器动力学建模与简单PID控制