我的编程空间,编程开发者的网络收藏夹
学习永远不晚

redis分布式锁与zk分布式锁的对比分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

redis分布式锁与zk分布式锁的对比分析

在分布式环境下,传统的jvm级别的锁会失效,那么分布式锁就是非常有必要的一个技术,一般我们可以通过redis,zk等技术来实现我们的分布式锁

redis实现分布式锁

原理

我们都知道redis的处理读写请求是单线程的,这种情况就不会发生并发的问题,其实实现起来很简单,就是使用redis的 setnx 命令实现,该命令如果redis中存在当前key,就会返回0,否者插入成功。

那么就可以获取锁的时候添加一个k-v值(任意的一个值)到redis,释放锁的时候就删除,这样就使用redis实现了一个分布式锁,相当于分布式中所谓的锁概念其实就相当一个redis或者zk中的一个值,有这个值就加锁成功 

能实现的锁类型

1、普通的锁

2、读写锁:大致就是给当前的key设置一个特定的值标识当前锁是读锁还是写锁,读与读之间不互斥,相当与就是没有锁,读与写,写于写之间进行互斥,这个锁的目的是为了解决缓存一致性的问题,这个问题下面来分析

3、红锁:底层原理涉及到redis半数写入机制,针对主从架构中主节点挂了但是数据还未同步到从节点的问题,实现的方式就是当一半以上的节点都写入成功了才返回给客户端成功的提示,而不是主节点写入成功就返回,但是这种情况下的效率比较慢

注意事项 

1、死锁的情况:出现死锁的情况有以下几种情

(1)应用程序没有正常的释放锁:比如程序抛出异常之类导致释放锁代码没有执行; 

解决方案:需要把释放锁的代码写在finally模块里面。

(2)锁还没有释放redis宕机:这个时候本来应该删除的key因为redis服务停掉了导致删除不成功,出现死锁的问题 

解决方案:给每一个key设置一个超时时间,超时了自动清除。

2、锁永久失效的情况:出现原因是因为当前线程A还没有运行完然后锁因为过期时间的原因自动删除了,这个时候其他线程B又能拿到这个锁在redis中创建一个对应的k-v值,然后线程A执行到释放锁的时候会删除掉对应key的值,这个时候删除的值是线程B对应的锁,而不是线程A的,这样在高并发的情况下就有可能导致锁压根不生效 

解决方案:在进行设值的时候,value值设置成能标识当前线程的一个值,比如在当前线程中创建一个uuid,然后在释放锁的时候也要比较value值,相同的情况就表示是当前线程对应的锁,允许释放,否则不允许释放。

3、会存在锁提前释放的问题:当然这个问题也是引起上面第2个问题的根本原因,但是解决方案是不一样的 

解决方案:在获得锁之后,处理业务逻辑的过程中,新建一个timer来定时的去重置锁的生命周期,当然前提是当前业务逻辑还在执行,这个定时的频率一般设置为锁生命周期的1/3,redisson中的 **看门狗 **其实内部就是这样实现。 

4、主从结构中锁丢失:上面 红锁 已经说明了情况

zk实现分布式锁

原理

zk实现分布式锁的原理其实和redis很像,都是往里面插入对应的值,通过zk的create命令来实现,zk中的值是通过树形结构,类似与文件夹的层级目录一样,如果当前节点存在那么create命令就会执行失败,这种情况就代表其他的线程已经获取到了锁,当前线程通过get -w /xxx的命令对当前锁进行监听,如果当前锁被其他线程释放,那么当前线程会重新参与竞争锁 

能实现的锁类型

1、非公平锁:就是通过create创建节点,谁创建成功谁就获得了锁,其他锁对这个节点进行监听,当释放锁的时候,所有线程又来竞争这个锁,但是这种情况会引发羊群效应,就是当一个节点被释放的时候所有的线程都会来竞争,浪费性能

2、公平锁:通过zk的临时有序节点来实现,当前线程创建一个临时顺序节点,然后判断当前节点是不是最小的节点,如果时就获得锁,如果不是那么就监听他的上一个节点,等到释放锁的时候会通知后一个节点,然后重复以上判断,这个就是公平锁的实现方案,这样就可以避免羊群效应,减轻服务器的压力,但是这种情况可能会发生幽灵节点的产生导致死锁

幽灵节点:就是客户端发送创建命令之后,zk已经成功创建,但是在响应的时候发生了宕机,这个时候客户端以为没有成功,但是服务器端实际上已经有了,但是这个客户端不知道,就不会去释放,就造成了幽灵节点,通过 Protection模式能够避免这个问题,这个的本质就是在节点前面加上一个唯一的标识,如uuid,人客户端再次请求的时候会比较这个uuid,如果有就认为创建成功了,使用curator的protection模式原理就是这样的,一下附一张公平锁实现原理图:

redis分布式锁与zk分布式锁的对比分析

3、读写锁:实现原理和公平锁差不多,只是在创建每一个节点的时候标识当前节点时读锁(加read标识)还是写锁(加write标识)

两种锁的对比

分布式系统中通常要考虑CAP的,一致性,可用性和分区容错性,很多场景下是很难同时保证CAP的,这个时候就得做出取舍,分布式锁也是这样的。

redis分布式锁:

  • 优点:性能高,能保证AP,保证其高可用,
  • 缺点:但是不能保证其一致性,原因就是在redis集群+主从的结构中,数据是通过分片存储的,但是这个时候当一个master节点挂了之后,slave节点还未同步到master节点的数据,导致数据丢失,万一丢失的数据刚好是你的锁,那么就有可能造成并发问题,所以不能保证强一致性,这种情况下可以通过redisson的红锁来解决,解决的原理其实就是redis的半数写入机制,但是这样完全降低了redis的性能,所以一般情况下是不采用的,zk其实能保证其一致性的原因就是其半数写入机制加上其 leader选举的逻辑实现

zk分布式锁:

  • 优点:能够保证其一致性,每个节点的创建都会同时写入leader和follwer节点,半数以上写入成功才返回,如果leader节点挂了之后选举的流程会优先选举zxid(事务Id)最大的节点,就是选数据最全的,又因为半数写入的机制这样就不会导致丢数据(ZAB协议)
  • 缺点:性能没有redis高 

以上已经说明了两种分布式锁实现的方式及其原理,怎么选择以实际业务为准

缓存一致性:数据库于缓存的结果不一样

双写一致性问题(图网上找的,懒得画了)

redis分布式锁与zk分布式锁的对比分析

读写一致性问题

redis分布式锁与zk分布式锁的对比分析

解决方案:

(1)对于我们的用户自己的订单数据,或者用户信息数据,或者说高并发场景下能容忍短时间的数据不一致,这些都可以采用添加过期时间(本来进入到缓存的数据就不要求强一致性,这种方式能解决大多数的情况,这种方式比较推荐也最常用)

(2)延迟双删:就是在更新了数据库之后等一小段时间再删除缓存(这种的缺点就是对于非高并发的请求,出现缓存一致性的问题概率本来就不大,但是却人为的降低了代码的性能)

(3)采用我们redis提供的分布式读写锁,读读之间不阻塞,一旦有数据更新那么读的操作就阻塞,等待更新+删除缓存的操作结束之后再进行读,这个情况虽然能真正的保证数据的一致性,但是加锁了之后会进行阻塞,高并发情况下的性能就降低了

(4)使用阿里巴巴的cannal组件,类似于一个mysql的slave节点,监听着mysql的binlog日志文件,有变化就会主动的通知我们(推荐)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

redis分布式锁与zk分布式锁的对比分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

redis分布式锁与zk分布式锁的对比分析

目录Redis实现分布式锁原理能实现的锁类型注意事项 zk实现分布式锁原理能实现的锁类型两种锁的对比在分布式环境下,传统的jvm级别的锁会失效,那么分布式锁就是非常有必要的一个技术,一般我们可以通过redis,zk等技术来实现我们的分布式锁
2022-11-18

【分布式】分布式锁

目录 一、分布式锁介绍二、基于 Redis 实现分布式锁1. 如何基于 Redis 实现一个最简易的分布式锁?2.为什么要给锁设置一个过期时间?3. 如何实现锁的优雅续期?4. 如何实现可重入锁? 一、分布式锁介绍 单机多线
2023-08-17

Redis超详细分析分布式锁

目录分布式锁应用场景使用Redis 实现分布式锁单机版Redis实现分布式锁使用原生Jedis实现使用Springboot实现分布式锁为了保证一个方法在高并发情况下的同一时间只能被同一个线程执行,在传统单体应用单机部署的情况下,可以使用J
2022-07-27

分布式锁的原理及Redis怎么实现分布式锁

这篇文章主要介绍“分布式锁的原理及Redis怎么实现分布式锁”,在日常操作中,相信很多人在分布式锁的原理及Redis怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”分布式锁的原理及Redis怎么
2023-02-02

Redis中分布式锁Redlock的示例分析

这篇文章主要介绍了Redis中分布式锁Redlock的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Redlock实现库Java Redisson Star 9458
2023-06-16

redis实现分布式锁实例分析

本文小编为大家详细介绍“redis实现分布式锁实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“redis实现分布式锁实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1、业务场景引入模拟一个电商系统,
2023-06-29

Redis分布式锁实例分析讲解

目录1 一人一单并发安全问题2 分布式锁的原理和实现2.1 什么是分布式锁2.2 分布式锁的实现1 一人一单并发安全问题之前一人一单的业务使用的悲观锁,在分布式系统下,是无法生效的。理想的情况下是这样的:一个线程成功获取互斥锁,并对查询
2022-12-06

Redis实现分布式锁

单体锁存在的问题 在单体应用中,如果我们对共享数据不进行加锁操作,多线程操作共享数据时会出现数据一致性问题。 (下述实例是一个简单的下单问题:从redis中获取库存,检查库存是否够,>0才允许下单) 我们的解决办法通常是加锁。如下加单体锁
2023-08-16

Redis分布式锁的实现方式

目录一、分布式锁是什么1、获取锁2、释放锁二、代码实例上面代码存在锁误删问题:三、基于SETNX实现的分布式锁存在下面几个问题1、不可重入2、不可重试3、超时释放4、主从一致性四、Redisson实现分布式锁1、pom2、配置类3、测试类五
2023-04-03

Redis分布式锁之红锁的实现

目录一、问题二、办法三、原理四、实战一、问题分布式锁,当我们请求一个分布式锁的时候,成功了,但是这时候slave还没有复制我们的锁,masterDown了,我们的应用继续请求锁的时候,会从继任了master的原slave上申请,也会成功。
2022-08-09

python实现redis分布式锁

#!/usr/bin/env python# coding=utf-8import timeimport redisclass RedisLock(object): def __init__(self, key): se
2023-01-31

编程热搜

目录