分布式锁实现方式有很多种,其中最常用的就是用redis或者zk来实现分布式锁,本篇将以redis作为分布式锁来进行展开;
redission是什么?
Redisson在基于NIO的Netty框架上,充分的利用了Redis键值数据库提供的一系列优势,在Java实用工具包中常用接口的基础上,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。
当然,上面是官方的解释,其实redission就是java对redis的分布式锁做了一个实现,并暴露出一些内置的api供开发者调用。
redission实现分布式锁
利用该框架暴露出来的接口,获取锁对象: RLock lock = redission.getLock('order_no'); 加锁:lock .lock(); 解锁:lock.unlock();
代码语言:txt复制 RLock lock = redission.getLock('order_no');
lock.lock();
try{
//执行业务代码:生成订单号
String orderNo = RandomUtils.genRandom("B1");
} finally{
lock.unlock();
}
底层原理
解释一下:
- 加锁 1.1. 加锁成功:底层线程开启一个watch dog操作,每10s查看当前的锁是否被当前线程持有,如果持有,则每10s重置锁时间为30s 1.2. 加锁失败:同步阻塞等待,不断尝试加锁(while(true))
- 根据hash算法选择redis集群中的一个节点存入key,然后执行一段lua脚本(为什么要用lua脚本呢?因为使用lua脚本执行多个redis操作可以保证操作的原子性)
- 解锁 图片引用自:https://www.cnblogs.com/AnXinliang/p/10019389.html
redission分布式锁优缺点
- watch dog自动延期机制,无需手动对锁时间进行续期
- 可重入加锁机制(如果已经获得了该锁,则在本次操作中可以重复加锁不阻塞,相当于AQS里面信号量,调用一次state 的值 1,释放一次state值-1 ,其他线程访问的时候state必须为0)
- 释放锁机制