前言
Java中的锁主要包括synchronized锁和JUC包中的锁,这些锁都是针对单个JVM实例上的锁,对散布式环境是无效的,那末基于散布式锁的怎么实现呢?
常见的散布式锁的实现以下图:
基于数据库
悲观锁
悲观锁(Pessimistic Lock)顾名思义为很悲观的锁,每次在拿数据的时候都会上锁。这样他人想拿数据就被挡住,直到悲观锁被释放,悲观锁中的同享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程,但是在效力方面,处理加锁的机制会产生额外的开消,且容易产生死锁。
实现原理
悲观并发控制实际上是"先取锁再访问"的守旧策略,为数据处理的安全提供了保证.
具体实现
例如通过悲观锁来实现库存扣减的伪代码以下:
// 对库存记录进行行锁
SELECT *FROM sys_goods s WHERE s.Id=’1′ FOR UPDATE;
//履行库存扣减
update sys_stock s set s.stockQty=s.stockQty-#{number} where s.goodId=1 and s.stockQty>0;
//提交事务,自动释放悲观锁。
乐观锁
简介
乐观锁是基于数据版本号(version)的机制来实现的。数据库表添加"version"字段, 读取出数据时,将此版本号读出,在更新进程中,会对版本号进行比较,如果是一致的,则会成功履行本次操作,且版本号加1,如果版本号不一致,则会更新失败。
实现原理
相对悲观锁,乐观锁的实现不会使用到数据库的锁机制,乐观锁的原理使用的CAS的机制来实现的,CAS(Compare-and-Swap)即比较并替换.
- 1、比较:读取到了一个值A,在将其更新为B之前,检查原值会不会仍为A(未被其他线程改动).
- 2、设置:如果是未发送变化,则将A更新为B结束。如果产生变化,则甚么都不做。
具体实现
例如乐观锁来实现库存扣减的伪代码以下:
// 查询库存记录,获得版本号
SELECT stockQty,version FROM sys_goods s WHERE s.Id=’1′
//履行库存扣减,避免出现超卖
update sys_stock s set
s.stockQty=s.stockQty-#{number},
s.version=version+1
where s.goodId=1 and s.stockQty>0 and version=#{version};
Redis实现散布式锁
关于Redis散布式锁的实现,已在前期的文章中进行了讲授,大家可以参考以下文章
Spring Boot 实现Redis散布式锁原理
Spring Boot 集成Redisson实现散布式锁详细案例
Zooker实现散布式锁
Zookper实现散布式锁,主要是利用zookeeper节点的临时和有序性来实现。
加锁进程
当客户端1要求时,Zookeeper客户端会创建一个持久节点Locks节点,如果客户端1想获得锁,会在locks节点下创建临时节点/node_000000,如果查找Locks下面所有临时有序子节点,当自己为最小的节点是则获得锁成功。
当客户端2尝试获得锁时,也会查看locks下面的临时节点,判断自己的节点/node_000001是不是是最小,如果不是最小则获得锁失败,客户端2会向它排序靠前的节点node_000000注册watch事件,用来监听node_000000会不会存在,虽然抢锁失败,但是node_000001进入等待状态。
释放锁的进程
Zookeeper的客户端业务完成或客户端产生故障,都会删除临时节点并且释放锁。如果是任务完成,客户端1还会显式调用删除node_000000的指令。
例如上述图,客户端1断开,临时节点node_000000已被删除,而此时node_000001通过watcher监听发现自己为为最小的临时节点,所以获得锁成功。
异常场景分析
客户端1创建临时节点后,会与Zookeeper服务器保护一个Session,这个Session会依赖客户端 定时心跳来保持连接。由于网路异常缘由,Zookeeper长时间收不到客户端1的心跳,就认为这个Session过期了,也会把这个临时节点删除,此时客户端2创建临时节点能够获得锁成功。当客户端网络恢复正常后,它依然认为持有锁,此时就会造成锁冲突。
具体实现
Zookeeper实现散布式锁,可以采取Curator实现散布式锁,关于SpringBoot如何集成Curator,大家可以参考以下文章:
Java Spring Boot 集成Zookeeper
Zookpeer实现散布式锁实现库存扣减
小结:
关于散布式锁的实现的对照,详情请查看下图:
总结
本文详细的介绍了几种散布式锁的实现和使用,业务需要根据场景选择适合的散布式锁的实现,如有疑问,请随时反馈。
到此这篇关于Redis常见散布锁的原理和实现的文章就介绍到这了,更多相关Redis散布锁原理内容请搜索之前的文章或继续浏览下面的相关文章希望大家以后多多支持!
文章来源:丸子建站
文章标题:Redis常见散布锁的原理和实现
https://www.wanzijz.com/view/51253.html