分布式锁有那些开源实现
常见的有以下几种分布式锁,或者如果搜索”分布式锁”,通常是以下这些实现:Redis-setnx、Redission、Redlock、ZooKeeper、etcd。那我们来看下这些分布式锁的实现方式和优缺点。先说明一点前提,我们在技术选型的时候,往往是要根据具体的业务场景做选择的,不是做纯粹的技术讨论,因为技术是为业务服务的。
Redis setnx
基于Redis锁主要利用Redis的setnx命令实现的,为了防止死锁setnx 和 expire必须一起使用,早期为了解决setnx 和 expire 非原子性通常使用lua脚本解决这个问题。当然Redis在 2.6.12版本以后解决了setnx 和 expire 非原子性的问题了。
在实现业务场景中,为了防止锁误解除、获取锁失败时阻塞等还得写不少的代码.就是说如果你在想生产环境使用,还是得费不少精力解决这些问题,比如重入锁、租期续约、防止锁的误删除等功能,都需要额外的开发。
生产环境为了redis避免单点故障,通过Sentinel或集群实现故障转移,但是Redis的主从是异步通讯的。如果是在主加锁,然后主挂了,从还没有同步加锁信息,那么客户端的业务线程就会出现并行的情况,这个就没有安全性了。
所以我们总结一下就是,基于Redis的setnx只是提供分布式锁的原子性,其它的特性如:安全性、活性等功能,还需要额外实现。如果要在生产环境使用健壮、易用的分布式锁,还需要额外手段保障数据的一致性和安全性。
小米技术部的文章,总结的比较到位,供大家参考。https://xiaomi-info.github.io/2019/12/17/redis-distributed-lock/
Redission
Redisson也是java的redis客户端之一,Redisson提供了分布式锁的API操作,相对setnx更容易用、功能更强大。Redisson加锁、释放锁操作也是通过lua脚本完成的。
Redisson分布式锁的API对开发人员来说,比较友好,相对容易操作。在锁的特性方面,Redisson的锁是支持重入锁和公平锁的。
Redisson支持单实例和哨兵模式,但是哨兵模式的安全性和一致性,我没有测试过,不好说。
Redisson的WatchDog 机制能够很好的解决锁续期的问题,这是一个很大的进步。因为业务端是很难预测业务需要占用锁的时间,为了避免业务还没有执行完就释放分布工锁了,所以占用锁的时间就设置得比较长,从而锁的粒度就比较粗。有了WatchDog就可以改善这个问题了,可以定期去续锁的租期,让锁的粒度更小。
总结一下,使用Redisson作为分布式锁比Redis的setnx命令更容用,功能更强大,这是Redisson的进步之处。缺点还是redis基于异步的主从复制,从而在发生主从切换时,会出现两个线程同时获取到锁的情况。可以看出来,这个是基于Redis实现分布锁的通病。因为本质上Redis还是AP模型,而不是一个CP模型。另外,Redis的服务端的数据复制是异步的,没有一致性算法保障的。如果你的业务场景能够容忍这个缺点,使用Redisson是没有问题的,因为Redis基本是现成的,学习和部署起来也很简单。
有一篇关于Redisson文章,供大家参考。https://github.com/angryz/my-blog/issues/4