做视频的软件模板下载网站有哪些内容,网上注册公司流程工商,微信网站开发设计,查询公司的网站Java开发者视角下的Zookeeper—— 在什么场景下使用#xff0c;怎么用
可以参考#xff1a;https://zhuanlan.zhihu.com/p/62526102
Zookeeper是什么#xff1f;
ZooKeeper 是一个分布式的#xff0c;开放源码的分布式应用程序协同服务。ZooKeeper 的设计目标是将那些复…Java开发者视角下的Zookeeper—— 在什么场景下使用怎么用
可以参考https://zhuanlan.zhihu.com/p/62526102
Zookeeper是什么
ZooKeeper 是一个分布式的开放源码的分布式应用程序协同服务。ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来构成一个高效可靠的原语集并以一系列简单易用的接口提供给用户使用。
应用场景
配置管理。 Java微服务系统对于各个独立服务都要使用集中化的配置管理此时可以用到ZookeeperDNS服务组成员管理分布式锁
适用于存储和协同相关的关键数据不适合大数据量存储。 因为zookeeper需要把所有数据加载到内存中所存储的数据量受到内存的限制 zookeeper存储关键数据保证数据的高可用性和性能才是它的设计目的。可以看一下Java开发者的相关文章Kafka用到zookeeper所以说想要使用Kafka两个都得装上。 kafka使用zookeeper来管理自己的元数据配置 在实现分布式锁的情境下也会使用到zookeeper。
分布式系统开发视角——怎么设计需要设计哪些API
内容参考MIT6.824https://mit-public-courses-cn-translatio.gitbook.io/mit6-824/lecture-08-zookeeper/8.4-zookeeper
特点1 Zookeeper是一个通用的协调服务如果想要使用Raft那么设计自己的应用程序与Raft交互。 Zookeeper就是把分布式服务给封装了然后提供API 它使用的一致性协议是ZAB
特点2 Zookeeper 一写多读 性能提升但是不保证强一致性如果要求系统的强一致性增加server数量并不能提升系统性能性能瓶颈在于leader leader需要处理每一个请求将请求的拷贝发送给每一个其他服务器非leader节点的增加并不能实际完成任何工作。
针对该问题的改进一写多读只有写请求需要经过leader读请求不需要经过leader。 在现实世界中读请求比写请求多得多比如web页面都是通过读请求来生成web页面。但是如果把客户端请求发送给副本能否得到预期结果副本中的数据并不一定是最新的因为append entries只要求大多数节点收到并响应我们需要读的节点也许为少数节点此时数据是落后的。
一致保证Consistency Guarantees
对于Zookeeper来说并不要求返回最新的写入数据。 Zookeeper放弃线性一致性不提供线性一致的读。它有自己有关一致性的定义 两个主要的保证
写请求是线性一致的 linearable writes 尽管客户端可以并发的发送写请求然后Zookeeper表现的就像以某种顺序一次只执行一个写请求并且也符合写请求的实际时间。所以如果一个写请求在另一个写请求开始前就结束了那么Zookeeper实际上也会先执行第一个写请求再执行第二个写请求。 任何一个客户端的请求都会按照客户端指定的顺序来执行论文里称之为FIFOFirst In First Out客户端序列 FIFO client order
对于写请求最终会以客户端确定的顺序执行。这一点可以理解为请求的执行顺序按照客户端发出指令的时间为准客户端可以发送异步的写请求服务端的执行顺序就按照客户端发送请求的时间序号。
对于读请求如果第一个读请求在Log中的一个位置执行那么第二个读请求只允许在第一个读请求对应的位置或者更后的位置执行。 也就是读读一致性的要求这个位置也就是Log对应的条目号zxid每次读请求的响应中会带上zxid给client 当client再次发出请求到一个相同或者不同的副本时会在请求中带上最高的zxid这样副本就会知道至少要在Log中的这个点或之后执行读请求。 如果这个副本的最新日志小于zxid那么就无法响应客户端请求这里可以是发出信息拒绝client或是一直阻塞直到log更新才能响应client的读请求。
如果客户端先发送写请求紧接着发读请求此时需要写请求执行以后才能接着处理读请求。这是为了满足写读一致性。 为了处理这种情况客户端的读请求还要带上 上一次写请求对应的zxid 副本必须看到对应zxid的写请求才能再执行读请求。
同步操作 sync
zookeeper有一个弥补非严格线性一致的方法 —— sync假设现在需要刚刚写入的最新的数据可以发送sync请求本质上是写请求让sync请求写入到所有副本的sync 。 我认为sync可以理解为一个标志点。然后向副本发送读请求并携带信息告知发送了sync这事 副本需要在看到sync后才能回复这个读请求。 因为收到了sync也就意味着收到了sync之前的所有日志。副本的响应至少是发送sync请求时对应的状态。sync是个代价很高的操作本来读请求是不经过leader的发送sync后意味着客户端需要等待日志同步到sync的位置才能响应。
就绪文件 Ready file/znode
znode是zookeeper的数据点 file znode 和linux一致“一切皆文件”
考虑zookeeper管理配置文件场景Master节点更新一个存有集群信息的配置而大量客户端需要读取配置此时Master节点能做到原子更新吗 客户端并不希望读到更新到一半的配置。我希望zookeeper能够对读做一个限制不读到中间状态。
zookeeper应对这种情况的方式Ready file如果Ready file存在则client可以读取配置如果Ready file不存在client不能读取。
Master更新配置的流程
删除Ready file更新相关的配置文件更新完成后创建Ready file
所有步骤均为写请求zookeeper可以确保这些请求以线性顺序执行。 对于副本也需要按这一流程执行在更新前删除Ready file 更新后创建Ready file。 clinet若在此时发送读请求副本发现ready file不存在那么会过一会再重试。结合一致保证章节中所提到的zookeeper写读一致性的实现 如果客户端可以看见创建Ready file的写请求 读请求必须在该写请求之后 因此zookeeper可以保证读请求看到对配置的全部更新。
问题又来了 客户端想要看见Ready file需要通过调用exist客户端调用exist的时候Ready file存在但是读完后master开始更新配置这样带来的后果就是配置虽然更新了但是客户端还以为是老配置。zookeeper的解决方法是 客户端不仅会发送exists来查询Ready file是否存在还会建立一个针对Ready file的watch通道。一旦Ready file改变副本节点会向客户端发送通知。client处理完了发来的通知再重新执行读配置的操作。
Zookeeper API
zookeeper可以用来解决的问题
比如VMware FT它的主备切换需要test-and-set服务 zookeeper可以提供这样一种第三方服务发布服务器的配置信息选举master
zookeeper的API看起来像是文件系统 请求zookeeper数据的时候需要指定路径路径就像Linux文件路径一样文件和目录都叫做znode类别如下
Regular znodes 创立即永久Ephemeral znodes 与客户端会话绑定Sequential znodes CREATE(PATHDATAFLAG)。入参分别是文件的全路径名PATH数据DATA和表明znode类型的FLAG。这里有意思的是CREATE的语义是排他的。也就是说如果我向Zookeeper请求创建一个文件如果我得到了yes的返回那么说明这个文件之前不存在我是第一个创建这个文件的客户端如果我得到了no或者一个错误的返回那么说明这个文件之前已经存在了。所以客户端知道文件的创建是排他的。在后面有关锁的例子中我们会看到如果有多个客户端同时创建同一个文件实际成功创建文件获得了锁的那个客户端是可以通过CREATE的返回知道的。DELETE(PATHVERSION)。入参分别是文件的全路径名PATH和版本号VERSION。有一件事情我之前没有提到每一个znode都有一个表示当前版本号的version当znode有更新时version也会随之增加。对于delete和一些其他的update操作你可以增加一个version参数表明当且仅当znode的当前版本号与传入的version相同才执行操作。当存在多个客户端同时要做相同的操作时这里的参数version会非常有帮助并发操作不会被覆盖。所以对于delete你可以传入一个version表明只有当znode版本匹配时才删除。EXIST(PATHWATCH)。入参分别是文件的全路径名PATH和一个有趣的额外参数WATCH。通过指定watch你可以监听对应文件的变化。不论文件是否存在你都可以设置watch为true这样Zookeeper可以确保如果文件有任何变更例如创建删除修改都会通知到客户端。此外判断文件是否存在和watch文件的变化在Zookeeper内是原子操作。所以当调用exist并传入watch为true时不可能在Zookeeper实际判断文件是否存在和建立watch通道之间插入任何的创建文件的操作这对于正确性来说非常重要。GETDATA(PATHWATCH)。入参分别是文件的全路径名PATH和WATCH标志位。这里的watch监听的是文件的内容的变化。SETDATA(PATHDATAVERSION)。入参分别是文件的全路径名PATH数据DATA和版本号VERSION。如果你传入了version那么Zookeeper当且仅当文件的版本号与传入的version一致时才会更新文件。LIST(PATH)。入参是目录的路径名返回的是路径下的所有文件。 举例使用zookeeper实现计数器
错误做法
count GET(key)
// get 之后 count还有可能改变
PUT(k, count 1)因为read-update-write 不是原子的
正确做法
WHILE TRUE:X, V GETDATA(F) //read操作任意副本执行IF SETDATA(f, X 1, V): // write操作 leader执行。 //如果get后数据被修改版本号就不是V无法执行SET操作会进行下一个循环BREAKTest-and-set服务也可以这样实现。旧的数据为0 想要将它设置为1那么在set的时候需要带上旧的版本号版本号必须与读时的版本号相同。