当前位置:首页 > 开发语言 > 正文

redis分布式锁怎么实现 基于redis的分布式锁

redis分布式锁怎么实现 基于redis的分布式锁

大家好,关于redis分布式锁怎么实现很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于基于redis的分布式锁的知识点,相信应该可以解决大家的一些困惑和...

大家好,关于redis分布式锁怎么实现很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于基于redis的分布式锁的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!

redis与zookeeper分布式锁区别

您好,Redis与Zookeeper的分布式锁的区别如下:

1.实现方式不同:Redis分布式锁是基于Redis单机实现的,而Zookeeper分布式锁是基于Zookeeper集群实现的。

2.锁的粒度不同:Redis分布式锁的锁粒度是基于某个具体的业务逻辑实现的,而Zookeeper分布式锁的锁粒度是基于Zookeeper节点实现的。

3.锁的可靠性不同:Redis分布式锁在单机故障或网络故障时可能会出现锁失效的情况,而Zookeeper分布式锁在Zookeeper集群中有多个节点存储锁信息,所以具有更高的可靠性。

4.性能不同:Redis分布式锁的性能较高,因为它是基于内存实现的,而Zookeeper分布式锁的性能相对较低,因为它需要进行网络通信。

5.应用场景不同:Redis分布式锁适用于锁持有时间较短,竞争锁的客户端数量较少的场景,而Zookeeper分布式锁适用于锁持有时间较长,竞争锁的客户端数量较多的场景。

Redis分布式锁的原理是什么如何续期

分布式锁的需求产生

分布式锁的需求是伴随着应用分布式部署而来的,在单体应用,且只部署一台服务器的情况下,通过java的同步锁即可实现。同步锁,即是一个原子性的操作。

那么当应用进行了分布式部署,应用有多个服务,这个时候应用服务端就没有一个可提供原子性操作的地方了,Redis性能高,且是单线程,因此可提供一个原子性操作的地方,利用它,就可以实现分布式锁。

用场景说话,使用Redis分布式锁的场景如下图所示:

如下图所示,随后会根据场景说明分布式锁及续期相关问题的来龙去脉。

图中序号1:进来一个请求,这个请求要求我们保存一个“订单A”;图中序号2:2.1步,请求进来,首先去尝试设置一个Redis值,他的键就是订单号“订单A”,如果尝试成功,则代表我这个线程是第一次设置,相当于我拿到了这个锁;如果尝试失败,那么,可以抛出异常或者等待一段时候后再次重试,这里可以根据业务场景的不同采取不同的策略。这里的关键是在Redis中的操作是单线程的,因此该操作是原子性的。2.2步,为了防止应用服务意外中断,Redis中的数据一直存活,消耗资源,需要设置一个超时时间。(如果为了严谨,可以将2.1,2.2两步封装成一个lua脚本部署在Redis服务器上)图中序号3:情况A,这个时候是当Redis的key还未失效,程序就已经执行完成,且删除了Redis中的数据,一切正常;情况B:就是需要续期的场景,如果要避免这个场景的出现,可以将Rediskey的失效时间设置长一点,可以应对大多数业务。如果要彻底解决,可以在应用端添加一个Redis锁的注册中心,然后起一个监听线程去监听这个注册中心,发现有锁还在被持有,但是Redis已经快过期了,则修改相应key的失效时间,进行续期。

Java语言如何正确实现Redis分布式锁

和大家分享我的经验,如何用redis提供的一个简单接口,轻松实现redis分布式锁。

在开始之前,我先简单介绍下redis的性能。

高效的Redis

Redis本身是单线程的,这样带来的好处是能够提高读写效率。多线程通常来说会有上下文切换带来的时间损耗,而redis通过绑定单个CPU到某块内存,实现了上下文切换的最小开销,因此这种场景反而比多线程还要高效。

不安全的Redis

但是,如果有不同的节点同时要对Redis中的同一个数据进行操作,由于是来自不同Redis服务器,就会发生线程不安全的情况。

举例有两个功能函数X和Y(也可以看做是两个服务器节点),二者功能相同,都要执行读取Redis中变量P,并且对其加一的操作。如果是线程安全的,那么X和Y分别执行完之后,P的值应该比原来增加2,但是由于函数XY互相独立,那就可能发生下面这种情况:

1X读取P

2Y读取P

3X将P+1写回Redis

4Y将P+1写回Redis

执行结束后,P的值却变成了P+1,而不是P+2。

这就是线程不安全导致的结果。

redis的分布式锁

那么如何用Redis来避免上面的情况呢。

Redis对外开放了一个非常厉害的api,目前经常被大家用来做分布式锁,是绝对的线程安全,这个函数就是SETkeyfieldvalue加上NX参数。这个NX参数可是了不得,通常来说,set函数是不管field字段是否存在,只要写入成功就会返回1,但是如果增加了NX参数,那么如果field值在redis中已经存在,就会返回nil,否则才返回1。因此可以通过这个函数来执行加锁操作,如果返回值不为nil,则加锁成功,否则代表有其他线程在操作数据,当前请求需要等待。

不仅如此,为了避免死锁,SET还有一个参数为EX,即EX毫秒后,field会自动清空。

此外,还有PX,XX参数,具体含义见如下文档。

以上就是我在工作中总结的防止redis并发的方式,如果你有其他想法,欢迎在下方评论区与我沟通。

我是苏苏思量,来自BAT的java开发工程师,每天分享技术见闻,欢迎关注我,与我共同进步。

关于redis分布式锁怎么实现的内容到此结束,希望对大家有所帮助。

最新文章