目录
- 什么是分布式锁?
- 前言
- 实现要点
-
正确的redis分布式锁实现
- 错误加锁方式
- 错误解锁方式
- 正确加锁释放锁方式
什么是分布式锁?
要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。
线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state)。
进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronized等线程锁实现进程锁。
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
前言
现在的业务场景越来越复杂,使用的架构也就越来越复杂,分布式、高并发已经是业务要求的常态。像腾讯系的不少服务,还有CDN优化、异地多备份等处理。
说到分布式,就必然涉及到分布式锁的概念,如何保证不同机器不同线程的分布式锁同步呢?
实现要点
- 互斥性,同一时刻,智能有一个客户端持有锁。
- 防止死锁发生,如果持有锁的客户端崩溃没有主动释放锁,也要保证锁可以正常释放及其他客户端可以正常加锁。
- 加锁和释放锁必须是同一个客户端。
- 容错性,只有redis还有节点存活,就可以进行正常的加锁解锁操作。
正确的redis分布式锁实现
错误加锁方式
错误方式一
保证互斥和防止死锁,首先想到的使用redis的setnx命令保证互斥,为了防止死锁,锁需要设置一个超时时间。
?
1 2 3 4 5 6 7 |
|
在多线程并发环境下,任何非原子性的操作,都可能导致问题。这段代码中,如果设置过期时间时,redis实例崩溃,就无法设置过期时间。如果客户端没有正确的释放锁,那么该锁(永远不会过期),就永远不会被释放。
错误方式二
比较容易想到的就是设置值和超时时间为原子原子操作就可以解决问题。那使用setnx命令,将value设置为过期时间不就ok了吗?
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
乍看之下,没有什么问题。但仔细分析,有如下问题:
value设置为过期时间,就要求各个客户端严格的时钟同步,这就需要使用到同步时钟。即使有同步时钟,分布式的服务器一般来说时间肯定是存在少许误差的。
锁过期时,使用 jedis.getSet虽然可以保证只有一个线程设置成功,但是不能保证加锁和解锁为同一个客户端,因为没有标志锁是哪个客户端设置的嘛。
错误解锁方式
解锁错误方式一
直接删除key
?
1 2 3 4 |
|
简单粗暴,直接解锁,但是不是自己加锁的,也会被删除,这好像有点太随意了吧!
解锁错误方式二
判断自己是不是锁的持有者,如果是,则只有持有者才可以释放锁。
?
1 2 3 4 5 6 |
|
看起来很完美啊,但是如果你判断的时候锁是自己持有的,这时锁超时自动释放了。然后又被其他客户端重新上锁,然后当前线程执行到jedis.del(key),这样这个线程不就删除了其他线程上的锁嘛,好像有点乱套了哦!
正确加锁释放锁方式
基本上避免了以上几种错误方式之外,就是正确的方式了。要满足以下几个条件:
命令必须保证互斥
设置的key必须要有过期时间,防止崩溃时锁无法释放
value使用唯一id标志每个客户端,保证只有锁的持有者才可以释放锁
加锁直接使用set命令同时设置唯一id和过期时间;其中解锁稍微复杂些,加锁之后可以返回唯一id,标志此锁是该客户端锁拥有;释放锁时要先判断拥有者是否是自己,然后删除,这个需要redis的lua脚本保证两个命令的原子性执行。
下面是具体的加锁和释放锁的代码:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
|
单是一个redis的分布式锁就有这么多道道,不知道你是否看明白了?留言讨论下吧!
总结
以上所述是小编给大家介绍的Redis分布式锁的实现方式(redis面试题),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
原文链接:https://blog.csdn.net/chanllenge/article/details/102983597
本文链接:https://my.lmcjl.com/post/11155.html
4 评论