Redis分布式锁有哪些?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!我们通常使用的synchronized或者Lock都是线程锁,对同一个JVM进程内的多个线程有效。因为锁的本质 是内存中存放一个标记,记录获取锁的线程是谁,这个标记对每个线程都可见。然而我们启动的多个订单服务,就是多个JVM,内存中的锁显然是不共享的,每个JVM进程都有自己的 锁,自然无法保证线程的互斥了,这个时候我们就需要使免费云主机域名用到分布式锁了。常用的有三种解决方案:1.基于数据库实现 2.基于zookeeper的临时序列化节点实现 3.redis实现。本文我们介绍的就是redis的实现方式。
实现分布式锁要满足3点:多进程可见,互斥,可重入。1) 多进程可见 redis本身就是基于JVM之外的,因此满足多进程可见的要求。2) 互斥 即同一时间只能有一个进程获取锁标记,我们可以通过redis的setnx实现,只有第一次执行的才会成功并返回1,其它情况返回0。 释放锁
释放锁其实只需要把锁的key删除即可,使用del xxx指令。不过,如果在我们执行del之前,服务突然宕机,那么锁就永远无法删除了。所以我们可以通过setex 命令设置过期时间即可。上面的分布式锁实现了,但是这时候还可能出现另外2个问题:
一:获取锁时
setnx获取锁成功了,还没来得及setex服务就宕机了,由于这种非原子性的操作,死锁又发生了。其实redis提供了 nx 与 ex连用的命令。
二:释放锁时
1. 3个进程:A和B和C,在执行任务,并争抢锁,此时A获取了锁,并设置自动过期时间为10s
2. A开始执行业务,因为某种原因,业务阻塞,耗时超过了10秒,此时锁自动释放了
3. B恰好此时开始尝试获取锁,因为锁已经自动释放,成功获取锁
4. A此时业务执行完毕,执行释放锁逻辑(删除key),于是B的锁被释放了,而B其实还在执行业务
5. 此时进程C尝试获取锁,也成功了,因为A把B的锁删除了。
问题出现了:B和C同时获取了锁,违反了互斥性!如何解决这个问题呢?我们应该在删除锁之前,判断这个锁是否是自己设置的锁,如果不是(例如自己 的锁已经超时释放),那么就不要删除了。所以我们可以在set 锁时,存入当前线程的唯一标识!删除锁前,判断下里面的值是不是与自己标识释放一 致,如果不一致,说明不是自己的锁,就不要删除了。 按照上面方式实现分布式锁之后,就可以轻松解决大部分问题了。网上很多博客也都是这么实现的,但是仍然有些场景是不满足的,例如一个方法获取到锁之后,可能在方法内调这个方法此时就获取不到锁了。这个时候我们就需要把锁改进成可重入式锁了。 3) 重入锁: 也叫做递归锁,指的是在同一线程内,外层函数获得锁之后,内层递归函数仍然可以获取到该锁。换一种说法:同一个线程再次进入同步代码时,可以使用自己已获取到的锁。可重入锁可以避免因同一线程中多次获取锁而导致死锁发生。像synchronized就是一个重入锁,它是通过moniter函数记录当前线程信息来实现的。实现可重入锁需要考虑两点:
获取锁:首先尝试获取锁,如果获取失败,判断这个锁是否是自己的,如果是则允许再次获取, 而且必须记录重复获取锁的次数。
释放锁:释放锁不能直接删除了,因为锁是可重入的,如果锁进入了多次,在内层直接删除锁, 导致外部的业务在没有锁的情况下执行,会有安全问题。因此必须获取锁时累计重入的次数,释放时则减去重入次数,如果减到0,则可以删除锁。因此,存储在锁中的信息就必须包含:key、线程标识、重入次数。不能再使用简单的key-value结构, 这里推荐使用hash结构。
获取锁的脚本(注释删掉,不然运行报错)释放锁的脚本(注释删掉,不然运行报错)完整代码感谢各位的阅读!看完上述内容,你们对Redis分布式锁有哪些大概了解了吗?希望文章内容对大家有所帮助。如果想了解更多相关文章内容,欢迎关注百云行业资讯频道。
ORACLE数据库X86化是发展的一种趋势,通过多年的工作实践,整理了这篇X86平台RAC安装最佳实践。希望大家对X86平台的最佳实践有一定了解。文档从以下几个方面进行信息描述。硬件架构更多详细内容,可免费云主机域名以阅读GitHub上分享的PDF。https…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。