我是kacen,一个会点前端的java后端开发工程师。
博主今天写一下zookeeper的简介,毕竟写了安装部署之后一直没有时间再发布新的东西,补一下。我也不多逼逼,咋们开始吧。
咋们先说一下为什么会有zookeeper需求吧,毕竟有需求才会有实现。
打个比喻:一个公司里面有A、B、C三个不同职能的部门。当一个部门内部需要开会的时候,人员可以随时召集到且进行讨论,但是如果跨部门开会做整合的时候就需要提前安排和通知。为什么?因为这是一个跨边界的问题,A、B、C三个部门互不熟悉,所以需要提前安排和通知。
那要怎么去实行,有两个解决方案:
1.有序列的去通知,A通知B,B通知C。
2.交由老板或者人事(第三方)去统一去依次通知A、B、C三个部门。
通过这个案例,我们可以知道一个独立的个体在需要和其他的独立个体交流时,就会产生一个边界问题,然后我们再把它放到计算机上来理解就清晰很多了。
先说一下操作系统吧,我们的app通常都是一个进程,因为每个应用不一样,所以他们需要考虑很多不同的问题,导致每个进程需要一个边界来限定他们,这个就是进程边界。
操作系统会给每个不同的进程分配资源,进程内部可以共享资源,但是如果是其他进程就会有不同的资源,这就会产生进程边界,由于这个边界,进程之间的资源就不可以被互相共享使用了。
但是这个总会有特殊的情况,如果进程之间需要相互的交流怎么办呢?聪明的小伙伴应该知道了吧,比较常用的就是socket,其他还有消息队列,流之类的。多个进程的就有nginx。
当然中间件的开发者都是国外的一些大雕搞出来,这也和不同国情有关。国内大多数都在为了有房(有钱)+有车(有钱)+有生活(有时间)= 努力的搞业务。所以往往做不出生产级别的技术。
重点来了,咋们回到公司部门的例子
公司有ABC三个部门,但是有一天公司分配的3个任务给了错误的人。但是这3个部门已经完成了对应的任务(但是不专业),这个时候就需要互换或者重做,但是重做会消耗大量的资源,这时候他们就会需要相互交流,按照方案1来操作,A会通知B,B会通知C。这个问题的处理在只有3个的时候可能并不明显,但是有20个部门同时发生这样的事情,那就会变得很复杂。
那如果是按照第二个方案,咋们由一个第三方将三个或者多个部门集合统一来协调处理这些事情,那事情就会变得更加简单,越多的部门这个效果就越明显。我们把这个解决方案放到进程之间的相互交流的,那这个第三方(即中间件)就是我们的zookeeper了。
这个解决方案一定程度的降低了对技术人员的一些要求(毕竟我们可以使用框架,不用去了解一些深层次的通信协议知识)也降低了个体的复杂性(一个单独的进程不用支撑完整的进程通信,只需要支持客户端就可以了),但是这个也会有新的问题产生(这个之后会谈)。
这里我们就了解到了zookeeper为什么会被造出来,因为有这个需求。
Zookeeper的数据模型
咋们的计算机大部分时间在干嘛,当然是做数据的处理和存储,zookeeper作为协调者肯定需要加倍的关注这一点了。
我们先来看一下java的数据底层的存储方式,一个是数组,另一个则是链表。
我们都知道数组的优点就是简单,因为它是一维的,具有线性关系(即有前后顺序),但是它也有它的缺点,就是功能不够好,后面说到链表就知道了。
链表的底层是树,我们可以认为它是二维的,就好像祖谱一样,左右是兄弟,上下是父子,因此也就有了从属关系。它是一个复杂度和功能都兼顾的结构。
当然还有更复杂的图结构算法,它是网状结构的,是一个多维的结构,他们可以相互连通,它就像咋们抗战时期的地道或者咋们的地铁(内部人员称它是线网),都是一个大的网状结构,虽然复杂,但是功能也很强大(想了解的小伙伴链接在此https://www.cnblogs.com/xiaohuiduan/p/11352209.html。
简单介绍了一下数据结构,我们在来看一下zookeeper。zookeeper的选型也是选择了树作为自己的存储数据的结构,像这样:
/
|
|————————————————————————————————————|
/menu /menu2
| |
|—————————————|——————————————| …………
/menu/1 /menu/2 /menu/3
上面这个图自己看吧。然后我们再来说一下增删改查,对应树大家都懂了吧,就是添加节点数据,删除节点数据,修改树的某个节点已经存储数据,查找树的某个节点已经存储数据。
这里插入一下,树的前序、中序、后续、广度排序的实现代码:
https://github.com/KacenBoy/binary-tree
Zookeeper应具备的功能
在这里我们还是一样,从需求出发来看zookeeper需要有什么功能
watch功能
例子:
现在有两个进程,进程A和进程B。进程A和进程B都连接到zookeeper,A进程创建一个节点来证明自己的存在,进程A连接的节点为node,然后我们设置一个节点数据“doing”,表示自己正在处理数据,当它处理完就更新为“done”。
这个时候A已经完成自己需要做的事情,那B就要去zookeeper里找到node这个节点来看一下自己是否需要开始处理自己的数据,doing就等待,done就开始。但是这样一直盯着一个东西,自己又有其他的事情要做咋办呢。这个时候zookeeper就需要有一个盯梢的能力,但是有情报没办法传达,那不是扯dan吗,所以它还需要有一个通知其他进程的能力(即通知的能力),这两个功能结合起来在zookeeper里叫watch。
然后我们会怎么操作呢,既然B比较关注node这个节点,那就需要zookeeper去watch这个node节点,如果有什么敌情马上汇报。(watch这个到时候会放另外一篇来讲)
说到这里很多小伙伴就有一个疑问了,既然有了watch,那它是不是永久性的呢,答案是否定的,毕竟一直当你不需要的时候还一直盯着,既不是很浪费资源,所这个watch是一次性的,如果B还需要被通知,那就重新放多一个watch就好啦,如此简洁方便。(给你们一个恶趣味的例子,那就是你们上洗手间的时候,em自己脑补)
刚讲完上面的小伙伴是不是又有疑问了,那它与进程间的连接是不是的keepalive的呢,答案?是的。为什么,因为如果你需要用它来发通知给A或者B那么,它如果断开了那要怎么通知呢,呵呵哒。补一下zookeeper是可以将进程A的数据发送给进程B的。
会话延续能力
咋们一直在说高可用的问题,很多企业会给服务做集群,这样是基本的操作方式。既然有多台服务,那咋们如果在使用zk来做这个集群的管理者,那么,它们在断开的时候,zk会做什么样的操作呢。
在说这个问题前,我们要先了解一下zk的一些高可用机制,首先我们得知道zk提供长连接/session,Ephemeral Znode,Event&Notification,ping的机制上来做高可用的。这里边比较复杂我就不多说。主要看一下session(会话)。(其他文章细说)
session在服务端和客户端建立的时候就会生成一个全局唯一的id(session id),在超时时间内,服务端会向客户端发送请求(heart beat),来确认连接正常。如果连不上就超时,反则重置超时时间。这段话你可能看了无数遍了,不过它就是如此。因为具体的话比较多,还是老样子,得分其他文章来说这些东西。
结语
先总结一下我都说了什么,这个很重要。
1.走哦可拍
以上就是zk的一些基本知识和介绍。如果有说错或者不喜欢的请直接怼我,或者想交流的请在下方留言。
网友评论