案例

  先搭建一个dubbo+zookeeper的demo,然后根据demo来细说。
  第一步:从dubbo官网下载dubbo-master.zip文件,从zookeeper官网下载zookeeper.tar.gz文件。
  第二步:解压zookeeper.tar.gz文件,在解压\zookeeper-3.4.10\bin路径下,点击zkServer.cmd(本案例是直接在windows下运行),成功启动,发现其绑定了端口号2181。
  第三步:解压dubbo-master.zip文件,然后在用eclipse导入其项目空间。发现dubbo的注入地址默认配置的是zookeeper://127.0.0.1:2181这个地址,不用修改,然后将其放到tomcat下启动。(且记先启动zookeeper在启动dubbo,不然dubbo启动连接不到zookeeper,启动失败的。)
  第四步:打开http://localhost:8088/dubbo-admin-2.5.8/,然后输入账号密码,登录到dubbo管理界面。(确切地址是多少,看你的配置)。这样4步,dubbo管理平台就已经搭建好了。
  第五步:在写一个消费者和生产者来同步dubbo来进行通信。先创建一个生产者。这里不详细说了,大部分都是maven工程的创建修改,直接给上代码,供大家测试调试生产者
  第六步:写一个消费者来消费生产者的服务。这里也是直接提供代码让大家来进行调试。消费者
  第七步:输入http://localhost:8089/spring-mvc/hello/dh1,发现调用已经成功,同时发现dubbo管理界面出现了一个生成者,一个消费者。

什么是zookeeper  

  Zookeeper是Hadoop的一个子项目,它是分布式系统中的协调系统,可提供的服务有:配置服务,名字服务,分布式同步,组服务等。

zookeeper配置文件

  我们可以通过修改Zookeeper的配置文件来修改Zookeeper的启动信息。
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/zookeeper-data/
clientPort=2181
  tickTime:指定了ZooKeeper的基本时间单位(以毫秒为单位);
  initLimit:指定了启动zookeeper时,zookeeper实例中的随从实例同步到领导实例的初始化连接时间限制,超出时间限制则连接失败(以tickTime为时间单位);
  syncLimit:指定了zookeeper正常运行时,主从节点之间同步数据的时间限制,若超过这个时间限制,那么随从实例将会被丢弃;
  dataDir:zookeeper存放数据的目录;
  clientPort:用于连接客户端的端口。

zookeeper存储模型

  Zookeeper的存储结构采用的是结构化存储,很像数据结构当中的树,也很像文件系统的目录。树是由节点所组成,Zookeeper的数据存储也同样是基于节点,这里称之为znode。但是,不同于树的节点,Znode的引用方式是路径引用,类似于文件路径:/a/b。
  Znode包含4个信息。
  data:Znode存储的数据信息。
  ACL:记录Znode的访问权限,哪些ip那些人可以访问本节点。
  stat:包含Znode的各种元数据,比如事务id,大小,时间戳等。
  child:当前节点的子节点引用。

zookeeper的基本操作

  create:创建节点。
  delete:删除节点。
  exists:判断是否存在节点。
  getData:获取一个节点的数据。
  setData:设置一个节点的数据。
  getChildren:获取节点下所有的子节点。
  其中exist,getData.getChildren 都是读操作。客户端在请求读操作时可以设置是否watch(该效果是当Znode发生改变时,如增删改时,请求watch的客户端将会接收到异步通知,也就是说当一个节点被watch后,就会在对应的哈希表里面插入被watch的Znode路径以及watch列表)。

zookeeper的一致性

  Zookeeper身为分布式系统的协调服务,如果自身挂了怎么办呢?为了防止单机挂掉,ZooKeeper维护了一个集群。这个集群是一主多从结构。更新数据时,首先更新到主节点(这里的节点指的是服务器节点,不是Znode),再同步到从节点。为了保证主从节点数据一致性,zookeeper采用了ZAB协议。
  ZAB协议定义了3种节点状态。
  Looking:选举状态。
  Following:从节点所处的状态。
  Leading:Leader节点(主节点)所处的状态。
  最大ZXID的概念:
  最大ZXID也就是节点本地的最新事务编号,包含epoch和计数两部分。epoch是纪元的意思,相当于Raft算法选主时候的term。
  从节点挂了没有任何影响。如果主节点挂了,那么集群就会进行崩溃恢复。分为3个阶段。
  第一阶段,所有节点变成Looking状态。这些节点会各自向其他节点发起投票,投票信息包含自身服务器ID和最新事务ID.(ZXID)。接下来,节点会用自身的ZXID和从其他节点接受到的ZXID比较,如果别的节点比自己大,那就重新投票,投给接受到节点最大的ZXID的节点的票。
  每次投完票后,服务器都会统计投票数量,判断是否存在半数以上的投票,如果存在这样的节点,那么这个节点将会成为准Leader节点,状态也会变成Leading,其他节点就会从Looking转换为Following。
  第二阶段:发现阶段,用于在从节点中发现最新的ZXID和事务日志,因为可能存在Leader的ZIXD不一定是最新的,有可能意外情况,导致最新的ZXID不是最新的。
  所以这个阶段,Leader集思广益,接收所有Follower发过来的epoch值,Leader从中选出最大的值,基于此值加一,生成最新的epoch分给各个Follower.各个Follower收到全新的epoch后,返回ACK给Leader,带上各自最大的ZXID和历史事务日志,Leader选出最大的ZXID,并更新自身历史日志。
  第三阶段:同步阶段,将Leader刚接收到的最新历史事务日志,同步给集群所有的Follower。只有半数Follower同步成功,这个准Leader才能正式成为leader.

zookeeper的数据写入

  
  1.客户端发出写出请求给任意的Follower。
  2.Follower把写入数据的请求转发给Leader。
  3.Leader采用二段提交的方式,先发送Propose广播给Follower。
  4.Follower接受到Propose消息,写入日志成功后,返回ACk消息给Leader。
  5.Leader接到半数以上ACK消息,返回成功给客户端,并且广播Commit请求给Follower。