更新时间:2020-10-30 来源:黑马程序员 浏览量:
Master选举是一个在分布式系统中非常常见的应用场景。分布式最核心的特性就是能够将具有独立计算能力的系统单元部署在不同的机器上,构成一个完整的分布式系统。而与此同时,实际场景中往往也需要在这些分布在不同机器上的独立系统单元中选出一个所谓的“老大”,在计算机中,我们称之为Master。
在分布式系统中,Master往往用来协调集群中其他系统单元,具有对分布式系统状态变更的决定权。例如,在一些读写分离的应用场景中,客户端的写请求往往是由 Master来处理的;而在另一些场景中,Master则常常负责处理一些复杂的逻辑,并将处理结果同步给集群中其他系统单元。Master选举可以说是ZooKeeper最典型的应用场景了,接下来,我们就结合“一种海量数据处理与共享模型”这个具体例子来看看 ZooKeeper在集群Master选举中的应用场景。
在分布式环境中,经常会碰到这样的应用场景:集群中的所有系统单元需要对前端业务提供数据,比如一个商品
ID,或者是一个网站轮播广告的广告
ID(通常出现在一些广告投放系统中)等,而这些商品ID或是广告ID往往需要从一系列的海量数据处理中计算得到——这通常是一个非常耗费 I/O 和
CPU资源的过程。鉴于该计算过程的复杂性,如果让集群中的所有机器都执行这个计算逻辑的话,那么将耗费非常多的资源。一种比较好的方法就是只让集群中的部分,甚至只让其中的一台机器去处理数据计算,一旦计算出数据结果,就可以共享给整个集群中的其他所有客户端机器,这样可以大大减少重复劳动,提升性能。 这里我们以一个简单的广告投放系统后台场景为例来讲解这个模型。
整个系统大体上可以分成客户端集群、分布式缓存系统、海量数据处理总线和 ZooKeeper四个部分
首先我们来看整个系统的运行机制。图中的Client集群每天定时会通过ZooKeeper来实现Master选举。选举产生Master客户端之后,这个Master就会负责进行一系列的海量数据处理,最终计算得到一个数据结果,并将其放置在一个内存/数据库中。同时,Master还需要通知集群中其他所有的客户端从这个内存/数据库中共享计算结果。
接下去,我们将重点来看 Master 选举的过程,首先来明确下 Master 选举的需求:在集群的所有机器中选举出一台机器作为Master。针对这个需求,通常情况下,我们可以选择常见的关系型数据库中的主键特性来实现:集群中的所有机器都向数据库中插入一条相同主键 ID 的记录,数据库会帮助我们自动进行主键冲突检查,也就是说,所有进行插入操作的客户端机器中,只有一台机器能够成功——那么,我们就认为向数据库中成功插入数据的客户端机器成为Master。
借助数据库的这种方案确实可行,依靠关系型数据库的主键特性能够很好地保证在集群中选举出唯一的一个Master。但是我们需要考虑的另一个问题是,如果当前选举出的Master挂了,那么该如何处理?谁来告诉我Master挂了呢?显然,关系型数据库没法通知我们这个事件。那么,如果使用ZooKeeper是否可以做到这一点呢? 那在之前,我们介绍了ZooKeeper创建节点的API接口,其中一个重要特性便是:利用ZooKeeper的强一致性,能够很好保证在分布式高并发情况下节点的创建一定能够保证全局唯一性,即ZooKeeper将会保证客户端无法重复创建一个已经存在的数据节点。也就是说,如果同时有多个客户端请求创建同一个节点,那么最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很容易地在分布式环境中进行Master选举了。
在这个系统中,首先会在 ZooKeeper
上创建一个日期节点,例如“2020-11-11
客户端集群每天都会定时往ZooKeeper 上创建一个临时节点,例如/master_election/2020-11-11/binding。在这个过程中,只有一个客户端能够成功创建这个节点,那么这个客户端所在的机器就成为了Master。同时,其他没有在ZooKeeper上成功创建节点的客户端,都会在节点/master_election/2020-11-11 上注册一个子节点变更的 Watcher,用于监控当前的 Master 机器是否存活,一旦发现当前的 Master 挂了,那么其余的客户端将会重新进行Master选举。
从上面的讲解中,我们可以看到,如果仅仅只是想实现Master选举的话,那么其实只需要有一个能够保证数据唯一性的组件即可,例如关系型数据库的主键模型就是非常不错的选择。但是,如果希望能够快速地进行集群
Master 动态选举,那么就可以基于 ZooKeeper来实现。
猜你喜欢: