✅引入分布式锁解决并发问题

背景

我的项目中,有一个场景会出现并发问题,就是我们有一个支付单,这个支付单会有到期的自动关闭,以及用户也可以主动取消订单进行关闭。

这两个操作,有的时候就会出现并发的问题,导致重复关单,重复发消息给下游,导致下游处理失败。

为了解决这个并发的问题,我在项目中采用了分布式锁来解决。

技术选型

其实分布式锁有很多种方案,无非就是借助一个第三方的系统,来做互斥性的协调。那么市面上主流的实现方式就是基于数据库、zookeeper以及redis。

我在选型的时候分别了解了一下这几个方案。

其实最简单的肯定是数据库的方式,在数据库中建一张表,加锁时创建一条记录,解锁时再把记录删除,通过唯一性约束来避免重复的记录。当要加锁的时候,判断下数据库中是否已经有这条记录了,没有就插入一条。

这个方案的话好处就是实现简单,缺点也比较明显,就是太依赖数据库,在高并发情况下,可能会对数据库造成压力,并且性能也不太好,而且也会占用很多数据库链接,影响正常的业务。

基于数据库的悲观锁当然也可以实现,但是悲观锁的机制,可能会导致锁表,也会导致线程阻塞的问题,所以这个方案我也放弃了。

另外在zookeeper和redis中,我选择了redis,因为redis我们现在系统中已经在用了,但是zk的话我们没有引入,并且搭建一个zk集群成本也挺高的。

你做了什么

在redis中呢,我们最开始使用了setnx的方案,但是后来经常会出现并发问题,后来发现是因为有的时候,我们设置的解锁的超时时间太短了,导致锁提前释放了。但是拉长超时时间又会使得接口的吞吐量降低,后来我发现redisson其实他实现了看门狗的机制,可以帮助我们做自动续期,我就选了redisson的方案。

但是,其实现在我们这个方案也存在一定的问题,那就是在redis的主节点如果出现问题的情况下,可能会导致锁丢失,但是因为我们这个目前业务量还没有那么大,所以暂时还没有遇到这个问题,不过我也了解过,其实可以基于redlock来解决这个问题,redlock可以借助集群的投票机制,超过半数以上写入成功才算加锁成功,这样可解决单点故障的问题。后面会考虑优化一下。

得到的结果

解决了并发的问题

学习资料

✅分布式锁有几种实现方式?

✅如何用SETNX实现分布式锁?

✅什么是RedLock,他解决了什么问题?

如何用Redisson实现分布式锁?

✅如何用Zookeeper实现分布式锁?

原文: https://www.yuque.com/hollis666/xkm7k3/gq8eszf1bgks154g