Zookeeper 论文笔记
Zookeeper
Zookeeper 是分布式系统的服务,底层使用类似 Raft 的 Zab 共识算法,它提供的服务用于协作分布式程序。它提供了类似文件系统的 API,客户端可以使用这些 API 来完成分布式程序,比如分布式锁。
公开课中其实存在着一些看不懂的话题,不知道在讨论什么,zookeeper's guarantees 这部分没太看得懂,公开课讨论这部分的时候看得一头雾水,这部分应该是关于正确性的讨论。目前论文只能看懂这个系统的概况,API 的设计,客户端和系统的交互,如何使用提供的 API 来完成一些分布式应用,比如分布式锁。
结构
中间的 Atomic Broadcast 类似 Raft,作为一个共识模块。读操作可以在任何一个节点上,写操作只能在 leader 上。
接口
create(path, data, flags):在指定路径创建具有指定数据的指定类型的节点。path 为指定路径,data 为指定数据,flags 可以指定的类型有常规、临时、顺序增加。
delete(path, version):删除指定版本号的节点。如果不匹配,那么不删除
exists(path, watch):返回 path 是否存在一个节点。当 watch 为真,客户端可以 watch 这个节点,当发生变化,客户端可以知道发生了改变。
getData(path, watch):返回 path 上的数据和元数据,watch 只在节点存在的时候有作用。
setData(path, data, version):设置 path 上的数据。
getChildren(path, watch):获取一个节点的后继节点。
sync(path):在发出这个请求之后,等待这个请求之前的所有更新操作完成。
特性
wait-free:对于一个客户端,它的请求无需等待其他客户端的请求,虽然这个请求完成的可能很慢。使用了 watch 机制来达成 wait-free。
Linearizable writes:所有更新 zk 状态的请求是可串行化的,存在一个请求次序,按照这个次序执行,可以产生和原来并行执行请求一样的结果。
FIFO client order:对于一个客户端,它的请求是按照发送的顺序来执行的。
读写:所有的节点都可以读取,但是只有 leader 节点可以写入。在 follower 节点上不保证读取到最新的数据,但是保证读取的顺序,读取到了较新的数据,就不会读取在这以前的数据。使用 sync 操作,可以等待当前请求之前尚未完成的更新操作全部完成,在执行当前操作。加入更多的服务器,可以使到读取速度提高,但是写入速度会变慢,因为共识算法需要保证 majority。
读操作:速度快,但是不保证可以得到最新的数据。相当于 CAP 中舍弃了 C。因为有 FIFO 这个 guarantee,同一个客户端的读取操作一定是保证可以读到自己前面写入的内容的。
Q&A
Q: Why isn't possible for two clients to acquire the same lock? In particular, how does Zookeeper decide if a client has failed and it can give the client's locks to other clients?
A: 第一个问题,可以通过创建节点、判断节点是否存在、Watch 来创建节点。create 的 flag 只有 EPHEMERAL,想要获得锁的所有客户端创建的节点名字是相同的。第二个问题,看论文中第 10 页,讲了使用心跳包的机制来检测 client 是否仍然在线。
Q: What if a client reads from an up-to-date replica, then a lagging replica?
A: It may see data values go backwards in time! Also forbidden. 在 zookeeper 中,使用 zxid,读 4.4 节,可以知道,当一个服务器挂掉之后,客户端需要重新连接,拿着 zxid 去找一个可以的服务器。客户端要记录 zxid,以免读取了数据之后,又读取到了更加前的数据。
Q: How does linearizability differ from serializability?
A: 看这个链接:http://www.bailis.org/blog/linearizability-versus-serializability 。其中讲到的 real-time constraint,要求读操作能读取到前面的写入操作。serializability 讲的是事务并发执行的正确性,只要事务的一系列并发操作等同于一个串行化的操作序列,那么说可串行化,是并发执行的正确结果。