redis watchdog_花5min就能搞清楚redis和zookeeper分布式锁的区别,太有必要读一下了...

v2-bdd3ba6adcd9ad12a93a27bbde7d7eb7_1440w.jpg?source=172ae18b

今天有个师弟问到了我这个问题,我说网络上文章有很多,自己查一下吧,他说读了好几篇还是不太清楚,于是我就搜了一下,呃……

最终还是耐心地给他上了一课,他听完以后感激涕零,想到他晚上回到家,倒上二两散装白酒,跟女友分享今天学习到新技能时的喜悦,我欣慰地笑了。

一、目标

锁,解决的是多线程或多进程情况下的数据一致性问题;分布式锁,解决的是分布式集群下的数据一致性问题。

本身这个事情就没有多复杂,问起这个问题的人起码都使用过redis和zookeeper吧,在这里我就不多哔哔了,咱们直接搞起来。

两者的区别,根本上在于两者的实现不同。

二、单机

单机场景下,首选redis实现分布式锁。

理由如下(同时也是redis的特点):

1.redis完全基于内存

2.redis单线程多路复用,减少了多个线程创建时的开销,避免了不必要的上下文切换以及资源竞争导致的锁开销

3.全程hash结构

总之就一个字,速度贼鸡儿快!

而zk的话是目录树结构,性能完全没得比。

有些人说,哎呀,redis可能会丢数据的呀~

我不知道这话从哪听到的,纯属扯淡!现在我拍着胸脯向你保证,redis他妈的不丢数据!

redis持久化方式有两种对吧,rdb和aof。rdb遇到redis宕机,的确是会丢掉上次bgsave到目前的数据,可是你能选择aof模式啊。

aof模式下还需要做件小事情,打开redis.conf文件,找到${appendfsync}这个字段,给它配置成always,搞定,如此简单。

${appendfsync}:

no:完全依赖于操作系统的调度

everysec:每隔一秒调用一次fsync

always:每次写命令都会调用fsync,最安全,性能差

fsync的意思是说将缓存中的数据刷到磁盘。需要知道,为了提高速度,文件系统也是有缓存的,运维工程师每次释放linux系统的内存前都要执行sync命令,就是干这个的。

v2-06b50229e3a6fee144d82bbd1c4133eb_b.jpg

还有些人说,我选择zk实现,zk的ephemeral节点在连接端挂掉之后能够自己删除~

呵呵,你给redis设置个过期时间不就OK了吗?业务未执行完担心锁过期?你可以做续时啊,你不会做你可以使用现成的redisson啊,redisson有watch dog能帮你搞定的。

所以单实例场景下,redis完全莫问忒。唯一要注意的就是redis的内存淘汰,别鸡儿莫名其妙数据给删了都不知道。内存淘汰策略的话可以选择noeviction,到了阈值就抛异常,获取锁的时候要写数据嘛,这样内存满了就不能写了。

但是如今稍微大一些的系统,都不太可能使用单实例,redis和zk实现的分布式锁主要区别也不是在单实例场景下。

三、集群

说起分布式集群,必然要提起的是CAP原则,CAP即Consistency、Availability、Partition tolerance,就是一致性、可用性和分区容错性,三者只能取其二,我们就是要从CP、AP来选则,为什么不选CA?因为选了CA就是单机版本了。

先说redis集群,redis集群是基于AP实现的,有3种模式:

第一种是master-slaver,简单的主从模式;

第二种是sentinel,叫哨兵模式,就是多了个哨兵,假如master宕机了,它帮你做主备切换,不用再人工干涉了;

第三种是cluster,叫集群模式,这种模式下多个节点存储不同的数据。节点上有个叫slot的玩意儿,将范围限制在0-16383,每次数据来了,通过crc16计算出一个结果,然后对16384取余数,通过这个数就知道哈希槽在哪个节点了,最终到对应的节点上存数据。需要知道的是,为了保证高可用,每个节点也引入了主从模式

v2-74811849b47f3c5642bccf7742055356_b.jpg

问题就出在这里,说一下redis主从复制过程:

1.从服务器连接主服务器,发送sync命令;

2.主服务器收到sync命令后,开始执行bgsave命令生成rdb文件并使用缓冲区记录此后执行的所有写命令;

3.主服务器bgsave执行完后,向所有从服务器发送rdb文件,并在发送期间继续记录被执行的写命令;

4.从服务器收到rdb文件后丢弃所有旧数据,载入收到的快照;

5.主服务器发送完rdb文件后开始向从服务器发送缓冲区中的写命令;

6.从服务器完成对rdb文件的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

7.主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令

划重点,redis为了保证高可用,主从复制过程是异步的,也就是说,当客户端向master写了一个数据,master提交完就给你飞吻了,而不管slaver是否已经同步完成数据,这样写数据和同步数据各玩各的,同步数据过程中不影响写数据,这样叫做高可用,但也带来了以下两个问题。

问题1,主从复制丢数据

C1向master申请到了锁a,master在同步数据的过程中挂掉了,此时slaver还没有拿到锁a的数据,主备切换,slaver升级成master1,C2向master1申请锁a,申请成功

问题2,脑裂

C1向master申请到了锁a,master网络出问题了,sentinel收不到master的心跳,于是将slaver选举成master1,但此时还有些C端能够访问到master,假如此时C2能够访问到master,但C3访问的却是master1,于是C2在master上能够申请到锁b,C3在master1上也能够申请到锁b

当这两种情况出现的时候,锁肯定就有问题了,即便是RedLock来实现,也只能降低风险,而不能保证100%可靠。不要拿超级计算机上使用成千上万个redis单实例实现RedLock来杠。

顺便提醒一下,redis中rdb文件生成,不管是持久化还是主从复制,都要先copy完整的数据副本到内存中,所以必须要注意redis的内存量与当前系统的内存量。

下面说zk集群,zk集群是基于CP实现的,具有强一致性。而强一致性,则是通过ZAB(ZooKeeper Atomic Broadcast)协议实现的,即ZooKeeper原子播送协议。

ZAB协议支持自动恢复和原子播送,是专门为zk量身定做的一种一致性协议。

关于自动恢复是通过投票选举来实现的,有兴趣的伙伴可以自行查阅,我就懒得说了,这里专门讲一下原子播送。

原子播送即同步复制的过程,我们从其它的一致性协议2PC说起。

2PC协议,叫两阶段提交协议(Two-phase Commit),简单些来说:

第一阶段:表决(请求阶段)

事务协调者通知每个参与者准备提交或取消事务,然后进入表决过程,参与者要么在本地执行事务,但不提交;参与者将告知协调者自己的决策: 同意或取消

第二阶段:执行(提交阶段)

此时,协调者将基于请求阶段的投票结果进行决策: 提交或取消;当且仅当所有的参与者同意提交事务,协调者才通知所有的参与者提交事务,否则协调者将通知所有的参与者取消事务;参与者在接收到协调者发来的消息后将执行相应的操作

v2-6751af6a362c9a4127a26c14316ed6c7_b.jpg

2PC协议隐藏的问题中在这里我们仅仅需要关注的是同步阻塞,即同步过程中不允许有新的数据写入。

其他的一致性协议还有3PC、Paxos等,ZAB协议的过程可以参考2PC协议(但ZAB协议是过半有效),但实际上更像是Paxos协议的改进版本,由于比较复杂,这里放不下,咿,还听押韵的~就不说了。但是,他们都没有能够彻底解决同步阻塞的问题。

四、结论

redis和zk分布式锁的区别,关键就在于高可用性和强一致性的选择,redis的性能高于zk太多了,可在可靠性上又远远不如zk,具体场景下如何选择,只能仁者见仁,智者见智,老鼠的儿子会打洞了。

简单说一下,就是老生常谈的几个话题(和洋洋姐确认过了):

火车站窗口卖票:需要的是强一致性,zk的话性能堪忧,春运的时候岂不是炸了?

银行转账:需要的是最终一致性,redis的话不如zk可靠,需要做一些其它补偿。

网上购物:需要的是最终一致性,容错率更高,比如你看着还有俩,但是买不到了,也不是很严重对吧。

原创不易,点个赞再走呗!

Thanks♪(・ω・)ノ

--------------------------------

公众号:以镒称铢

出自<孙子兵法 · 军形>,故胜兵若以镒称铢,败兵若以铢称镒。胜者之战民也,若决积水于千仞之溪者,形也。

长按下图二维码关注,你将发现一个不一样的世界,君子引而不发,跃如也~

v2-01d33b473454110b39660d6214353bf4_b.jpg
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值