对分布式锁的一点理解以及实现

  • 内容
  • 评论
  • 相关

摘要:目前得到一个任务需求,需要基于redis做一个分布式锁,于是,我开始查阅大量资料,整理,实践,给予最合适的分布式锁处理方案。

 

目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题。分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

 

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。有的时候,我们需要保证一个方法在同一时间内只能被同一个线程执行。在单机环境中,Java中其实提供了很多并发处理相关的API,但是这些API在分布式场景中就无能为力了。也就是说单纯的Java Api并不能提供分布式锁的能力。所以针对分布式锁的实现目前有多种方案。

 

针对分布式锁的实现,目前比较常用的有以下几种方案:

1、基于数据库实现分布式锁

2、基于缓存(Redis、Memcached)实现分布式锁

3、基于Zookeeper实现分布式锁

 

本文重点讲解基于缓存(Redis)实现分布式锁。

 

1、基于数据库实现分布式锁

实现数据库实现分布式锁的思想:额外创建一张表,用来做分布式锁,某一字段用来存方法名称,为了方法名称相同而引起冲突,可以用包名+类名+方法名的形式来防止发生,该字段设置非空索引、唯一索引。在执行分布式的时候,争抢资源前需要对目标方法插入该表,如果插入成功,获取锁成功,可以执行相关方法;如果插入失败,获取锁失败,尝试执行获取锁或者放弃执行目标方法。这就是基于数据库实现分布式锁的实现思想。

 

2、基于缓存实现分布式锁

这是本文讨论的重点。用Redis实现分布式锁。

Redis实现分布式锁有两种方案:

1、使用setnx实现。

2、使用官方推荐的Redisson、RedLock实现。

 

2.1使用setnx实现

 

有人就会问,博主,不是setnx吗?怎么是set?对于此,你应该了解一下setnx和set的区别,set有很多重载方法,其实setnx是对set的一个封装,setnx没有ttl,所以如果获取锁的时候没有及时释放,这时候系统崩溃,释放锁失败,可能会导致后续的死锁,这是当然使我们不愿意见到的一面,当然,也可以在获取锁的时候设置一个ttl,而set可以直接在获取锁的时候设置一个ttl,具体参考jedis的方法。

 

方法注释已经很详细了,在执行目标方法之前,调用tryGetDistributedLock()方法,return true说明获得锁,执行相关代码;return false说明获取锁失败,尝试执行获取或放弃执行目标方法。流程图如下:

 

2.2基于Redisson、RedLock实现(官方推荐)

 

第一步:maven引入相关jar

 

第二步:创建DistributedLocker接口

 

第三步:创建RedisLocker类实现DistributedLocker接口

 

第四步:创建AquiredLockWorker接口

 

第五步:创建RedissonConnector类

 

第六步:创建UnableToAquireLockException继承RuntimeException

 

第七步:测试类

 

运行结果:

Thread-9 start

Thread-9 sleep 129millis

Thread-9 end

Thread-12 start

Thread-12 sleep 29millis

Thread-12 end

Thread-8 start

Thread-8 sleep 195millis

Thread-8 end

Thread-11 start

Thread-11 sleep 60millis

Thread-11 end

Thread-10 start

Thread-10 sleep 9millis

Thread-10 end

 

如此可见,官方提供的分布式锁解决方案还是相对而言比较稳定,安全可靠的。

 

3、基于zookeeper实现分布式锁

本文暂不做这方面的介绍

 

 

 

 

 

你若看到别人表面的光鲜,

希望你也能感受到他们背后的付出和努力。

 

喜欢 1

评论

0条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Title - Artist
0:00