首先客户端连接zookeeper集群中的任何一个节点,可以是leader节点,也可以是follower节点,一旦连接,节点会给客户端分配会话ID,并向客户端发送确认,如果客户端收到确认,那么连接成功,客户端会有规律地给zookeeper发送心跳包,确保连接没有断开。
- 客户端向zookeeper从节点发送读请求,节点会直接从数据库中找到这个节点的数据然后返回。
- 客户端向zookeeper从节点发送写请求,节点会将znode路径和数据转发到leader节点,leader会将写请求转换为proposal提案,并且分配一个事务ID zxid,将这个proposal放到每个节点的队列(主节点会给每个从节点分配一个专用队列)中去,然后会根据先进先出的策略,将消息发送给从节点,从节点接收到后会将事务写入到磁盘中去,然后返回ACK响应给主节点,当主节点接收到半数以上的从节点的ACK响应后,主节点会认为这个事务提交成功,完成这个事务提交,同时给所有从节点发送commit消息,从节点接收到消息后,会将这条事务提交。
由此看来zookeeper没法保证客户端读取的都是最新的数据,
分布式
分布式最大的难点在于各个节点的状态怎么同步。
CAP理论
C是一致性,Consistency,就是各个节点保存的数据都是最新的。
A是Availability, 可用性,每次请求都可以获得响应,但是没法保证是最新的响应。
P是分区容错性(Partition tolerance),就是每个节点可能都存在于不同的子网络,也就是不同的分区,不同分区之间的通信总是有可能发生故障的,或者总是有可能存在一些节点挂了的情况。
可以认为P总是成立的,C和A是无法同时做到。所以一般对于数据一致性要求特别高的业务,例如支付,交易相关的业务,就是会优先保证一致性C和分区容错性P,就是保证数据一致性,例如让所有子节点都收到更新后才算提交成功,就像MySQL主从同步中的全同步模式一样。普通的业务是优先保证可用性A和分区容错性P,比如在MySQL主从同步时,默认就是异步的方式,我们执行一条更新SQL,只需要主节点更新成功就行就对事务进行提交,不需要等待从节点更新数据成功,主节点会异步把SQL发送给从节点。