提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
首先呢,本文参考了这篇文章https://www.cnblogs.com/keeya/p/14332131.htm,这个文章被抄袭了很多次,如果你搜一下【Redisson的看门狗机制】会出现很多个一样的内容,但是个人阅读源码后,发现里面有部分说的不是特别的准确,和我个人理解的对不上。那么在此之上,我就把我对redis实现分布式锁中看门狗这个机制,表达一下我的理解,为了保存逻辑的完整性,我索性也就搬运了这个文章的内容,但是文中表达一下我的个人理解:
背景
据Redisson官网的介绍,Redisson是一个Java Redis客户端,与Spring 提供给我们的 RedisTemplate 工具没有本质的区别,可以把它看做是一个功能更强大的客户端(虽然官网上声称Redisson不只是一个Java Redis客户端)
强烈推荐下阅读redisson的中文官网
我想我们用到 Redisson 最多的场景一定是分布式锁,一个基础的分布式锁具有三个特性:
- 互斥:在分布式高并发的条件下,需要保证,同一时刻只能有一个线程获得锁,这是最最基本的一点。
- 防止死锁:在分布式高并发的条件下,比如有个线程获得锁的同时,还没有来得及去释放锁,就因为系统故障或者其它原因使它无法执行释放锁的命令,导致其它线程都无法获得锁,造成死锁。
- 可重入:我们知道ReentrantLock是可重入锁,那它的特点就是同一个线程可以重复拿到同一个资源的锁。
实现的方案有很多,这里,就以我们平时在网上常看到的redis分布式锁方案为例,来对比看看 Redisson 提供的分布式锁有什么高级的地方。
普通的 Redis 分布式锁的缺陷
我们在网上看到的redis分布式锁的工具方法,大都满足互斥、防止死锁的特性,有些工具方法会满足可重入特性。
如果只满足上述3种特性会有哪些隐患呢?redis分布式锁无法自动续期,比如,一个锁设置了1分钟超时释放,如果拿到这个锁的线程在一分钟内没有执行完毕,那么这个锁就会被其他线程拿到,可能会导致严重的线上问题,我已经在秒杀系统故障排查文章中,看到好多因为这个缺陷导致的超卖了。
Redisson 提供的分布式锁
watch dog 的自动延期机制
Redisson 锁的加锁机制如上图所示,线程去获取锁,获取成功则执行lua脚本,保存数据到redis数据库。
如果获取失败: 一直通过while循环尝试获取锁(可自定义等待时间,超时后返回失败),获取成功后,执行lua脚本,保存数据到redis数据库。
Redisson提供的分布式锁是支持锁自动续期的,也就是说,如果线程仍旧没有执行完,那么redisson会自动给redis中的目标key延长超时时间,这在Redisson中称之为 Watch Dog 机制。
同时 redisson 还有公平锁、读写锁的实现。
使用样例如下,附有方法的详细机制释义
private void redissonDoc() throws InterruptedException {
//1. 普通的可重入锁
RLock lock = redissonClient.getLock("generalLock");
//