1. ZooKeeper分布式锁
1.1 排他锁实现分布式锁
面试官:知道Zookeeper有什么应用场景吗?
目前地球村里大型公司部署的分布式技术,绝大部分都是由Zookeeper提供底层的技术支持,所以Zookeeper多么重要就不用我多说了吧。
我们可以利用Zookeeper来完成分布式系统涉及的各种核心功能,例如以下4种:
-
数据发布/订阅。可以用来实现配置中心。
-
命名服务。类似于UUID,可以生成全局唯一的ID。
-
集群管理。每一个服务器是一个子节点,可以用来检测到集群中机器的上/下线情况。
-
分布式锁。
胡广先讲下我们可以怎么利用Zookeeper来实现分布式锁,要实现分布式锁,分为获取锁和释放锁两个步骤。
ZooKeepr获取锁时会在/exclusive_lock
节点下创建子节点,如果创建成功则获得锁。如果创建失败,则访问Zookeeper的客户端会在该节点注册一个Watcher监听
,用来实时监控子节点的变更从而重新获得锁,这有点类似于线程的循环等待。
当要释放锁时,Zookeeper会删除该子节点,此时/exclusive_lock
节点下就有空位了。Watcher监听则通知客户端可以重新创建子节点来获得锁资源。
1.2 共享锁实现分布式锁
面试官:你说的是排他锁,共享锁呢?
大家有没发现,上面分布式锁的实现方式是排他锁,我们也可以使用共享锁的实现方式,来看看两者的区别。
排他锁,又称为写锁或独占锁,是一种基本的锁类型。如果事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只允许事务T1对O1进行读取和更新操作,其他任何事务都不能再对这个数据对象进行任何类型的操作——直到T1释放了排他锁。
共享锁,又称为读锁,同样是一种基本的锁类型。如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对这个数据对象加共享锁——直到该数据对象上的所有共享锁都被释放。
Zookeeper以共享锁方式来实现分布式锁,每次读、写请求都会去创建子节点,这是一个类似于“/shared_lock/[Hostname]-请求类型-序号
”的临时顺序节点。
每一个要获得分布式锁的客户端都会去获取子节点列表,同时注册Watcher监听,读、写这两步有不同的步骤。
(1)获取读锁的话,如果前面比自己小的序号没有写请求,则表示可以读。
(2)获取写锁的话,只有在自己是序号最小的情况下,才可以读成功。
另外共享锁的释放锁和排他锁都是一样的,只需要删除所创建的子节点就可以。
1.3 共享锁羊群效应
面试官:有没听说过共享锁的羊群效应?
大家要注意下,共享锁来实现分布式锁,在集群规模比较大的场景下,可能会出现羊群效应。
什么是羊群效应?我们看看百度百科的解释。
羊群效应是个人的观念或行为由于真实的或想象的群体的影响或压力,而向与多数人相一致的方向变化的现象。
其实共享锁的特别之处,在于每次读、写请求都要注册Watcher监听来获取子节点列表,特别是数量更多的读请求,每1分钟可能是上百万次的请求。
以共享锁来实现,子节点列表只要每次一变动,就要通知所有的服务器客户端。这明显造成了短时间大量的事件通知,给Zookeeper带来的性能消耗是巨大的。
1.4 处理羊群效应
面试官:那怎么解决呢?
如何看待共享锁带来的羊群效应,我们从两个方面来看待。如果在集群不大的情况下羊群效应发生带来的影响不会太大,而且这种设计简单实用。
而如果在集群规模大的场景下,我们可以这样改进。客户端的读、写请求首先获取子节点列表,但都不注册Watcher监听。
(1)读请求:只向比自己序号小的最后一个写请求节点注册Watcher监听。
(2)写请求:只向比自己序号小的最后一个节点注册Watcher监听。
这样的设计就可以避免羊群效应,主要是从监听子节点列表,改进为只监听某个子节点。
2. Kafka应用场景
2.1 Kafka应用场景
面试官:Kafka应用场景呢,知道Kafka是怎么利用Zookeeper吗?
胡广了解到的Kafka利用Zookeeper的主要有 4 点,我们来看看。
(1)使用Zookeeper来对所有Broker服务器、Topic进行管理。Broker启动后都会到Zookeeper上创建属于自己的临时节点,其节点路径为/broker/ids/[0…N]
,注册Topic节点也是一样。
(2)而在Kafka防止消费重复消费方面,消费者消费消息后,都会在消息分区写入临时节点,代表该消息已消费。
(3)另外在Kafka生产者负载均衡方面,Kafka消息生产者会通过监听Broker节点列表,负载均衡地分发到某一个Broker。
(4)在消费者负载均衡有两方面。一方面,每一个消费者服务器都会在Zookeeper创建消费者节点。当有新消息时,Kafka就可以通过Zookeeper的消费者节点列表负载均衡地通知某个消费者;另一方面,Kafka将一个Topic分成了多个分区,多个分区由不同的Broker处理,这是实现对Broker的负载均衡。
你好,我是胡广。 致力于为帮助兄弟们的学习方式、面试困难、入职经验少走弯路而写博客 🌹🌹🌹 坚持每天两篇高质量文章输出,加油!!!🤩
如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 😄 (^ ~ ^) 。想看更多 那就点个关注 吧 我会尽力带来有趣的内容 。
😎感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以 给我留言咨询,希望帮助更多的人
更多专栏:
📊 Java设计模式宝典:从入门到精通(持续更新)📝 Java基础知识:GoGoGo(持续更新)
⚽ Java面试宝典:从入门到精通(持续更新)
🌟 程序员的那些事~(乐一乐)
🤩 Redis知识、及面试(持续更新)
🚀 Kafka知识文章专栏(持续更新)
🎨 Nginx知识讲解专栏(持续更新)
📡 未完待续。。。
🎯 未完待续。。。
🔍 未完待续。。。
感谢订阅专栏 三连文章