当前位置: 首页 > news >正文

为企业做网站建设优化小程序包年竞价凡科网用户登录

为企业做网站建设优化小程序包年竞价,凡科网用户登录,个人网站做seo,wordpress上传的地址加一、简介 1、场景 如何让⼀个应⽤中多个独⽴的程序协同⼯作是⼀件⾮常困难的事情。开发这样的应⽤#xff0c;很容易让很多开发⼈员陷⼊如何使多个程序协同⼯作的逻辑中#xff0c;最后导致没有时间更好地思考和实现他们⾃⼰的应⽤程序逻辑#xff1b;又或者开发⼈员对协同…一、简介 1、场景 如何让⼀个应⽤中多个独⽴的程序协同⼯作是⼀件⾮常困难的事情。开发这样的应⽤很容易让很多开发⼈员陷⼊如何使多个程序协同⼯作的逻辑中最后导致没有时间更好地思考和实现他们⾃⼰的应⽤程序逻辑又或者开发⼈员对协同逻辑关注不够只是⽤很少的时间开发了⼀个简单脆弱的主协调器导致不可靠的单⼀失效点。 ZooKeeper 可以在分布式系统中协作多个任务其设计保证了健壮性这就使得应⽤开发⼈员可以更多关注应⽤本⾝的逻辑⽽不是协同⼯作上。ZooKeeper从⽂件系统API得到启发提供⼀组简单的API使得开发⼈员可以实现通⽤的协作任务包括选举主节点、管理组内成员关系、管理元数据等。ZooKeeper包括⼀个应⽤开发库主要提供Java和C两种语⾔的API和⼀个⽤Java实现的服务组 件。ZooKeeper的服务组件运⾏在⼀组专⽤服务器之上保证了⾼容错性和可扩展性。 整个ZooKeeper的服务器集群管理着应⽤协作的关键数据。ZooKeeper 不适合⽤作海量数据存储。对于需要存储海量的应⽤数据的情况我们有很多备选⽅案⽐如说数据库和分布式⽂件系统等。因为不同的应⽤有不同的需求如对⼀致性和持久性的不同需求所以在设计应⽤时最佳实践还是应该将应⽤数据和协同数据独⽴开。 异步系统可能存在的问题消息延迟、处理器性能、时钟偏移等。没有收到⼀个进程发送的消息 可能是该进程已经崩溃或是最新消息发⽣了⽹络延迟或是其他情况导 致进程延迟或者是进程时钟发⽣了偏移。 ZooKeeper的精确设计简化了这些问题的处理ZooKeeper并不是完全消除这些问题⽽是将这些问题在应⽤服务层⾯上完全透明化使得这些 问题更容易处理。ZooKeeper实现了重要的分布式计算问题的解决⽅案直观为开发⼈员提供某种程度上实现的封装⾄少这是我们⼀直希望的。 分布式系统中的进程通信有两种选择直接通过⽹络进⾏信息交换或读写某些共享存储。ZooKeeper 使⽤共享存储模型来实现应⽤间的协作和同步原语。对于共享存储本⾝又需要在进程和存储间进⾏⽹络通信。⽹络通信是分布式系统中并发设计的基础。 提供的服务包括统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。 2、使用实例 Apache HBase HBase是⼀个通常与Hadoop⼀起使⽤的数据存储仓库。在HBase中 ZooKeeper⽤于选举⼀个集群内的主节点以便跟踪可⽤的服务器并保存集群的元数据。 Apache Kafka Kafka是⼀个基于发布-订阅pub-sub模型的消息系统。其中 ZooKeeper⽤于检测崩溃实现主题topic的发现并保持主题的⽣产和 消费状态。 Apache Solr Solr是⼀个企业级的搜索平台。Solr的分布式版本命名为SolrCloud它 使⽤ZooKeeper来存储集群的元数据并协作更新这些元数据。 YahooFetching Service YahooFetching Service是爬⾍实现的⼀部分通过缓存内容的⽅式⾼效地获取⽹页信息同时确保满⾜⽹页服务器的管理规则⽐如robots.txt ⽂件。该服务采⽤ZooKeeper实现主节点选举、崩溃检测和元数据存储。 Facebook Messages Facebook推出的这个应⽤http://on.fb.me/1a7uViK集成了email、短 信、Facebook聊天和Facebook收件箱等通信通道。该应⽤将ZooKeeper作为 控制器⽤来实现数据分⽚、故障恢复和服务发现等功能。 总结 当开发⼈员使⽤ ZooKeeper进⾏开发时开发⼈员设计的那些应⽤往往可以看成⼀组连接到ZooKeeper服务器端的客户端它们通过ZooKeeper的客户端API连接到 ZooKeeper服务器端进⾏相应的操作。 Zookeeper 的客户端API功能强⼤其中包括 保障强⼀致性、有序性和持久性 实现通用的同步原语的能⼒ 在实际分布式系统中并发往往导致不正确的⾏为。ZooKeeper提供了⼀种简单的并发处理机制 3、示例主-从应用 主从架构中主节点进程负责跟踪从节点状态和任务的有效性并分配任务到从节点。 1主从模式存在的问题 主节点失效 如果主节点发送错误并失效系统将⽆法分配新的任务或重新分配已失败的任务。 主节点失效时我们需要有⼀个备份主节点backup master。当主 要主节点primary master崩溃时备份主节点接管主要主节点的⾓⾊进⾏故障转移然⽽这并不是简单开始处理进⼊主节点的请求。新的主要主节点需要能够恢复到旧的主要主节点崩溃时的状态。对于主节点状态的可恢复性我们不能依靠从已经崩溃的主节点来获取这些信息⽽需要从其他地⽅获取也就是通过ZooKeeper来获取。 状态恢复并不是唯⼀的重要问题。假如主节点有效备份主节点却认为主节点已经崩溃。这种错误的假设可能发⽣在以下情况例如主节点负载很⾼导致消息任意延迟备份主节点将会接管成为主节点的⾓⾊执⾏所有必需的程序最终可能以主节点的⾓⾊开始执⾏成为第⼆个主要主节点。更糟的是如果⼀些从节点⽆法与主要主节点通信如由于⽹络分区network partition错误导致这些从节点可能会停⽌与主要主节点的通信⽽与第⼆个主要主节点建⽴主-从关系。针对这个场景中导致的问题我们⼀般称之为脑裂split- brain系统中两个或者多个部分开始独⽴⼯作导致整体⾏为不⼀致性。我们需要找出⼀种⽅法来处理主节点失效的情况关键是我们需要避免发⽣脑裂的情况。 从节点失效 如果从节点崩溃已分配的任务将⽆法完成。 客户端向主节点提交任务之后主节点将任务派发到有效的从节点中。从节点接收到派发的任务执⾏完这些任务后会向主节点报告执⾏状态。主节点下⼀步会将执⾏结果通知给客户端。 如果从节点崩溃了所有已派发给这个从节点且尚未完成的任务需要重新派发。其中⾸要需求是让主节点具有检测从节点的崩溃的能⼒。主节点必须能够检测到从节点的崩溃并确定哪些从节点是否有效以便派发崩溃节点的任务。⼀个从节点崩溃时从节点也许执⾏了部分任务也许全部执⾏完但没有报告结果。如果整个运算过程产⽣了其他作⽤我们还有必要执⾏某些恢复过程来清除之前的状态。 通信故障 如果主节点和从节点之间⽆法进⾏信息交换从节点将⽆法得知新任务分配给它。 如果⼀个从节点与主节点的⽹络连接断开⽐如⽹络分区network partition导致重新分配⼀个任务可能会导致两个从节点执⾏相同的任务。如果⼀个任务允许多次执⾏我们在进⾏任务再分配时可以不⽤验证第⼀个从节点是否完成了该任务。如果⼀个任务不允许那么我们的应⽤需要适应多个从节点执⾏相同任务的可能性 2主-从架构的需求 主节点选举这是关键的⼀步使得主节点可以给从节点分配任务。 崩溃检测主节点必须具有检测从节点崩溃或失去连接的能⼒。 组成员关系管理主节点必须具有知道哪⼀个从节点可以执⾏任务的能⼒。 元数据管理主节点和从节点必须具有通过某种可靠的⽅式来保存分配状态和执⾏状态的能⼒ 理想的⽅式是以上每⼀个任务都需要通过原语的⽅式暴露给应⽤对开发者完全隐藏实现细节。ZooKeeper提供了实现这些原语的关键机制因此开发者可以通过这些实现⼀个最适合他们需求、更加关注应⽤逻辑的分布式应⽤。 4、CAP定律 CAP⼀致性Consistency、可⽤性Availability和分区容错性Partition-tolerance 该定律指出⼀个分布式系统最多同时满足两种属性。 ZooKeeper的设计尽可能满⾜⼀致性和可⽤性当然在发⽣⽹络分区时ZooKeeper也提供了只读能⼒。 我们⽆法拥有⼀个理想的故障容错的、分布式的、真实环境存在的系统来处理可能发⽣的所有问题。但我们还是可以争取⼀个稍微不那么宏伟的⽬标。⾸先我们只好对我们的假设或⽬标适当放松例如我们可以假设时钟在某种范围内是同步的我们也可以牺牲⼀些⽹络分区容错的能⼒并认为其⼀直是⼀致的当⼀个进程运⾏中也许多次因⽆法确定系统中的状态⽽被认为已经发⽣故障。虽然这些是⼀些折中⽅案⽽这些折中⽅案允许我们建⽴⼀些印象⾮常深刻的分布式系统。 二、Zookeeper 基础 1、Zookeeper 概述 ZooKeeper是一个开源的分布式的为分布式框架提供协调服务的 Apache 项目。 从设计模式角度来理解Zookeeper是一个基于观察者模式设计的分布式服务管理框架它负责存储和管理大家都关心的数据然后接受观察者的注册一旦这些数据的状态发生变化Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。 ZooKeeper 并不直接暴露分布式服务所需要的原语及原语的调用方法。ZooKeeper以类似文件系统的方式存储数据暴漏出调用这些数据的API让应用通过ZooKeeper的机制和API自己来实现分布式相关原语。 ZooKeeper 数据模型的结构与 Unix 文件系统很类似整体上可以看作是一棵树每个节点称做一个 ZNode。每一个 ZNode 默认能够存储 1MB 的数据每个 ZNode 都可以通过其路径唯一标识 server id主节点的znode没有数据表⽰当前还没有选举出主节点/workers节点作为⽗节点其下每个znode⼦节点保存了系统中⼀个可 用从节点信息。如图2-1所示有⼀个从节点foot.com2181。/tasks节点作为⽗节点其下每个znode⼦节点保存了所有已经创建并等待从节点执⾏的任务的信息主-从模式的应用的客户端在/tasks下添加⼀个znode⼦节点用来表示⼀个新任务并等待任务状态的znode节点。/assign节点作为⽗节点其下每个znode⼦节点保存了分配到某个从 节点的⼀个任务信息当主节点为某个从节点分配了⼀个任务就会在/assign下增加⼀个⼦节点。 Zookeeper 特点 Zookeeper集群一个领导者Leader多个跟随者Follower组成集群中只要有半数以上节点存活Zookeeper集群就能正常服务Zookeeper一般安装奇数台服务器全局数据一致每个Server保存一份相同的数据副本Client无论连接到哪个Server数据都是一致的。更新请求顺序执行来自同一个Client的更新请求按其发送顺序依次执行。数据更新原子性一次数据更新要么成功要么失败。实时性在一定时间范围内Client能读到最新数据。 1.1 API 概述 znode节点可能含有数据也可能没有。如果⼀个znode节点包含任何 数据那么数据存储为字节数组byte array。字节数组的具体格式特定 于每个应⽤的实现ZooKeeper并不直接提供解析的⽀持。我们可以使⽤如 Protocol Buffers、Thrift、Avro或MessagePack等序列化Serialization包 来⽅便地处理保存于znode节点的数据格式不过有些时候以UTF-8或 ASCII编码的字符串已经够⽤了 ZooKeeper的API暴露了以下⽅法 create/path data 创建⼀个名为/path的znode节点并包含数据data。 delete/path 删除名为/path的znode。 exists/path 检查是否存在名为/path的节点。 setData/path data设置名为/path的znode的数据为data。 getData/path 返回名为/path节点的数据信息。 getChildren/path 返回所有/path节点的所有⼦节点列表。 ZooKeeper并不允许局部写⼊或读取znode节点的数据。当设置⼀个znode节点的数据或读取时znode节点的内容会被整个替换或全部读取进来。 ZooKeeper客户端连接到ZooKeeper服务通过API调⽤来建⽴会话session。 1.2 Znode不同类型 当新建znode时还需要指定该节点的类型mode不同的类型决定了znode节点的⾏为⽅式。 1持久节点和临时节点 znode节点可以是持久persistent节点还可以是临时ephemeral 节点。持久的znode如/path只能通过调⽤delete来进⾏删除。临时的znode与之相反当创建该节点的客户端崩溃或关闭了与ZooKeeper的连接时这个节点就会被删除。 持久znode是⼀种⾮常有⽤的znode可以通过持久类型的znode为应⽤保存⼀些数据即使znode的创建者不再属于应⽤系统时数据也可以保存下来⽽不丢失。例如在主-从模式例⼦中需要保存从节点的任务分配情况即使分配任务的主节点已经崩溃了。 临时znode传达了应⽤某些⽅⾯的信息仅当创建者的会话有效时这些信息必须有效保存。例如在主从模式的例⼦中当主节点创建的znode为临时节点时该节点的存在意味着现在有⼀个主节点且主节点状态处于正常运⾏中。如果主znode消失后该znode节点仍然存在那么系统将⽆法监测到主节点崩溃。这样就可以阻⽌系统继续进⾏因此这个znode需要和主节点⼀起消失。我们也在从节点中使⽤临时的znode如果⼀个从节点失效那么会话将会过期之后znode/workers也将⾃动消失。 ⼀个临时znode在以下两种情况下将会被删除 当创建该znode的客户端的会话因超时或主动关闭⽽中⽌时。 当某个客户端不⼀定是创建者主动删除该节点时。 因为临时的znode在其创建者的会话过期时被删除所以我们现在不允许临时节点拥有⼦节点。在社区讨论中已经讨论过关于允许临时znode拥有⼦节点的问题其想法是使其⼦节点也均为临时节点。这个功能也许会出现在未来的发布版本中但现在还是不可⽤的。 2有序节点 ⼀个znode还可以设置为有序sequential节点。⼀个有序znode节点被分配唯⼀个单调递增的整数。当创建有序节点时⼀个序号会被追加到路径之后。例如如果⼀个客户端创建了⼀个有序znode节点其路径为/tasks/task-那么ZooKeeper将会分配⼀个序号如1并将这个数字追加到路径之后最后该znode节点为/tasks/task-1。有序znode通过提供了创建具有唯⼀名称的znode的简单⽅式。同时也通过这种⽅式可以直观地查看znode的创建顺序。 总结znode⼀共有4种类型持久的persistent、临时的ephemeral、持久有序的persistent_sequential和临时有序的ephemeral_sequential。 1.3 监视与通知 ZooKeeper通常以远程服务的⽅式被访问如果每次访问znode时客户端都需要获得节点中的内容这样的代价就⾮常⼤。因为这样会导致更⾼的延迟⽽且ZooKeeper需要做更多的操作。 这是⼀个常见的轮询问题。为了替换客户端的轮询我们选择了基于通知notification的机制客户端向ZooKeeper注册需要接收通知的znode通过对znode设置监视点watch来接收通知。监视点是⼀个单次触发的操作意即监视点会触发⼀个通知。为了接收多个通知客户端必须在每次通知后设置⼀个新的监视点。当节点/tasks发⽣变化时客户端会收到⼀个通知并从ZooKeeper读取⼀个新值。 因为通知机制是单次触发的操作所以在客户端接收⼀个znode变更通知并设置新的监视点时znode节点也许发⽣了新的变化不要担⼼你不会错过状态的变化。假设事件按以下顺序发⽣ ​ 1.客户端c2设置监视点来监控/tasks数据的变化。 ​ 2.客户端c1连接后向/tasks中添加了⼀个新的任务。 ​ 3.客户端c2接收通知。 ​ 4.客户端c2设置新的监视点在设置完成前第三个客户端c3连接后向/tasks中添加了⼀个新的任务。 客户端c2最终设置了新的监视点但由c3添加数据的变更并没有触发⼀个通知。为了观察这个变更在设置新的监视点前c2实际上需要读取节点/tasks的状态通过在设置监视点前读取ZooKeeper的状态最终c2就不会错过任何变更。 通知机制的⼀个重要保障是对同⼀个znode的操作先向客户端传送通知然后再对该节点进⾏变更。如果客户端对⼀个znode设置了监视点⽽该znode发⽣了两个连续更新。第⼀次更新后客户端在观察第⼆次变化前就接收到了通知然后读取znode中的数据。我们认为主要特性在于通知机制阻⽌了客户端所观察的更新顺序。虽然ZooKeeper的状态变化传播给某些客户端时更慢但我们保障客户端以全局的顺序来观察ZooKeeper的状态。 ZooKeeper可以定义不同类型的通知这依赖于设置监视点对应的通知类型。客户端可以设置多种监视点如监控znode的数据变化、监控znode⼦节点的变化、监控znode的创建或删除。为了设置监视点可以使⽤任何API中的调⽤来读取ZooKeeper的状态在调⽤这些API时传⼊⼀个watcher对象或使⽤默认的watcher。本章后续主从模式的实现及第4章会以主从模式的例⼦来展开讨论我们将深⼊研究如何使⽤该机制。 **注意谁来管理我的缓存 ** 如果不让客户端来管理其拥有的ZooKeeper数据的缓存我们不得不让ZooKeeper来管理这些应用程序的缓存。但是这样会导致ZooKeeper的设计更加复杂。事实上如果让ZooKeeper管理缓存失效可能会导致ZooKeeper在运⾏时停滞在等待客户端确认⼀个缓存失效的请求上因为在进⾏所有的写操作前需要确认所有的缓存数据是否已经失效。 流程 服务器启动时去注册信息创建的都是临时节点客户端获取到当前在线服务器列表并注册监听服务端服务节点下线集群服务器节点上下线通知客户端process(){ 重新再去获取服务器列表并注册监听 } 1.4 版本 每⼀个znode都有⼀个版本号它随着每次数据变化⽽⾃增。两个API操作可以有条件地执⾏setData和delete。这两个调⽤以版本号作为转⼊参数只有当转⼊参数的版本号与服务器上的版本号⼀致时调⽤才会成功。当多个ZooKeeper客户端对同⼀个znode进⾏操作时版本的使⽤就会显得尤为重要。例如假设客户端c1对znode/config写⼊了⼀些配置信息如果另⼀个客户端c2同时更新了这个znode此时c1的版本号已经过期c1调⽤setData⼀定不会成功。使⽤版本机制有效避免了以上情况。在这个例⼦中c1在写⼊数据时使⽤的版本⽆法匹配使得操作失败图2-4描述了这个情况。 2、ZooKeeper架构 应⽤通过客户端库来对ZooKeeper实现了调⽤。客户端库负责与ZooKeeper服务器端进⾏交互。 图2-5展⽰了客户端与服务器端之间的关系。每⼀个客户端导⼊客户端库之后便可以与任何ZooKeeper的节点进⾏通信。 ZooKeeper服务器端运⾏于两种模式下独⽴模式standalone和仲裁模式quorum。独⽴模式⼏乎与其术语所描述的⼀样有⼀个单独的服务器ZooKeeper状态⽆法复制。在仲裁模式下具有⼀组ZooKeeper服务器我们称为ZooKeeper集合ZooKeeper ensemble它们之前可以进⾏状态的复制并同时为服务于客户端的请求。从这个⾓度出发我们使⽤术语“ZooKeeper集合”来表⽰⼀个服务器设施这⼀设施可以由独⽴模式的⼀个服务器组成也可以仲裁模式下的多个服务器组成 2.1 ZooKeeper 仲裁模式 在仲裁模式下ZooKeeper复制集群中的所有服务器的数据树。但如果让⼀个客户端等待每个服务器完成数据保存后再继续延迟问题将⽆法接受。在公共管理领域法定⼈数是指进⾏⼀项投票所需的⽴法者的最⼩数量。⽽在ZooKeeper中则是指为了使ZooKeeper⼯作必须有效运⾏的服务器的最⼩数量。这个数字也是服务器告知客户端安全保存数据前需要保存客户端数据的服务器的最⼩个数。例如我们⼀共有5个ZooKeeper服务器但法定⼈数为3个这样只要任何3个服务器保存了数据客户端就可以继续⽽其他两个服务器最终也将捕获到数据并保存数据。选择法定⼈数准确的⼤⼩是⼀个⾮常重要的事。法定⼈数的数量需要保证不管系统发⽣延迟或崩溃服务主动确认的任何更新请求需要保持下去直到另⼀个请求代替它。 为了明⽩这到底是什么意思让我们先来通过⼀个例⼦来看看如果法定⼈数太⼩会如何出错。假设有5个服务器并设置法定⼈数为2现在服务器s1和s2确认它们需要对⼀个请求创建的znode/z进⾏复制服务返回客户端指出znode创建完成。现在假设在复制新的znode到其他服务器之前服务器s1和s2与其他服务器和客户端发⽣了长时间的分区隔离整个服务的状态仍然正常因为基于我们的假设设定法定⼈数为2⽽现在还有3个服务器但这3个服务器将⽆法发现新的znode/z。因此对创建节点/z的请求是⾮持久化的。 这就是第1章中讲述的脑裂场景的例⼦。为了避免这个问题这个例⼦中法定⼈数的⼤⼩必须⾄少为3即集合中5个服务器的多数原则。为了能正常⼯作集合中⾄少要有3个有效的服务器。为了确认⼀个请求对状态的更新是否成功完成这个集合同时需要⾄少3个服务器确认已经完成了数据的复制操作。因此如果要保证集合可以正常⼯作对任何更新操作的成功完成我们⾄少要有1个有效的服务器来保存更新的副本即⾄少在⼀个节点上合理的法定⼈数存在交集。 通过使⽤多数⽅案我们就可以容许f个服务器的崩溃在这⾥f为⼩于集合中服务器数量的⼀半。例如如果有5个服务器可以容许最多f2个崩溃。在集合中服务器的个数并不是必须为奇数只是使⽤偶数会使得系统更加脆弱。假设在集合中使⽤4个服务器那么多数原则对应的数量为3个服务器。然⽽这个系统仅能容许1个服务器崩溃因为两个服务器崩溃就会导致系统失去多数原则的状态。因此在4个服务器的情况下我们仅能容许⼀个服务器崩溃⽽法定⼈数现在却更⼤这意味着对每个请求我们需要更多的确认操作。底线是我们需要争取奇数个服务器。我们允许法定⼈数的数量不同于多数原则。 仲裁模式搭建见Zookeeper 集群搭建 2.3 选举机制 1Zookeeper 第一次启动 ​ SID服务器ID。用来唯一标识一台ZooKeeper集群中的机器每台机器不能重复和myid一致。 ​ ZXID事务ID。ZXID是一个事务ID用来标识一次服务器状态的变更。在某一时刻集群中的每台机器的ZXID值不一定完全一致这和ZooKeeper服务器对于客户端“更新请求”的处理逻辑有关。 ​ Epoch每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加 5台服务器的集群的选举流程 ① 服务器1启 动发起一次选举。服务器1投自己一票。此时服务器1票数一票不够半数以上3票选举无法完成服务器1状态保持为LOOKING ② 服务器2启动再发起一次选举。服务器1和2分别投自己一票并交换选票信息此时服务器1发现服务器2的myid比自己目前投票推举的服务器1 大更改选票为推举服务器2。此时服务器1票数0票服务器2票数2票没有半数以上结果选举无法完成服务器12状态保持LOOKING ③ 服务器3启动发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果服务器1为0票服务器2为0票服务器3为3票。此时服务器3的票数已经超过半数服务器3当选Leader。服务器12更改状态为FOLLOWING服务器3更改状态为LEADING ④ 服务器4启动发起一次选举。此时服务器123已经不是LOOKING状态不会更改选票信息。交换选票信息结果服务器3为3票服务器4为 1票。此时服务器4服从多数更改选票信息为服务器3并更改状态为FOLLOWING ⑤ 服务器5启动同4一样当小弟。 2Zookeeper 非第一次启动 1当ZooKeeper集群中的一台服务器出现以下两种情况之一时就会开始进入Leader选举 服务器初始化启动。 服务器运行期间无法和Leader保持连接。 2当一台机器进入Leader选举流程时当前集群也可能会处于以下两种状态 集群中本来就已经存在一个Leader 机器试图去选举Leader时会被告知当前服务器的Leader信息对于该机器来说仅仅需要和Leader机器建立连接并进行状态同步即可 集群中确实不存在Leader 假设ZooKeeper由5台服务器组成SID分别为1、2、3、4、5ZXID分别为8、8、8、7、7并且此时SID为3的服务器是Leader。某一时刻3和5服务器出现故障因此开始进行Leader选举。 EPOCHZXIDSID EPOCHZXIDSID EPOCHZXIDSID ​ SID 1181 SID 1182 SID 1 174 选举Leader规则①EPOCH大的直接胜出 ②EPOCH相同事务id大的胜出 ③事务id相同服务器id大的胜出 2.3 会话 在对ZooKeeper集合执⾏任何请求前⼀个客户端必须先与服务建⽴会话。客户端提交给ZooKeeper的所有操作均关联在⼀个会话上。当⼀个会话因某种原因⽽中⽌时在这个会话期间创建的临时节点将会消失。 当客户端通过某⼀个特定语⾔套件来创建⼀个ZooKeeper句柄时它就会通过服务建⽴⼀个会话。客户端初始连接到集合中某⼀个服务器或⼀个独⽴的服务器。客户端通过TCP协议与服务器进⾏连接并通信但当会话⽆法与当前连接的服务器继续通信时会话就可能转移到另⼀个服务器上。ZooKeeper客户端库透明地转移⼀个会话到不同的服务器。 会话提供了顺序保障这就意味着同⼀个会话中的请求会以FIFO先进先出顺序执⾏。通常⼀个客户端只打开⼀个会话因此客户端请求将全部以FIFO顺序执⾏。如果客户端拥有多个并发的会话FIFO顺序在多个会话之间未必能够保持。⽽即使⼀个客户端中连贯的会话并不重叠也未必能够保证FIFO顺序。下⾯的情况说明如何发⽣这种问题 客户端建立了⼀个会话并通过两个连续的异步调用来创建/tasks 和/workers。 第⼀个会话过期。 客户端创建另⼀个会话并通过异步调用创建/assign。 在这个调⽤顺序中可能只有/tasks和/assign成功创建了因为第⼀个会话保持了FIFO顺序但在跨会话时就违反了FIFO顺序。 1会话的生命周期lifetime 会话的⽣命周期是指会话从创建到结束的时期⽆论会话正常关闭还是因超时⽽导致过期。 会话状态CONNECTING、CONNECTED、CLOSED和NOT_CONNECTED。 状态的转换 依赖于发⽣在客户端与服务之间的各种事件 ① ⼀个会话从NOT_CONNECTED状态开始当ZooKeeper客户端初始化后转换到CONNECTING状态箭头1 ② 正常情况下成功与ZooKeeper服务器建⽴连接后会话转换到CONNECTED状态箭头2 ③ 当客户端与ZooKeeper服务器断开连接或者⽆法收到服务器的响应时它就会转换回CONNECTING状态箭头3并尝试发现其他ZooKeeper服务器 ④ 如果可以发现另⼀个服务器或重连到原来的服务器当服务器确认会话有效后状态又会转换回CONNECTED状态。否则它将会声明会话过期然后转换到CLOSED状态箭头4 ⑤ 应⽤也可以显式地关闭会话箭头4 和箭头5 **注意发⽣⽹络分区时等待CONNECTING ** 如果⼀个客户端与服务器因超时⽽断开连接客户端仍然保持CONNECTING状态。如果因⽹络分区问题导致客户端与ZooKeeper集合被隔离⽽发⽣连接断开那么其状态将会⼀直保持直到显式地关闭这个会话或者分区问题修复后客户端能够获悉ZooKeeper服务器发送的会话已经过期。发⽣这种⾏为是因为ZooKeeper集合对声明会话超时负责⽽不是客户端负责。直到客户端获悉ZooKeeper会话过期否则客户端不能声明自⼰的会话过期。然⽽客户端可以选择关闭会话。 创建⼀个会话时你需要设置会话超时这个重要的参数这个参数设置了ZooKeeper服务允许会话被声明为超时之前存在的时间。如果经过时间t之后服务接收不到这个会话的任何消息服务就会声明会话过期。⽽在客户端侧如果经过t/3的时间未收到任何消息客户端将向服务器发送⼼跳消息。在经过2t/3时间后ZooKeeper客户端开始寻找其他的服务器⽽此时它还有t/3时间去寻找。 **注意客户端会尝试连接哪⼀个服务器 ** 在仲裁模式下客户端有多个服务器可以连接⽽在独立模式下客户端只能尝试重新连接单个服务器。在仲裁模式中应用需要传递可用的服务器列表给客户端告知客户端可以连接的服务器信息并选择⼀个进⾏连接。 当尝试连接到⼀个不同的服务器时⾮常重要的是这个服务器的ZooKeeper状态要与最后连接的服务器的ZooKeeper状态保持最新。客户端不能连接到这样的服务器它未发现更新⽽客户端却已经发现的更新。ZooKeeper通过在服务中排序更新操作来决定状态是否最新。ZooKeeper确保每⼀个变化相对于所有其他已执⾏的更新是完全有序的。因此如果⼀个客户端在位置i观察到⼀个更新它就不能连接到只观察到i’i的服务器上。在ZooKeeper实现中系统根据每⼀个更新建⽴的顺序来分配给事务标识符。 图2-7 描述了在重连情况下事务标识符zkid的使⽤。当客户端因超时与s1断开连接后客户端开始尝试连接s2但s2延迟于客户端所知的变化。然⽽s3对这个变化的情况与客户端保持⼀致所以s3可以安全连接 2.4 监听器原理 ​ 客户端注册监听它关心的目录节点当目录节点发生变化数据改变、节点删除、子目录节点增加删除时ZooKeeper 会通知客户端。监听机制保证 ZooKeeper 保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。 1监听原理详解 ​ ① 首先要有一个main()线程 ​ ② 在main线程中创建Zookeeper客户端这时就会创建两个线程一个负责网络连接通信connet一个负责监听listener。 ​ ③ 通过connect线程将注册的监听事件发送给Zookeeper。 ​ ④ 在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。 ​ ⑤ Zookeeper监听到有数据或路径变化就会将这个消息发送给listener线程。 ​ ⑥ listener线程内部调用了process()方法。 2常见的监听 ​ ① 监听节点数据的变化 get path [watch]​ ② 监听子节点增减的变化 ls path [watch]3节点的值变化监听 ​ ① 在 hadoop104 主机上注册监听/sanguo 节点数据变化 [zk: localhost:2181(CONNECTED) 26] get -w /sanguo ​ ② 在 hadoop103 主机上修改/sanguo 节点的数据 [zk: localhost:2181(CONNECTED) 1] set /sanguo xisi​ ③ 观察 hadoop104 主机收到数据变化的监听 WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo注意在hadoop103再多次修改/sanguo的值hadoop104上不会再收到监听。因为注册 一次只能监听一次。想再次监听需要再次注册。 4节点的子节点变化监听路径变化 ​ ① 在 hadoop104 主机上注册监听/sanguo 节点的子节点变化 [zk: localhost:2181(CONNECTED) 1] ls -w /sanguo [shuguo, weiguo] ​ ② 在 hadoop103 主机/sanguo 节点上创建子节点 [zk: localhost:2181(CONNECTED) 2] create /sanguo/jin simayi Created /sanguo/jin​ ③ 观察 hadoop104 主机收到子节点变化的监听 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo注意节点的路径变化也是注册一次生效一次。想多次生效就需要多次注册。 2.5 zookeeper常用客户端命令 addauth scheme auth close config [-c] [-w] [-s] connect host:port create [-s] [-e] [-c] [-t ttl] path [data] [acl] delete [-v version] path deleteall path delquota [-n|-b] path get [-s] [-w] path getAcl [-s] path history listquota path ls [-s] [-w] [-R] path ls2 path [watch] printwatches on|off quit reconfig [-s] [-v version] [[-file path] | [-members serverIDhost:port1:port2;port3[,...]*]] | [-add serverIdhost:port1:port2;port3[,...]]* [-remove serverId[,...]*] redo cmdno removewatches path [-c|-d|-a] [-l] rmr path set [-s] [-v version] path data setAcl [-s] [-v version] [-R] path acl setquota -n|-b val path stat [-w] path sync path1查询节点 ① 查询子节点列表 ls [-s] [-w] [-R] pathls 列出绝对路径path下的所有子节点信息列出一级不递归 -s 查看节点信息取代ls2 -R 递归显示子节点 -w 为节点设置监视 ② 查看节点数据 get [-s] [-w] pathget 查看节点值 -s 查询节点值节点属性 -w 为在数据更改上做监视 ③ stat 查看节点属性 stat [-w] path查看当前节点详细数据 [zk: hadoop102:2181(CONNECTED) 5] ls -s / [zookeeper]cZxid 0x0 ctime Thu Jan 01 08:00:00 CST 1970 mZxid 0x0 mtime Thu Jan 01 08:00:00 CST 1970 pZxid 0x0 cversion -1 dataVersion 0 aclVersion 0 ephemeralOwner 0x0 dataLength 0 numChildren 1① czxid创建节点的事务 zxid 每次修改 ZooKeeper 状态都会产生一个 ZooKeeper 事务 ID。事务 ID 是 ZooKeeper 中所有修改总的次序。每次修改都有唯一的 zxid如果 zxid1 小于 zxid2那么 zxid1 在 zxid2 之前发生。 ② ctimeznode 被创建的毫秒数从 1970 年开始 ③ mzxidznode 最后更新的事务 zxid ④ mtimeznode 最后修改的毫秒数从 1970 年开始 ⑤ pZxidznode 最后更新的子节点 zxid ⑥ cversionznode 子节点变化号znode 子节点修改次数 ⑦ dataversionznode 数据变化号 ⑧ aclVersionznode 访问控制列表的变化号 ⑨ ephemeralOwner如果是临时节点这个是 znode 拥有者的 session id。如果不是 临时节点则是 0。 ⑩ dataLengthznode 的数据长度 ⑪ numChildrenznode 子节点数量 2新增节点 create [-s] [-e] [-c] [-t ttl] path [data] [acl]-s 要创建的znode是顺序节点 -e 要创建的znode是临时节点 -c 要创建的znode是容器节点 -t znode的失效时间 path 要创建的znode绝对路径 data znode保存的数据 acl znode的访问权限 其中-s为有序节点 -e为临时节点 -t指定ttl节点 当删除掉容器节点container节点下的所有子节点后 container节点本身也会被清除掉默认被清除的时间是60s 3修改节点 set [-s] [-v version] path dataset可以基于版本号进行修改类似于乐观锁机制。如果传入的版本号dataVersion和当前版本号不一致时zookeeper会拒绝本次修改 4删除节点 delete删除节点如果该节点下存在子节点该节点不允许删除。 deleteall删除某个节点极其所有后代节点也可以使用rmr path命令进行递归删除。 删除节点和更新节点一样也可以传入版本号当传入的数据版本号和当前节点的数据版本不一致时zookeeper不会执行删除操作。 [zk: localhost:2181(CONNECTED) 7] delete /wfj Node not empty: /wfj [zk: localhost:2181(CONNECTED) 10] deleteall /wfj [zk: localhost:2181(CONNECTED) 24] delete -v 1 /wfj version No is not valid : /wfj [zk: localhost:2181(CONNECTED) 25] delete -v 0 /wfj2.6 实现一个原语通过Zookeeper实现锁 假设有⼀个应⽤由n个进程组成这些进程尝试获取⼀个锁。再次强调ZooKeeper并未直接暴露原语因此我们使⽤ZooKeeper的接⼜来管理znode以此来实现锁。为了获得⼀个锁每个进程p尝试创建znode名为/lock。如果进程p成功创建了znode就表⽰它获得了锁并可以继续执⾏其临界区域的代码。不过⼀个潜在的问题是进程p可能崩溃导致这个锁永远⽆法释放。在这种情况下没有任何其他进程可以再次获得这个锁整个系统可能因死锁⽽失灵。为了避免这种情况我们不得不在创建这个节点时指定/lock为临时节点。 其他进程因znode存在⽽创建/lock失败。因此进程监听/lock的变化并在检测到/lock删除时再次尝试创建节点来获得锁。当收到/lock删除的通知时如果进程p还需要继续获取锁它就继续尝试创建/lock的步骤如果其他进程已经创建了就继续监听节点。 2.7 主从例子的实现 主-从模式的模型中包括三个⾓⾊ 主节点负责监视新的从节点和任务分配任务给可⽤的从节点。 从节点 通过系统注册⾃⼰以确保主节点看到它们可以执⾏任务然后开始监视新任务。 客户端创建新任务并等待系统的响应。 1主节点角色 因为只有⼀个进程会成为主节点所以⼀个进程成为ZooKeeper的主节点后必须锁定管理权。为此进程需要创建⼀个临时znode名为/master [zk: localhost:2181(CONNECTED) 0] create -e /master master1.example.com:2223 Created /master [zk: localhost:2181(CONNECTED) 1] ls [master, zookeeper] [zk: localhost:2181(CONNECTED) 2] get /master master1.example.com:2223 cZxid 0x67 ctime Tue Dec 11 10:06:19 CET 2012 mZxid 0x67 mtime Tue Dec 11 10:06:19 CET 2012 pZxid 0x67 cversion 0 dataVersion 0 aclVersion 0 ephemeralOwner 0x13b891d4c9e0005 dataLength 26 numChildren 0 [zk: localhost:2181(CONNECTED) 3]在znode中添加了主机信息以便ZooKeeper外部的其他进程需要与它通信。添加主机信息并不是必需的但这样做仅仅是为了说明我们可以在需要时添加数据。为了设置znode为临时性的需要添加-e标志。 假如其他进程不知道已经有⼀个主节点被选举出来并尝试创建⼀个/master节点 [zk: localhost:2181,localhost:2182,localhost:2183(CONNECTED) 0] create -e /master master2.example.com:2223 Node already exists: /master 在/master节点上设置⼀个监视点用来检测主节点是否崩溃备份主节点需要接替活动主节点的⾓⾊ [zk: localhost:2181,localhost:2182,localhost:2183(CONNECTED) 0] create -e /master master2.example.com:2223 Node already exists: /master [zk: localhost:2181,localhost:2182,localhost:2183(CONNECTED) 1] stat -w /master cZxid 0x100000003 ctime Fri Apr 01 19:28:11 CST 2022 mZxid 0x100000003 mtime Fri Apr 01 19:28:11 CST 2022 pZxid 0x100000003 cversion 0 dataVersion 0 aclVersion 0 ephemeralOwner 0x204628945f00000 dataLength 7 numChildren 0当主节点崩溃时 [zk: localhost:2181,localhost:2182,localhost:2183(CONNECTED) 2] WATCHER:: WatchedEvent state:SyncConnected type:NodeDeleted path:/master [zk: localhost:2181,localhost:2182,localhost:2183(CONNECTED) 3] ls / [zookeeper]NodeDeleted事件指出活动主节点的会话已经关闭或过期。同时注意/master节点已经不存在了。现在备份主节点通过再次创建/master节点来成为活动主节点。 [zk: localhost:2181,localhost:2182,localhost:2183(CONNECTED) 4] create -e /master master2.example.com:2223 Created /master因为备份主节点成功创建了/master节点所以现在客户端开始成为活动主节点。 2从节点、任务、分配 先创建三个重要的⽗znode/workers、/tasks和/assign [zk: localhost:2181(CONNECTED) 0] create /workers Created /workers [zk: localhost:2181(CONNECTED) 1] create /tasks Created /tasks [zk: localhost:2181(CONNECTED) 2] create /assign Created /assign [zk: localhost:2181(CONNECTED) 3] ls / [assign, tasks, workers, master, zookeeper] [zk: localhost:2181(CONNECTED) 4]这三个新的znode为持久性节点且不包含任何数据。本例中通过使⽤这些znode可以告诉我们哪个从节点当前有效还告诉我们当前有任务需要分配并向从节点分配任务。 在真实的应⽤中这些znode可能由主进程在分配任务前创建也可能由⼀个引导程序创建不管这些节点是如何创建的⼀旦这些节点存在了主节点就需要监视/workers和/tasks的⼦节点的变化情况 [zk: localhost:2181(CONNECTED) 4] ls -w /workers [] [zk: localhost:2181(CONNECTED) 5] ls -w /tasks [] [zk: localhost:2181(CONNECTED) 6]3从节点角色 从节点⾸先要通知主节点告知从节点可以执⾏任务。从节点通过在/workers⼦节点下创建临时性的znode来进⾏通知并在⼦节点中使⽤主名来标识⾃⼰ [zk: localhost:2181(CONNECTED) 0] create -e /workers/worker1.example.com worker1.example.com:2224 Created /workers/worker1.example.com [zk: localhost:2181(CONNECTED) 1] 注意输出中ZooKeeper确认znode已经创建。之前主节点已经监视了/workers的⼦节点变化情况。⼀旦从节点在/workers下创建了⼀个znode主节点就会观察到以下通知信息 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/workers 下⼀步从节点需要创建⼀个⽗znode/assing/worker1.example.com来接收任务分配并通过第⼆个参数为true的ls命令来监视这个节点的变化以便等待新的任务。 [zk: localhost:2181(CONNECTED) 0] create -e /workers/worker1.example.com worker1.example.com:2224 Created /workers/worker1.example.com [zk: localhost:2181(CONNECTED) 1] create /assign/worker1.example.com [zk: localhost:2181(CONNECTED) 2] ls -w /assign/worker1.example.com从节点现在已经准备就绪可以接收任务分配。 4客户端角色 客户端向系统中添加任务。假设客户端请求主从系统来运⾏cmd命令。为了向系统添加⼀个任务客户端执⾏以下操作 [zk: localhost:2181(CONNECTED) 0] create -s /tasks/task- cmd Created /tasks/task-0000000000 我们需要按照任务添加的顺序来添加znode其本质上为⼀个队列。客户端现在必须等待任务执⾏完毕。执⾏任务的从节点将任务执⾏完毕后会创建⼀个znode来表⽰任务状态。客户端通过查看任务状态的znode是否创建来确定任务是否执⾏完毕因此客户端需要监视状态znode的创建事件 [zk: localhost:2181(CONNECTED) 1] ls -w /tasks/task-0000000000 [] [zk: localhost:2181(CONNECTED) 2] 执⾏任务的从节点会在/tasks/task-0000000000节点下创建状态znode节点所以我们需要⽤ls命令来监视/tasks/task-0000000000的⼦节点。⼀旦创建任务的znode主节点会观察到以下事件 [zk: localhost:2181(CONNECTED) 6] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks 主节点之后会检查这个新的任务获取可⽤的从节点列表之后分配这个任务给worker1.example.com [zk: 6] ls /tasks [task-0000000000] [zk: 7] ls /workers [worker1.example.com] [zk: 8] create /assign/worker1.example.com/task-0000000000 Created /assign/worker1.example.com/task-0000000000 [zk: 9] 从节点接收到新任务分配的通知 [zk: localhost:2181(CONNECTED) 3] WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/assign/worker1.example.com 从节点之后便开始检查新任务并确认该任务是否分配给⾃⼰ WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/assign/worker1.example.com [zk: localhost:2181(CONNECTED) 3] ls /assign/worker1.example.com [task-0000000000] [zk: localhost:2181(CONNECTED) 4] ⼀旦从节点完成任务的执⾏它就会在/tasks中添加⼀个状态znode [zk: localhost:2181(CONNECTED) 4] create /tasks/task-0000000000/status done Created /tasks/task-0000000000/status [zk: localhost:2181(CONNECTED) 5] 之后客户端接收到通知并检查执⾏结果 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/tasks/task-0000000000 [zk: localhost:2181(CONNECTED) 2] get /tasks/task-0000000000 cmd cZxid 0x7c ctime Tue Dec 11 10:30:18 CET 2012 mZxid 0x7c mtime Tue Dec 11 10:30:18 CET 2012 pZxid 0x7e cversion 1 dataVersion 0 aclVersion 0 ephemeralOwner 0x0 dataLength 5 numChildren 1 [zk: localhost:2181(CONNECTED) 3] get /tasks/task-0000000000/status done cZxid 0x7e ctime Tue Dec 11 10:42:41 CET 2012 mZxid 0x7e mtime Tue Dec 11 10:42:41 CET 2012 pZxid 0x7e cversion 0 dataVersion 0 aclVersion 0 ephemeralOwner 0x0 dataLength 8 numChildren 0 [zk: localhost:2181(CONNECTED) 4] 客户端检查状态znode的信息并确认任务的执⾏结果。可以看到任务成功执⾏其状态为“done”。当然任务也可能⾮常复杂甚⾄涉及另⼀个分布式系统。最终不管是什么样的任务执⾏任务的机制与通过ZooKeeper来传递结果本质上都是⼀样的。 九、参考资料 Zookeeper 分布式过程.pdf权限、锁机制、Watch机制
http://www.hkea.cn/news/14282477/

相关文章:

  • 营销型网站的建设软文使馆网站建设
  • 建设一个怎样的自己的网站建设一个打鱼游戏网站
  • 怎样做企业手机网站建设网页设计与制作配套素材
  • 滁州市大滁城建设网站wordpress数据搬移
  • 德化县住房和城乡建设局网站东道设计地址
  • 明年做那个网站能致富中国建设协会官网证件查询
  • 网站广告投放价格表广西建设厅考试网站首页
  • 网站排名必做阶段性seo策略获取更多付费流量
  • 湖南土特产销售网网站建设制作dede投票类网站源码
  • 如何在外管局网站做延期收汇鲁班设计远程工作
  • 贸易公司寮步网站建设哪家好信息流广告案例
  • 海外社交网站开发推广普通话的文章
  • 外贸如何建立网站企业网站的页面信息该如何排放
  • 义乌婚介网站建设杭州电商网站建设公司
  • 关于国家对网站建设临沂网站制作计划
  • 广州网站建设快速排名公众号怎么弄好看的模板
  • 企业网站设计seo中国电信网站备案流程
  • 贵州网站开发百度推广竞价排名
  • 福州网站建设模板网站建设目标有哪几个方面
  • 平邑网站建设龙岩seo外包公司
  • vs做的网站排版错位国外的跨境电商平台有哪些
  • 打开网站很慢wordpress m1 cms
  • 专业制作假行驶证nginx wordpress优化
  • 惠州 光电 网站上线优秀网站案例
  • app网站开发后台处理数据网站建设成本
  • 广州犀牛云网站建设贵州省水利建设管理总站网站
  • 长沙市建设厅官方网站织梦与wordpress
  • 济南网站优化技术厂家网站开发 实时更新
  • 网站 dns 解析商业信息发布平台
  • iis服务器的默认网站凡科网登录下载