barriers / 阅读 / 详情

ZooKeeper在HBase中的应用

2023-08-17 14:17:46
共1条回复
ardim

ZooKeeper是一个开源的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。

既然ZooKeeper的作用这么大,那我们就来详细说说ZooKeeper在HBase中的应用叭!

一个分布式HBase系统安装依赖于一个运行着的ZooKeeper集群,所有参与的节点和客户端必须能够正常访问运行着的ZooKeeper集群。HBase默认为你提供一个节点的ZooKeeper集群,它会伴随着HBase start/stop进程的启动/停止而启动/停止。那么HBase主要用ZooKeeper来干什么呢?HBase主要用ZooKeeper来实现HMaster选举与主备切换、系统容错、RootRegion管理、Region状态管理和分布式SplitWAL任务管理等。

一,HMaster选举与主备切换

HMaster选举与主备切换的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。

二,系统容错

当HBase启动时,每个RegionServer都会到ZooKeeper的/hbase/rs节点下创建一个信息节点(下文中,我们称该节点为”rs状态节点”),例如/hbase/rs/[Hostname],同时,HMaster会对这个节点注册监听。当某个 RegionServer 挂掉的时候,ZooKeeper会因为在一段时间内无法接受其心跳(即 Session 失效),而删除掉该 RegionServer 服务器对应的 rs 状态节点。与此同时,HMaster 则会接收到 ZooKeeper 的 NodeDelete 通知,从而感知到某个节点断开,并立即开始容错工作。

按照上面所说,那为什么HBase不直接让HMaster来负责RegionServer的监控呢?如果HMaster直接通过心跳机制等来管理RegionServer的状态,随着集群越来越大,HMaster的管理负担会越来越重,另外它自身也有挂掉的可能,因此数据还需要持久化。在这种情况下,ZooKeeper就成了理想的选择。

三,Region管理

对于大的HBase集群来说,Region的数量可能会多达十万级别,甚至更多,这样规模的Region状态管理交给ZooKeeper来做也是一个非常nice的选择。

四,分布式SplitWAL任务管理

当某台RegionServer服务器挂掉时,由于总有一部分新写入的数据还没有持久化到HFile中,因此在迁移该RegionServer的服务时,一个重要的工作就是从WAL中恢复这部分还在内存中的数据,而这部分工作最关键的一步就是SplitWAL,即HMaster需要遍历该RegionServer服务器的WAL,并按Region切分成小块移动到新的地址下,并进行日志的回放(replay)。

由于单个RegionServer的日志量相对庞大(可能有上千个Region,上GB的日志),而用户又往往希望系统能够快速完成日志的恢复工作。因此一个可行的方案是将这个处理WAL的任务分给多台RegionServer服务器来共同处理,而这就又需要一个持久化组件来辅助HMaster完成任务的分配。当前的做法是,HMaster会在ZooKeeper上创建一个SplitWAL节点(默认情况下,是/hbase/SplitWAL节点),将“哪个RegionServer处理哪个Region”这样的信息以列表的形式存放到该节点上,然后由各个RegionServer服务器自行到该节点上去领取任务并在任务执行成功或失败后再更新该节点的信息,以通知HMaster继续进行后面的步骤。ZooKeeper在这里担负起了分布式集群中相互通知和信息持久化的角色。

u200b

综上,就是ZooKeeper在HBase中的应用,在这里只列举出了一部分,相对说比较突出的作用,其实ZooKeeper在HBase中的应用远不止这些,比如HMaster还依赖ZooKeeper来完成Table的enable/disable状态记录,以及HBase中几乎所有的元数据存储都是放在ZooKeeper上的等等。

相关推荐

Zookeeper深入原理

Zookeeper 的视图结构是一个树形结构,树上的每个节点称之为数据节点(即 ZNode),每个ZNode 上都可以保存数据,同时还可以挂载子节点。并且Zookeeper的根节点为 "/"。 在 Zookeeper 中,每个数据节点都是有生命周期的,其生命周期的长短取决于数据节点的节点类型。在 Zookeeper 中有如下几类节点: 每个数据节点中除了存储了数据内容之外,还存储了数据节点本身的一些状态信息(State)。 在Zookeeper 中,事务是指能够改变 Zookeeper 服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新和客户端会话创建与失效等操作。对于每一个事务请求,Zookeeper 都会为其分配一个全局唯一的事务ID,用 ZXID 来表示,通常是一个 64 位的数字。每一个 ZXID 对应一次更新操作,从这些 ZXID 中可以间接地识别出 Zookeeper 处理这些更新操作请求的全局顺序。 ZXID 是一个 64 位的数字,其中低 32 位可以看作是一个简单的单调递增的计数器,针对客户端的每一个事务请求,Leader 服务器在产生一个新的事务 Proposal 的时候,都会对该计数器进行加 1 操作;而高 32 位则代表了 Leader 周期 epoch 的编号,每当选举产生一个新的 Leader 服务器,就会从这个 Leader 服务器上取出其本地日志中最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值,然后再对其进行加 1 操作,之后就会以此编号作为新的 epoch,并将低 32 位置 0 来开始生成新的 ZXID。 Zookeeper 中为数据节点引入了版本的概念,每个数据节点都具有三种类型的版本信息(在上面的状态信息中已经介绍了三种版本信息代表的意思),对数据节点的任何更新操作都会引起版本号的变化。其中我们以 dataVersion 为例来说明。在一个数据节点被创建完毕之后,节点的dataVersion 值是 0,表示的含义是 ”当前节点自从创建之后,被更新过 0 次“。如果现在对该节点的数据内容进行更新操作,那么随后,dataVersion 的值就会变成 1。即表示的是对数据节点的数据内容的变更次数。 版本的作用是用来实现乐观锁机制中的 “写入校验” 的。例如,当要修改数据节点的数据内容时,带上版本号,如果数据节点的版本号与传入的版本号相等,就进行修改,否则修改失败。 Zookeeper 提供了分布式数据的发布/订阅功能。一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。在 Zookeeper 中,引入了 Watcher 机制来实现这种分布式的通知功能。Zookeeper 允许客户端向服务端注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。 从上图可以看出 Zookeeper 的 Watcher 机制主要包括客户端线程、客户端WatchMananger 和 Zookeeper 服务器三部分。在具体工作流程上,简单地讲,客户端在向 Zookeeper 服务器注册 Watcher 的同时,会将 Watcher 对象存储在客户端的 WatchMananger 中。当 Zookeeper 服务器端触发 Watcher 事件后,会向客户端发送通知,客户端线程从 WatchManager 中取出对应的 Watcher 对象来执行回调逻辑。 Watcher是一个接口,任何实现了Watcher接口的类就是一个新的Watcher。Watcher内部包含了两个枚举类:KeeperState、EventType 注 :客户端接收到的相关事件通知中只包含状态及类型等信息,不包括节点变化前后的具体内容,变化前的数据需业务自身存储,变化后的数据需调用get等方法重新获取; 上面讲到zookeeper客户端连接的状态和zookeeper对znode节点监听的事件类型,下面我们来讲解如何建立zookeeper的watcher监听。在zookeeper中采用zk.getChildren(path, watch)、zk.exists(path, watch)、zk.getData(path, watcher, stat)这样的方式为某个znode注册监听。 下表以node-x节点为例,说明调用的注册方法和可监听事件间的关系: Zookeeper 中提供了一套完善的 ACL(Access Control List)权限控制机制来保障数据的安全。 ACL 由三部分组成,分别是:权限模式(Scheme)、授权对象(ID)和权限(Permission),通常使用“scheme: u200bid:permission”来标识一个有效的ACL 信息。下面分别介绍: 1.7.4、ACL 超级管理员 zookeeper的权限管理模式有一种叫做super,该模式提供一个超管可以方便的访问任何权限的节点 假设这个超管是:super:admin,需要先为超管生成密码的密文 那么打开zookeeper目录下的/bin/zkServer.sh服务器脚本文件,找到如下一行: 这就是脚本中启动zookeeper的命令,默认只有以上两个配置项,我们需要加一个超管的配置项 那么修改以后这条完整命令变成了 之后启动zookeeper,输入如下命令添加权限 在服务器集群初始化阶段,我们以 3 台机器组成的服务器集群为例,当有一台服务器server1 启动的时候,它是无法进行 Leader 选举的,当第二台机器 server2 也启动时,此时这两台服务器已经能够进行互相通信,每台机器都试图找到一个 Leader,于是便进入了 Leader 选举流程。 在zookeeper运行期间,leader与非leader服务器各司其职,即便当有非leader服务器宕机或新加入,此时也不会影响leader,但是一旦leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮leader选举,其过程和启动时期的Leader选举过程基本一致。 假设正在运行的有server1、server2、server3三台服务器,当前leader是server2,若某一时刻leader挂了,此时便开始Leader选举。选举过程如下: observer角色特点: 为了使用observer角色,在任何想变成observer角色的配置文件中加入如下配置: 并在所有server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:
2023-08-10 09:45:421

Zookeeper算法原理

zk算法的演进过程 1.Write-all-read-one 先讨论最简单的副本控制规则 Write-all-read-one(简称 WARO)是一种最简单的副本控制规则,顾名思义即在更新时写所有 的副本, 只有在所有的副本上更新成功,才认为更新成功, 从而保证所有的副本一致,这样在读取数据时可以读任一副本上的数据。 先做这样的约定 :更新操作(write)是一系列顺序的过程,通过其他机制 确定更新操作的顺序(例如 primary-secondary 架构中由 primary 决定顺序),每个更新操作记为 wi, i 为更新操作单调递增的序号,每个 wi执行成功后副本数据都发生变化,称为不同的数据版本,记作 vi。假设每个副本都保存了历史上所有版本的数据。 假设有一种 magic 的机制,当某次更新操作 wi一旦在所有 N 个副本上都成功,此时 全局都能知 道这个信息(现实情况是比较难的) ,此后读取操作将指定读取数据版本为 vi的数据,称在所有 N 个副本上都成功的更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。 在 WARO 中,如果某次更新操作 wi在某个副本上失败,此时该副本的最新的数据只有 vi-1,由于不满足在所有 N 个副本上都成功, 则 wi 不是一个“成功提交的更新操作”,此时,虽然其他 N-1 个副本上最新的数据是 vi,但 vi不是一个“成功提交的数据”,最新的成功提交的数据只是 vi-1 。 在工程实践中,这种 magic 的机制往往较难实现或效率较低。通常实现这种 magic 机制的方式就是 将版本号信息存放到某个或某组元数据服务器上 。假如更新操作非常频繁,那么记录更新成功的版本号 vi的操作将成为一个关键操作,容易成为瓶颈。另外,为了实现强一致性,在读取数据的前必须首先读取元数据中的版本号,在大压力下也容易因为元数据服务器的性能造成瓶颈。 缺点: WARO 的可用性。 由于更新操作需要在所有的 N 个副本上都成功,更新操作才能成功,所以一旦有一个副本异常,更新操作失败,更新服务不可用。对于更新服务,虽然有 N 个副本, 但系统无法容忍任何一个副本异常。另一方面, N 个副本中只要有一个副本正常,系统就可以提供读服务。对于读服务而言,当有 N 个副本时,系统可以容忍 N-1 个副本异常。 从上述分析可以发现 WARO 读服务的可用性较高,但更新服务的可用性不高 ,甚至虽然使用了 副本,但更新服务的可用性等效于没有副本. 2.Quorum 机制 将 WARO 的条件进行松弛,从而使得可以在 读写服务可用性之间做折中 ,得出 Quorum 机制. 在 Quorum 机制下,当某次更新操作 wi一旦在所有 N 个副本中的 W 个副本上都成功,则就称 该更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。令 R>N-W,由于更新 操作 wi仅在 W 个副本上成功,所以在读取数据时,最多需要读取 R 个副本则一定能读到 wi 更新后的数据 vi 。如果某次更新 wi在 W 个副本上成功,由于 W+R>N,任意 R 个副本组成的集合一定与成功的 W 个副本组成的集合有交集,所以读取 R 个副本一定能读到 wi更新后的数据 vi。 例一: 某系统有 5 个副本, W=3, R=3,最初 5 个副本的数据一致,都是 v1, 某次更新操作 w2 在前 3 副本上成功,副本情况变成(v2 v2 v2 v1 v1)。此时, 任意 3 个副本组成的集合中一定包括v2。 例二: N=5, W=2, R=3 时,若 4 个副本异常,更新操作始终无法完成。若 3 个副本异常时, 剩下的两个副本虽然可以提供更新服务,但对于读取者而言,在缺乏某些 magic 机制的,即如果读取者不知道当前最新已成功提交的版本是什么的时候,仅仅读取 2 个副本并不能保证一定可以读到最新的已提交的数据。 得出一个简单的结论: 仅 仅依赖 quorum 机制 是无法保证强一致性的。因为仅有 quorum 机制时 无法确定最新已成功提交的版本号 ,除非将最新已提交的版本号作为元数据由特定的元数据服务器或元数据集群管理,否则很难确定最新成功提交的版本号。 Quorum 机制只需成功更新 N 个副本中的 W 个,在读取 R 个副本时,一定可以读到 最新的成功 提交的数据。 但由于有不成功的更新情况存在,仅仅读取 R 个副本却不一定能确定哪个版本的数据是最新的已提交的数据(简而言之,就是说我读到的结果中包含了v1,v2我可以肯定最新的数据一定是他们两种的一个,但我却没办法确定是哪一个的) 例三: 在 N=5, W=3, R=3 的系统中,某时刻副本最大版本号为(v2 v2 v2 v1 v1)。注意,这里继续假设有 v2 的副本也有 v1,上述列出的只是最大版本号。此时,最新的成功提交的副本应该 是 v2,因为从全局看 v2已经成功更新了 3 个副本。 读取任何 3 个副本,一定能读到 v2。 但仅读 3 个副本时,有可能读到(v2 v1 v1)。 此时,由于 v2蕴含 v1, 可知 v1是一个成功提交的 版本, 但却不能判定 v2一定是一个成功提交的版本。 这是因为 ,假设**副本最大版本号为(v2 v1 v1 v1 v1), 当读取 3 个副本时也可能读到v2 v1 v1) ,此时 v2是一个未成功提交的版本。 所 以在本例中,仅仅读到(v2 v1 v1)时,可以肯定的是最新的成功提交的数据要么是 v1要么是 v2,却没办法确定究竟是哪一个。 对于一个强一致性系统,应该始终读取返回最新的成功提交的数据,在 quorum 机制下,要达 到这一目的需要对读取条件做进一步加强。 1. 限制提交的 更新操作必须严格递增 ,即只有在前一个更新操作成功提交后才可以提交后一 个更新操作,从而成功提交的数据版本号必须是连续增加的。 2. 读取 R 个副本,对于 R 个副本中版本号最高的数据, 2.1 若已存在 W 个,则该数据为最新的成功提交的数据 2.2 若存在个数据少于 W 个, 假设为 X 个, 则继续读取其他副本,直若成功读取到 W 个 该版本的副本,则该数据为最新的成功提交的数据;如果在所有副本中该数据的个数肯定不满 足 W 个,则 R 中版本号第二大的为最新的成功提交的副本。 例四: 依旧接例三,在读取到(v2 v1 v1)时,继续读取剩余的副本,若读到剩余两个副本为(v2 v2)则 v2 是最新的已提交的副本;若读到剩余的两个副本为(v2 v1)或(v1 v1)则 v1是最新成功提交的版本;若读取后续两个副本有任一超时或失败,则无法判断哪个版本是最新的成功提交的版本。 可以看出,在单纯使用 Quorum 机制时,若要确定最新的成功提交的版本,最多需要读取 R+ (W-R-1)=N 个副本,当出现任一副本异常时,读最新的成功提交的版本这一功能都有可能不可用。 实际工程中,应该尽量通过其他技术手段,回避通过 Quorum 机制读取最新的成功提交的版本。例如,当 quorum 机制与 primary-secondary 控制协议结合使用时,可以通过读取 primary 的方式读取到最新的已提交的数据。 在 primary-secondary 协议中,当 primary 异常时,需要选择出一个新的 primary,之后 secondary副本与 primary 同步数据。 通常情况下,选择新的 primary 的工作是由某一中心节点完成的,在引入quorum 机制后,常用的 primary 选择方式与读取数据的方式类似,即中心节点读取 R 个副本,选择R 个副本中版本号最高的副本作为新的 primary。新 primary 与至少 W 个副本完成数据同步后作为新的 primary 提供读写服务。首先, R 个副本中版本号最高的副本一定蕴含了最新的成功提交的数据。再者,虽然不能确定最高版本号的数是一个成功提交的数据,但新的 primary 在随后与 secondary 同步数据,使得该版本的副本个数达到 W,从而使得该版本的数据成为成功提交的数据。 以上这段其实就是zk的原理 简述下就是先用Quorum 机制选择出primary(版本号最高的,版本号是严格递增的),然后再用primary-secondary来同步数据,(我一定可以读取到版本号最高的,虽然此时有可能是已提交也有可能为未提交),但我同步之后可以保证该版本号的副本数达到w,从而使得该版本号的数据成为成功提交的数据. 例五: 在 N=5, W=3, R=3 的系统中,某时刻副本最大版本号为(v2 v2 v1 v1 v1),此时 v1是 系统的最新的成功提交的数据, v2 是一个处于中间状态的未成功提交的数据。假设此刻原 primary副本异常,中心节点进行 primary 切换工作。 这类“中间态”数据究竟作为“脏数据”被删除,还是作为新的数据被同步后成为生效的数据,完全取决于这个数据能否参与新 primary 的选举。此时有以下两种情况 情况一: 若中心节点与其中 3 个副本通信成功,读取到的版本号为(v1 v1 v1),则任 选一个副本作为 primary,新 primary以 v1 作为最新的成功提交的版本并与其他副本同步,当与第 1、第 2 个副本同步数据时,由于第 1、第 2 个副本版本号大于 primary,属于脏数据,删除脏数据,然后重新同步。 情况二: 若中心节点与其他 3 个副本通信成功,读取到的版本号为(v2 v1 v1), 则选取版本号为v2 的副本作为新的 primary,之后,一旦新 primary 与其他 2 个副本完成数据同步,则符合 v2 的副本个数达到 W 个,成为最新的成功提交的副本,新 primary 可以提供正常的读写服务。 一致性算法在实现状态机这种应用时,有以下常见的问题: 1.1 一般的leader选举过程 选举的轮次 1.2 leader选举的效率 1.3 加入一个已经完成选举的集群 怎么发现已完成选举的leader? 1.4 leader选举的触发 3.3.2 异常过程的顺序 follower挂掉又连接 raft与zk的对比 1 leader选举 为什么要进行leader选举? 在实现一致性的方案,可以像base-paxos那样不需要leader选举,这种方案达成一件事情的一致性还好,面对多件事情的一致性就比较复杂了,所以通过选举出一个leader来简化实现的复杂性。 1.1 一般的leader选举过程 更多的有2个要素: 1.1.1 选举投票可能会多次轮番上演,为了区分,所以需要定义你的投票是属于哪个轮次的。 他们都需要在某个轮次内达成过半投票来结束选举过程 1.1.2 投票PK的过程,更多的是日志越新越多者获胜 在选举leader的时候,通常都希望 选举出来的leader至少包含之前全部已提交的日志 自然想到包含的日志越新越大那就越好。 通常都是比较最后一个日志记录,如何来定义最后一个日志记录? 有2种选择,一种就是所有日志中的最后一个日志,另一种就是所有已提交中的最后一个日志。目前Raft和ZooKeeper都是采用前一种方式。日志的越新越大表示:轮次新的优先,然后才是同一轮次下日志记录大的优先 ZooKeeper:peerEpoch大的优先,然后zxid大的优先 但是有一个问题就是:通过上述的日志越新越大的比较方式能达到我们的上述希望吗? 特殊情况下是不能的,这个特殊情况详细可参见我们上面描述的 这个案例就是这种比较方式会 选举出来的leader可能并不包含已经提交的日志(和我们例三分析的一样) ,而Raft的做法则是对于日志的提交多加一个限制条件,即不能直接提交之前term的已过半的entry,即把这一部分的日志限制成未提交的日志,从而来实现上述的希望。 ZooKeeper呢?会不会出现这种情况?又是如何处理的? ZooKeeper是不会出现这种情况的,因为ZooKeeper在每次leader 选举完成之后,都会进行数据之间的同步纠正,所以每一个轮次,大家都日志内容都是统一的 而Raft在leader选举完成之后没有这个同步过程,而是靠之后的AppendEntries RPC请求的一致性检查来实现纠正过程,则就会出现上述案例中隔了几个轮次还不统一的现象 1.2 leader选举的效率 Raft中的每个server在某个term轮次内只能投一次票,哪个candidate先请求投票谁就可能先获得投票,这样就可能造成split vote,即各个candidate都没有收到过半的投票,Raft通过candidate设置不同的超时时间,来快速解决这个问题,使得先超时的candidate(在其他人还未超时时)优先请求来获得过半投票** ZooKeeper中的每个server,在某个electionEpoch轮次内,可以投多次票,只要遇到更大的票就更新,然后分发新的投票给所有人。这种情况下不存在split vote现象,同时有利于选出含有更新更多的日志的server,但是选举时间理论上相对Raft要花费的多。 1.3 加入一个已经完成选举的集群 1.3.1 怎么发现已完成选举的leader? 一个server启动后(该server本来就属于该集群的成员配置之一,所以这里不是新加机器),如何加入一个已经选举完成的集群 1.3.2 加入过程是否阻塞整个请求? 这个其实还要 看对日志的设计是否是连续的 如果 是连续的,则leader中只需要保存每个follower上一次的同步位置,这样在同步的时候就会自动将之前欠缺的数据补上,不会阻塞整个请求过程(****所以为什么redis的选举算法是raft?毕竟redis单线程****) 如果 不是连续的,则在确认follower和leader当前数据的差异的时候,是需要获取leader当前数据的读锁,禁止这个期间对数据的修改。差异确定完成之后,释放读锁,允许leader数据被修改,每一个修改记录都要被保存起来,最后一一应用到新加入的follower中。 1.4 leader选举的触发 触发一般有如下2个时机 2 上一轮次的leader 2.1 上一轮次的leader的残留的数据怎么处理? 首先看下上一轮次的leader在挂或者失去leader位置之前,会有哪些数据? 一个日志是否被过半复制,是否被提交,这些信息是由leader才能知晓的,那么下一个leader该如何来判定这些日志呢? 下面分别来看看Raft和ZooKeeper的处理策略: Raft的保守策略更多是因为Raft在leader选举完成之后,没有同步更新过程来保持和leader一致(在可以对外处理请求之前的这一同步过程)。而ZooKeeper是有该过程的 2.2 怎么阻止上一轮次的leader假死的问题 这其实就和实现有密切的关系了。 3 请求处理流程 3.1 请求处理的一般流程 这个过程对比Raft和ZooKeeper基本上是一致的,大致过程都是过半复制 先来看下Raft: 再来看看ZooKeeper: 备注:数据同步过程就有点类似于两阶段提交了。 假装是图2 3.2 日志的连续性问题 在需要保证顺序性的前提下,在利用一致性算法实现状态机的时候,到底是实现连续性日志好呢还是实现非连续性日志好呢? 还有在复制和提交的时候: 其他有待后续补充 3.3 如何保证顺序 具体顺序是什么? 这个就是先到达leader的请求,先被应用到状态机。这就需要看正常运行过程、异常出现过程都是怎么来保证顺序的 3.3.1 正常同步过程的顺序 3.3.2 异常过程的顺序保证 如follower挂掉又重启的过程: ZooKeeper:重启之后,需要和当前leader数据之间进行差异的确定,同时期间又有新的请求到来,所以需要暂时获取leader数据的读锁,禁止此期间的数据更改,先将差异的数据先放入队列,差异确定完毕之后,还需要将leader中已提交的议案和未提交的议案也全部放入队列,即ZooKeeper的如下2个集合数据 ConcurrentMap<Long, Proposal> outstandingProposals ConcurrentLinkedQueue<Proposal> toBeApplied 如果是leader挂了之后,重新选举出leader,会不会有乱序的问题? 3.4 请求处理流程的异常 一旦leader发给follower的数据出现超时等异常 4 分区的应对 目前ZooKeeper和Raft都是过半即可,所以对于分区是容忍的。如5台机器,分区发生后分成2部分,一部分3台,另一部分2台,这2部分之间无法相互通信 其中,含有3台的那部分,仍然可以凑成一个过半,仍然可以对外提供服务,但是它不允许有server再挂了,一旦再挂一台则就全部不可用了。 含有2台的那部分,则无法提供服务,即只要连接的是这2台机器,都无法执行相关请求。 所以ZooKeeper和Raft在一旦分区发生的情况下是是牺牲了高可用来保证一致性,即CAP理论中的CP。但是在没有分区发生的情况下既能保证高可用又能保证一致性,所以更想说的是所谓的CAP二者取其一,并不是说该系统一直保持CA或者CP或者AP,而是一个会变化的过程。在没有分区出现的情况下,既可以保证C又可以保证A,在分区出现的情况下,那就需要从C和A中选择一样。ZooKeeper和Raft则都是选择了C。
2023-08-10 09:45:491

Zookeeper的功能以及工作原理_功能原理

1.ZooKeeper是什么? ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户 2.ZooKeeper提供了什么? 1)文件系统 2)通知机制 3.Zookeeper文件系统 每个子目录项如 NameService 都被称作为znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。 有四种类型的znode: 1、PERSISTENT-持久化目录节点 客户端与zookeeper断开连接后,该节点依旧存在 2、PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点 客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 3、EPHEMERAL-临时目录节点 客户端与zookeeper断开连接后,该节点被删除 4、EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点 客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号4.Zookeeper通知机制 客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。 5.Zookeeper做了什么? 1.命名服务 2.配置管理 3.集群管理 4.分布式锁 5.队列管理 6.Zookeeper命名服务 在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现。 7.Zookeeper的配置管理 程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。现在把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好8.Zookeeper集群管理 所谓集群管理无在乎两点:是否有机器退出和加入、选举master。 对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。 新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。9.Zookeeper分布式锁 有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。 对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。用完删除掉自己创建的distribute_lock 节点就释放出锁。 对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。10.Zookeeper队列管理 两种类型的队列: 1、同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。 2、队列按照 FIFO 方式进行入队和出队操作。 第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。 第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。 11.分布式与数据复制 Zookeeper作为一个集群提供一致的数据服务,自然,它要在所有机器间做数据复制。数据复制的好处: 1、容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作;2、提高系统的扩展能力 :把负载分布到多个节点上,或者增加节点来提高系统的负载能力;3、提高性能:让客户端本地访问就近的节点,提高用户访问速度。 从客户端读写访问的透明度来看,数据复制集群系统分下面两种: 1、写主(WriteMaster) :对数据的修改提交给指定的节点。读无此限制,可以读取任何一个节点。这种情况下客户端需要对读与写进行区别,俗称读写分离;2、写任意(Write Any):对数据的修改可提交给任意的节点,跟读一样。这种情况下,客户端对集群节点的角色与变化透明。 对zookeeper来说,它采用的方式是写任意。通过增加机器,它的读吞吐能力和响应能力扩展性非常好,而写,随着机器的增多吞吐能力肯定下降(这也是它建立observer的原因),而响应能力则取决于具体实现方式,是延迟复制保持最终一致性,还是立即复制快速响应。 12.Zookeeper角色描述13.Zookeeper与客户端14.Zookeeper设计目的 1.最终一致性:client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。 2.可靠性:具有简单、健壮、良好的性能,如果消息被到一台服务器接受,那么它将被所有的服务器接受。 3.实时性:Zookeeper保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网络延时等原因,Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。 4.等待无关(wait-free):慢的或者失效的client不得干预快速的client的请求,使得每个client都能有效的等待。 5.原子性:更新只能成功或者失败,没有中间状态。 6.顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息a在消息b前发布,则在所有Server上消息a都将在消息b前被发布; 偏序是指如果一个消息b在消息a后被同一个发送者发布,a必将排在b前面。 15.Zookeeper工作原理 Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。 为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。 16.Zookeeper 下 Server工作状态 每个Server在工作过程中有三种状态: LOOKING:当前Server不知道leader是谁,正在搜寻 LEADING:当前Server即为选举出来的leader FOLLOWING:leader已经选举出来,当前Server与之同步 17.Zookeeper选主流程(basic paxos) 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。 1.选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;2.选举线程首先向所有Server发起一次询问(包括自己);3.选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;4.收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;5.线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数,设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。 通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1. 每个Server启动后都会重复以上流程。在恢复模式下,如果是刚从崩溃状态恢复的或者刚启动的server还会从磁盘快照中恢复数据和会话信息,zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复。选主的具体流程图所示:18.Zookeeper选主流程(fast paxos) fast paxos流程是在选举过程中,某Server首先向所有Server提议自己要成为leader,当其它Server收到提议以后,解决epoch和 zxid的冲突,并接受对方的提议,然后向对方发送接受提议完成的消息,重复这个流程,最后一定能选举出Leader。19.Zookeeper同步流程 选完Leader以后,zk就进入状态同步过程。 1. Leader等待server连接;2 .Follower连接leader,将最大的zxid发送给leader;3 .Leader根据follower的zxid确定同步点;4 .完成同步后通知follower 已经成为uptodate状态;5 .Follower收到uptodate消息后,又可以重新接受client的请求进行服务了。20.Zookeeper工作流程-Leader 1 .恢复数据;2 .维持与Learner的心跳,接收Learner请求并判断Learner的请求消息类型;3 .Learner的消息类型主要有PING消息、REQUEST消息、ACK消息、REVALIDATE消息,根据不同的消息类型,进行不同的处理。 PING 消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是 Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。21.Zookeeper工作流程-Follower Follower主要有四个功能: 1.向Leader发送请求(PING消息、REQUEST消息、ACK消息、REVALIDATE消息);2.接收Leader消息并进行处理;3.接收Client的请求,如果为写请求,发送给Leader进行投票;4.返回Client结果。 Follower的消息循环处理如下几种来自Leader的消息: 1 .PING消息: 心跳消息;2 .PROPOSAL消息:Leader发起的提案,要求Follower投票;3 .COMMIT消息:服务器端最新一次提案的信息;4 .UPTODATE消息:表明同步完成;5 .REVALIDATE消息:根据Leader的REVALIDATE结果,关闭待revalidate的session还是允许其接受消息;6 .SYNC消息:返回SYNC结果到客户端,这个消息最初由客户端发起,用来强制得到最新的更新。
2023-08-10 09:45:571

Zookeeper深入原理(3) - Zab协议

Zab协议全称是 Zookeeper Atomic BroadCast (Zookeeper 原子广播),Zookeeper是通过Zab协议来保证分布式事务的一致性。 1.Zab协议是zookeeper专门设计的一种 支持崩溃恢复 的 原子广播协议, 是Zookeeper保证数据一致性的核心算法。 2.在Zookeeper当中依赖Zab协议来保证数据的一致性,基于这个协议,zookeeper实现了一种主备模型,(Leader+Follower)的架构在保证集群中各个副本之间数据的一致性。 Leader负责处理写事务请求,然后Leader将数据同步到Follower节点上。 3.zookeeper客户端会随机连接到集群中的一个节点上,如果是读请求,就会从当前节点进行读取数据,如果是写的请求,就会将事务请求提交到Leader节点,leader节点接收到事务提交,就会广播该事务,如果超过一半节点写入成功,那么该事务就会被提交。1.Zab协议需要确保那些已经在leader服务器上提交的事务最终被所有服务器提交。 2.Zab协议需要确保那些在leader服务器上被提出而没有被提交的事务。 1.使用主进程(leader)来接受客户端并处理客户端的事务请求,并采用Zab的原子广播协议,将服务器数据变更的状态以事务提议的形式广播到所有的follower副本上去。 2.当主进程出现异常,整个zk集群依然能够正常运行。 Zab协议每个leader需要经过三个阶段:发现、同步、广播 发现 :要求Zookeeper集群必须选取出一个leader进程,同时leader需要维护一个follower可用客户端列表,将来客户端可以和这些follower进行通信。 同步 :Leader要将本身的数据与follower进行同步,实现多副本存储,也体现了CAP中的高可用和分区容错。follower将队列中未处理完的消息消费完成后,写入到本地日志中。 广播 :leader接受客户端提出的事务请求,将新的事务请求广播给follower节点。 Zab协议核心:定义了事务请求的处理方式。 1.所有的事务请求必须由一个全局唯一的服务器来协调处理(Leader 服务器),其余的服务器是follower服务器。 2.leader服务器负责将客户端提出的事务请求,转换成一个事务proposal,并将事务proposal分发给集群中follower服务器,也就是向所有follower节点发送数据广播请求。 3.分发之后leader服务器需要等待follower服务器的反馈,在Zab协议中,只要超过半数的follower服务器进行确认了,那么leader就会再次向所有的follower发送commit消息,要求将上一个事务进行提交。 Zab协议包括两种模式: 崩溃恢复 和 消息广播 协议过程 当整个集群启动过程中,或者leader服务器出现宕机或者网络终端等异常时,Zab协议就会进入崩溃恢复模式,选举出新的leader。 当选举出新的leader之后,同时集群中有过半的服务器与该leader服务器完成了状态同步(数据同步),Zab协议就会退出崩溃恢复模型,进入消息广播模式。 如果新增一台服务器加入集群中,当前集群中已经选举出leader,那么加入进来的服务器自动进入恢复模式,找到leader服务器进行状态同步,完成同步后,与其他follower一起参与到广播流程中。 Zookeeper集群中,数据副本的传递策略采用的是消息广播模式。Zab协议中Leader等待follower 的ACK反馈消息,当到达半数以上follower成功反馈即可,不需要等所有的follower全部反馈。leader服务器出现宕机和网络原因等导致leader与过半的follower服务器不能联系,就会自动进入崩溃恢复模式。 在Zab协议中,为了保证程序的正常运行,整个恢复过程结束后需要重新选出一个leader服务器,因此Zab协议需要一个高效且可靠的算法,来保证快速选举出leader。 Leader算法不仅让leader自己知道自己已经被选取为leader,还需要让集群中的所有服务器快速的感知到选举出的新leader服务器。 崩溃恢复包括两个部分: Leader选举 和 数据恢复 Zab 协议如何保证数据一致性假设两种异常情况: 1、一个事务在 Leader 上提交了,并且过半的 Folower 都响应 Ack 了,但是 Leader 在 Commit 消息发出之前挂了。 2、假设一个事务在 Leader 提出之后,Leader 挂了。 要确保如果发生上述两种情况,数据还能保持一致性,那么 Zab 协议选举算法必须满足以下要求: Zab 协议崩溃恢复要求满足以下两个要求 : 1) 确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交 。 2) 确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal 。 根据上述要求 Zab协议需要保证选举出来的Leader需要满足以下条件: 1) 新选举出来的 Leader 不能包含未提交的 Proposal 。 即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点。 2) 新选举的 Leader 节点中含有最大的 zxid 。 这样做的好处是可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作。 Zab 如何数据同步 1)完成 Leader 选举后(新的 Leader 具有最高的zxid),在正式开始工作之前(接收事务请求,然后提出新的 Proposal),Leader 服务器会首先确认事务日志中的所有的 Proposal 是否已经被集群中过半的服务器 Commit。 2)Leader 服务器需要确保所有的 Follower 服务器能够接收到每一条事务的 Proposal ,并且能将所有已经提交的事务 Proposal 应用到内存数据中。等到 Follower 将所有尚未同步的事务 Proposal 都从 Leader 服务器上同步过啦并且应用到内存数据中以后,Leader 才会把该 Follower 加入到真正可用的 Follower 列表中。 Zab 数据同步过程中,如何处理需要丢弃的 Proposal 在 Zab 的事务编号 zxid 设计中,zxid是一个64位的数字。 其中低32位可以看成一个简单的单增计数器,针对客户端每一个事务请求,Leader 在产生新的 Proposal 事务时,都会对该计数器加1。而高32位则代表了 Leader 周期的 epoch 编号。 epoch 编号可以理解为当前集群所处的年代,或者周期。每次Leader变更之后都会在 epoch 的基础上加1,这样旧的 Leader 崩溃恢复之后,其他Follower 也不会听它的了,因为 Follower 只服从epoch最高的 Leader 命令。 每当选举产生一个新的 Leader ,就会从这个 Leader 服务器上取出本地事务日志充最大编号 Proposal 的 zxid,并从 zxid 中解析得到对应的 epoch 编号,然后再对其加1,之后该编号就作为新的 epoch 值,并将低32位数字归零,由0开始重新生成zxid。 Zab 协议通过 epoch 编号来区分 Leader 变化周期 ,能够有效避免不同的 Leader 错误的使用了相同的 zxid 编号提出了不一样的 Proposal 的异常情况。 基于以上策略 当一个包含了上一个 Leader 周期中尚未提交过的事务 Proposal 的服务器启动时,当这台机器加入集群中,以 Follower 角色连上 Leader 服务器后,Leader 服务器会根据自己服务器上最后提交的 Proposal 来和 Follower 服务器的 Proposal 进行比对,比对的结果肯定是 Leader 要求 Follower 进行一个回退操作,回退到一个确实已经被集群中过半机器 Commit 的最新 Proposal 。 本文根据https://www.jianshu.com/p/2bceacd60b8a进行编写。
2023-08-10 09:46:051

Zookpeer是什么?在系统中如何起作用?

Zookeeper分布式服务框架是Apache Hadoop的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题。如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。 我们先看看它都提供了哪些功能,然后再看看使用它的这些功能能做点什么。 简单的说,zookeeper=文件系统+通知机制。 Zookeeper维护一个类似文件系统的数据结构: 每个子目录项如 NameService 都被称作为 znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。 客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。 这个似乎最简单,在zookeeper的文件系统里创建一个目录,即有唯一的path。在我们使用tborg无法确定上游程序的部署机器时即可与下游程序约定好path,通过path即能互相探索发现,不见不散了。 程序总是需要配置的,如果程序分散部署在多台机器上,要逐个改变配置就变得困难。 可以把这些配置全部放到zookeeper上去,保存在 Zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中就好。 集群管理无在乎两点:是否有机器退出和加入、选举master。 对于第一点,所有机器约定在父目录GroupMembers下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它下船了。当然又会有新机器加入,也是类似:所有机器收到通知---新兄弟目录加入,highcount又有了,有人上船了。 对于第二点,我们假设机器创建临时顺序编号目录节点,每次选取编号最小的机器作为master就好。 有了zookeeper的一致性文件系统,锁的问题变得容易。锁服务可以分为两类,一个是保持独占,另一个是控制时序。 对于第一类,我们将zookeeper上的一个znode看作是一把锁,通过createznode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。厕所有言:来也冲冲,去也冲冲,用完删除掉自己创建的distribute_lock 节点就释放出锁。 对于第二类, /distribute_lock 已经预先存在,所有客户端在它下面创建临时顺序编号目录节点,和选master一样,编号最小的获得锁,用完删除,依次方便。 两种类型的队列: 1、 同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。 2、队列按照 FIFO 方式进行入队和出队操作。 第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。 第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。 Zookeeper中的角色主要有以下三类: 系统模型如图所示: Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分 别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。 为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上 了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个 新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。 每个Server在工作过程中有三种状态: 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的 Server都恢复到一个正确的状态。Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的。系统默认的选举算法为fast paxos。先介绍basic paxos流程: 通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数必须是奇数2n+1,且存活的Server的数目不得少于n+1. 选完leader以后,zk就进入状态同步过程。 Leader主要有三个功能: PING消息是指Learner的心跳信息;REQUEST消息是Follower发送的提议信息,包括写请求及同步请求;ACK消息是 Follower的对提议的回复,超过半数的Follower通过,则commit该提议;REVALIDATE消息是用来延长SESSION有效时间。 Leader的工作流程简图如下所示,在实际实现中,流程要比下图复杂得多,启动了三个线程来实现功能。 Follower主要有四个功能: Follower的消息循环处理如下几种来自Leader的消息: Follower的工作流程简图如下所示,在实际实现中,Follower是通过5个线程来实现功能的。 https://blog.csdn.net/xinguan1267/article/details/38422149 https://blog.csdn.net/gs80140/article/details/51496925 https://www.2cto.com/kf/201708/668587.html https://blog.csdn.net/milhua/article/details/78931672 P.S. 这篇文章是本人对网络上关于ZK的文章阅读之后整理所得,作为入门级的了解。个人觉得看了上面的内容就能基本了解Zookeeper的作用了,后面在结合实际项目使用加深自己的了解。 end
2023-08-10 09:46:121

zookeeper服务注册和发现原理

zk的好处就是,服务注册和发现都是事实的。 微服务会对zk进行监听,如果服务有变动,则会实时更新注册信息。 集群建议部署单数个,集群可用服务器超过一半,zk才能对外提供服务。 最少部署3台。 集群模式下, 会有一个leader,和多个follower 。 leader会将服务注册的表同步到各个follower。 leader宕机后, follower会进行选举, 选举的过程中, zk是不对外提供服务的。 这时候,就保证不了可用性(A)。 这样的机制就可以保证一致性。 选举完成后, zk再对外提供服务。
2023-08-10 09:46:281

为什么要使用zookeeper?有什么功能吗?

2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中。当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑
2023-08-10 09:46:381

【Zookeeper系列】基本介绍

在学习一样技术之前,咱们需要先想一下,为什么需要学这一门技术? 许多分布式系统都是基于ZK作为底层核心组件对外提供服务,比如Kafka中,将Broker注册到ZK中,此时ZK充当着多重角色,比如注册中心、选举等;再比如说,我公司目前很多项目都是Dubbo,都是需要基于ZK实现服务发现和注册。 另外,ZK内其实也有很多优秀的算法和设计思想,熟悉ZK源码,也可以提升自己的“内功”。 如何快速入门Zookeeper呢?最简单的方式就是直接看 Zookeeper官网 啦!建议读者多参考官方文档和博客内容一起食用,效果更佳噢~ Zookeeper的 Logo 看起来就像个“铲屎官”,服务动物园内的动物们。 “A Distributed Coordination Service for Distributed Applications”,这是摘取官方的解释,我们可以得知Zookeeper 是一个为 分布式框架 提供协调服务的东东。 举些例子,有哪些分布式框架使用Zookeeper: ZK的作用不止上面几个,其实还可以做到负载均衡、统一配置、分布式队列等,但使用场景相对少,企业级系统中,会使用其他更加专业的框架组件。 分布式锁、注册中心、Leader选举将会是ZK系列中,重点分享的内容,敬请期待哈~ 在ZK中,需要先了解一些专业名词的概念,但不会一下子都列出来,当之后遇到的时候,再重点分析... 在ZK集群中,会分为 Leader 、 Follower 和 Observer 角色。 Leader作为集群的大佬,承担写请求和部分读请求;Follower作为Leader的小弟,将会承担部分读请求,当接收到写请求的时候会转发给Leader,由Leader处理写请求;Observer就有点特殊,Observer节点不参与选举和消息过半机制,这个不清楚的读者可以暂时有个记忆就行,之后遇到会重点说明。 实际上,节点只分为持久节点和临时节点,但有些场景需要保证顺序,所以就会在持久或临时节点的基础上,添加序号(递增的方式),形成持久顺序节点和临时顺序节点。</br> 那么什么是持久节点,什么是临时节点呢?最直观的一个现象就是,每个ZK客户端连接ZK集群后,都会产生一个节点,如果ZK客户端下线后,节点还存在的就是持久节点,若ZK客户端下线后节点也随着消失,那么该节点就是临时节点。 在ZK客户端启动前,可以自定义监听回调函数,这个有什么作用呢?客户端启动后会将监听事件发送给Zookeeper集群,Zookeeper集群中有一个用于记录监听事件的列表,当客户端监听的目录节点发生变化,如节点数据变更、节点增删等,就会通过ZK集群的监听列表,找到对应的客户端回调监听函数,那么客户端这边就可以根据业务场景,做出相应的动作。 ZAB协议的全称是:ZooKeeper Atomic Broadcast。ZAB是Zookeeper保证数据一致性的核心算法。借鉴了Paxos算法的思想,特地为Zookeeper设计的支持崩溃恢复的原子广播协议。其包括两种基本模式: 消息广播 和 崩溃恢复 消息广播指的是,集群中只有一个Leader处理写请求,并将写请求的事件广播给所有Follower,且能够保证数据不丢失。(也就是说,消息的写入是原子性的,因为只能有leader写入) 崩溃恢复指的是,当ZK集群刚启动还没选举出Leader或Leader因故障、重启、网络等原因的时候,ZAB协议会进入崩溃恢复模式,其目的就是为了选举新的Leader,且保证新Leader的数据是最新的,这样就能够避免因为Leader故障而导致单点丢失消息的情况,至于ZAB具体的原理,各位可以先看下以下参考文章,后续有机会我再专门写一篇关于 ZAB 协议的文章~ ZAB 协议参考文章 ZK内的数据模型结构和Unix文件系统非常相似,是一个有层级关系的树形数据结构。在ZK内,树形的数据结构使用称为ZNode节点保存数据,ZNode是ZK中数据结构最小单元,不仅能够保存数据,还能挂载子节点,形成一个有层次关系的树。 值得注意的是,ZNode的创建是纯内存操作的,所以速度很快,然后在ZK内部会定期将ZNode的数据持久化到磁盘上。 众所周知,在实际的企业应用,面对高并发的场景下,肯定是不能单节点部署,而是通过集群部署保证 高并发、高性能、高可用 (简称三高)。 高性能 :由于ZNode节点是纯内存操作,只要ZK部署在高配置的服务器中,三台ZK服务器抗住每秒几万的请求都是没问题的。 高可用 :只要部署奇数的服务器集群(比如3台、5台、11台机器),只要不超过一半的服务器宕机,都能保证ZK集群可用。 高并发 :因为ZNode是纯内存操作,所以在写数据的时候,速度是很快;而ZK集群中Leader和Follower节点都能处理读请求,所以ZK集群高并发能力是很强的。 基于ZAB协议,写请求统一由Leader服务器处理,然后由Leader将写数据的请求广播给其他Follower。 但会不会由于种种原因,如网络波动、Leader脑裂、Follower宕机等,导致消息不一致? 实际上,在ZK中采用2PC两阶段提交的思想,结合ZAB消息广播保证数据一致性。值得注意的是,Zookeeper只能保证最终一致性,并不能保证强一致性 那么具体是怎么保证数据最终一致性的呢?感兴趣的读者可以看下我另外一篇拙作【TODO...】 参考资料: 《从Paxos到Zookeeper分布式一致性原理与实践》 如果觉得文章不错的话,麻烦点个赞哈,你的鼓励就是我的动力!对于文章有哪里不清楚或者有误的地方,欢迎在评论区留言~
2023-08-10 09:46:581

Zookeeper在哪些系统中使用,又是怎么用的

  ZooKeeper作为发现服务的问题   ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它 很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。   在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个 CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就 是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的 职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性 的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且, 作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。   作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算 是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能 因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的,如果你这么用就惨 了!   而且更何况,如果被用作Service发现服务,ZooKeeper本身并没有正确的处理网络分割的问题;而在云端,网络分割问题跟其他类型的 故障一样的确会发生;所以最好提前对这个问题做好100%的准备。就像 Jepsen在 ZooKeeper网站上发布的博客中所说:在ZooKeeper中,如果在同一个网络分区(partition)的节点数(nodes)数达不到 ZooKeeper选取Leader节点的“法定人数”时,它们就会从ZooKeeper中断开,当然同时也就不能提供Service发现服务了。   如果给ZooKeeper加上客户端缓存(注:给ZooKeeper节点配上本地缓存)或者其他类似技术的话可以缓解ZooKeeper因为网 络故障造成节点同步信息错误的问题。 Pinterest与 Airbnb公 司就使用了这个方法来防止ZooKeeper故障发生。这种方式可以从表面上解决这个问题,具体地说,当部分或者所有节点跟ZooKeeper断开的情况 下,每个节点还可以从本地缓存中获取到数据;但是,即便如此,ZooKeeper下所有节点不可能保证任何时候都能缓存所有的服务注册信息。如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper 会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的;所以导致到达这些节点的服务请求 被丢失了。(注:这也是为什么ZooKeeper不满足CAP中A的原因)   更深层次的原因是,ZooKeeper是按照CP原则构建的,也就是说它能保证每个节点的数据保持一致,而为ZooKeeper加上缓存的做法 的 目的是为了让ZooKeeper变得更加可靠(available);但是,ZooKeeper设计的本意是保持节点的数据一致,也就是CP。所以,这样 一来,你可能既得不到一个数据一致的(CP)也得不到一个高可用的(AP)的Service发现服务了;因为,这相当于你在一个已有的CP系统上强制栓了 一个AP的系统,这在本质上就行不通的!一个Service发现服务应该从一开始就被设计成高可用的才行!   如果抛开CAP原理不管,正确的设置与维护ZooKeeper服务就非常的困难;错误会 经常发生, 导致很多工程被建立只是为了减轻维护ZooKeeper的难度。这些错误不仅存在与客户端而且还存在于ZooKeeper服务器本身。Knewton平台 很多故障就是由于ZooKeeper使用不当而导致的。那些看似简单的操作,如:正确的重建观察者(reestablishing watcher)、客户端Session与异常的处理与在ZK窗口中管理内存都是非常容易导致ZooKeeper出错的。同时,我们确实也遇到过 ZooKeeper的一些经典bug: ZooKeeper-1159 与 ZooKeeper-1576; 我们甚至在生产环境中遇到过ZooKeeper选举Leader节点失败的情况。这些问题之所以会出现,在于ZooKeeper需要管理与保障所管辖服务 群的Session与网络连接资源(注:这些资源的管理在分布式系统环境下是极其困难的);但是它不负责管理服务的发现,所以使用ZooKeeper当 Service发现服务得不偿失。   做出正确的选择:Eureka的成功   我们把Service发现服务从ZooKeeper切换到了Eureka平台,它是一个开 源的服务发现解决方案,由Netflix公司开发。(注:Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作 服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。)Eureka一开 始就被设计成高可用与可伸缩的Service发现服务,这两个特点也是Netflix公司开发所有平台的两个特色。( 他们都在讨论Eureka)。自从切换工作开始到现在,我们实现了在生产环境中所有依赖于Eureka的产品没有下线维护的记录。我们也被告知过,在云平 台做服务迁移注定要遇到失败;但是我们从这个例子中得到的经验是,一个优秀的Service发现服务在其中发挥了至关重要的作用!   首先,在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切 换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务 注册信息而已。所以,再也不用担心有“掉队”的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广 的网络分割故障,并实现“0”宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新 的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。   但是,Eureka做到的不止这些。正常配置下,Eureka内置了心跳服务,用于淘汰一些“濒死”的服务器;如果在Eureka中注册的服 务, 它的“心跳”变得迟缓时,Eureka会将其整个剔除出管理范围(这点有点像ZooKeeper的做法)。这是个很好的功能,但是当网络分割故障发生时, 这也是非常危险的;因为,那些因为网络问题(注:心跳慢被剔除了)而被剔除出去的服务器本身是很”健康“的,只是因为网络分割故障把Eureka集群分割 成了独立的子网而不能互访而已。   幸运的是,Netflix考虑到了这个缺陷。如果Eureka服务节点在短时间里丢失了大量的心跳连接(注:可能发生了网络故障),那么这个 Eureka节点会进入”自我保护模式“,同时保留那些“心跳死亡“的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对 于”死亡“的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出”自我保护模式“。所以Eureka的哲学是,同时保 留”好数据“与”坏数据“总比丢掉任何”好数据“要更好,所以这种模式在实践中非常有效。   最后,Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接 口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过 Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解 决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。   Eureka的构架保证了它能够成为Service发现服务。它相对与ZooKeeper来说剔除了Leader节点的选取或者事务日志机制, 这 样做有利于减少使用者维护的难度也保证了Eureka的在运行时的健壮性。而且Eureka就是为发现服务所设计的,它有独立的客户端程序库,同时提供心 跳服务、服务健康监测、自动发布服务与自动刷新缓存的功能。但是,如果使用ZooKeeper你必须自己来实现这些功能。Eureka的所有库都是开源 的,所有人都能看到与使用这些源代码,这比那些只有一两个人能看或者维护的客户端库要好。   维护Eureka服务器也非常的简单,比如,切换一个节点只需要在现有EIP下移除一个现有的节点然后添加一个新的就行。Eureka提供了一 个 web-based的图形化的运维界面,在这个界面中可以查看Eureka所管理的注册服务的运行状态信息:是否健康,运行日志等。Eureka甚至提供 了Restful-API接口,方便第三方程序集成Eureka的功能。
2023-08-10 09:47:071

常见分布式集群选举机制总结

1,Zookeeper -- paxos 2,kafka -- zookeeper上创建节点 3,redis -- 哨兵模式 4,Eureka -- 相互复制 我们探讨这几个集群的选举机制,其实就是探讨它们的高可用性。如果集群中的某些节点挂了,如何保证可用性?这个问题是分布式系统面临的三大问题之一。 Zookeeper的leader选举机制,是这四种集群中最复杂的选举机制,同时也是这四种集群中最接近paxos算法的实现。相比于Zookeeper的选举机制,kafka集群、redis集群、Eureka集群的选举机制简单了许多。 Zookeeper的leader选举是Zookeeper实现数据一致性的关键,同时也存在一些问题。认清Zookeeper的优点与缺陷,对于我们使用好它还是很有必要的。 Zookeeper的选举机制有2个触发条件:集群启动阶段和集群运行阶段leader挂机。这2种场景下选举的流程基本一致,我们以集群运行阶段leader挂机为例来进行说明。leader挂机以后,重新选举leader,选举的流程如下: 1,Zookeeper集群中的follower检测到leader挂机,然后把自己的状态置为LOOKING,开始进行leader选举。 2,每台服务器选举自己为leader,然后把自己的选票通过广播通知其他服务器。 3,每台服务器接收来自其他服务器的选票,并进行合法性校验,主要有两点校验,选举轮次校验和服务器的状态的校验。 4,处理选票。每台服务器都会将自己的选票与其他服务器的选票进行PK,PK的规则如下: 第一个规则:首先进行ZXID的PK,大者获胜。 第二条规则:如果ZXID相等,则进行myid的PK,大者获胜。 经过PK以后,如果当前服务器PK失败,则会把自己的选票重新投给胜者,然后把更新后的选票通过广播通知其他服务器。 5,统计选票。根据超过半数的原则,每台服务器都会统计leader的选票,如果超过半数,则结束选举。 6,更新服务器状态。follower把自己的状态更新为FOLLOWING,leader把自己的状态更新为LEADING。 OK,这就是Zookeeper的leader选举机制。经过若干轮选举以后,Zookeeper集群继续对外提供服务。由于选票PK首先比较的是ZXID,所以Zookeeper能够保证leader的数据是最新的。 kafka集群是如何保证高可用性的呢? kafka通过Zookeeper管理集群配置、选举leader、consumer group发生变化时进行rebalance。 那么我要问了,kafka是如何选举leader的呢? 概括来说,Kafka选举leader的过程是这样的:kafka的所有broker,在Zookeeper的/controller路径下创建临时节点,成功创建的那个broker就会成为leader,其他的broker就会成为follower。 当leader挂机时,临时节点会被删除,这是其他节点通过Zookeeper的watch机制,会监听到leader的变化,然后所有的follower会再次进行leader选举。 kafka的选举其实就是创建临时节点,这和Zookeeper分布式锁的实现原理基本相同。 redis主从切换和redis集群的理解。 要注意,主从切换默认只有一个master,但是对于多个master的集群,没有主从切换的说法。 redis没有类似Zookeeper的选举机制。redis的master挂掉以后,redis集群是通过主从切换来保证高可用性的。 redis主从切换有2种方式:手动切换和自动切换。 这里我们讨论自动切换,redis主从自动切换需要哨兵模式的支持,哨兵模式简单来说就是:监控master和slave,在master出现故障的时候,自动将slave切换成master,master恢复以后,作为新master的slave对外提供服务。 准确的来说,Eureka集群中的各节点之间不存在主从关系。Eureka集群中的节点的关系是对等的,其他3种集群则都存在主从关系,这是Eureka集群的一个特色。 Eureka集群的各个server之间通过相互注册的方式来实现集群的高可用性。数据同步的方式是增量备份,这样可以保证每个server都是最新最全的数据。从而保证集群的高可用性。这样即使某个server挂了,集群还可以对外提供服务。 Eureka有一个配置项:eureka.client.fetch-register,是否从Eureka server获取注册信息。如果我们是Eureka集群,那么该项配置为true。这样Eureka server直接就可以相互注册。 OK,这篇文章只是对4种集群的选举机制进行了一个概括性的介绍,具体细节还是很复杂的。之前有文章重点分析过Zookeeper的leader选举,后续还会另起文章分析其他几种集群的选举机制,到时候我们再进行更深入的讲解。
2023-08-10 09:47:141

SpringCloud + Zookeeper + Feign整合及Feign原理

Spring Cloud 与 Zookeeper的整合只需要添加相关的starter依赖和增加相关注解即可完成。 pom.xml 如下: bootstrap.yml 如下: 最后开启服务的注册与发现 service 和controller实现 笔者加入了swagger,如果需要只需加入如下依赖和配置: 至此,spring cloud与zookeeper的整合就完成了,调用结果如下: 为了测试与Feign的整合,再构建一个消费者:与上述构建的过程类似。 pom.xml 增加spring-cloud-starter-openfeign依赖 bootstrap.yaml: 开启服务注册与发现,@EnableFeignClients注解注册FeignClient @FeignClient注册声明定义FeignClient,笔者以两种方式定义了两个FeignClient: 1.通过请求路径定义FeignClient 2.通过生产者(即上述构建的helloService)暴露出来的接口定义FeignClient controller 测试: 测试结果如下: 知道了如何将SpringCloud, Zookeeper 和Feign进行整合,我们知道了怎么使用,更重要的是要知道里面的原理,做到知其然更要知其所以然。 通过上述对整合过程的描述中可以发现,@EnableFeignClients和@FeignClient两个注解是将Feign整合进Spring Cloud的重要组成部分,因此,从这两个注解入手来了解Feign。 @EnableFeignClients注解通过@Import引入了FeignClientsRegistrar进行feign客户端的注册, 同时FeignClientsRegistrar通过实现ImportBeanDefinitionRegistrar来将bean注册spring容器中: 至此,我们知道了通过@EnableFeignClients和@FeignClient两个注解以及其相关属性,在服务启动时,将每个feign client 以及其对应的配置和每个客户端通用的配置以bean的方式注册完到spring容器中。 当使用@Autowired注解自动注入FeignClient时,Spring容器会使用注册FeignClient用到的FeignClientFactoryBean为其生成FeignClient实例。 默认使用的targeter是HystrixTargeter,根据builder的类型设置不同的属性,并生产Feign client 从上面的分析可以得出,当服务启动时,通过@EnableFeignClients注解,启动对标注了@FeignClient注解的类进行扫描和注册,通过FeignClientFactoryBean将FeignClient注册到Spring容器中。当使用@Autowired注解进行自动注入时,注册到Spring容器中FeignClient会以动态代理的形式注入,这些动态代理中包含了接口方法的methodHandler用以处理调用转发。
2023-08-10 09:47:221

如何使用zookeeper实现程序重启

记得在大约在2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有...
2023-08-10 09:47:292

zookeeper怎么实现分布式锁

很多使用Zookeeper的情景是需要我们嵌入Zookeeper作为自己的分布式应用系统的一部分来提供分布式服务,此时我们需要通过程序的方式来启动Zookeeper。此时可以通过Zookeeper API的ZooKeeperServerMain类来启动Zookeeper服务。
2023-08-10 09:47:381

《ZooKeeper:分布式过程协同技术详解分布式过程协同技术详解》pdf下载在线阅读,求百度网盘云资源

《ZooKeeper:分布式过程协同技术详解》(Flavio Junqueira)电子书网盘下载免费在线阅读资源链接:链接:https://pan.baidu.com/s/1HrACV0QnQUAmm9oK2Bw13w 提取码:y237书名:ZooKeeper:分布式过程协同技术详解作者:Flavio Junqueira译者:谢超豆瓣评分:7.0出版社:机械工业出版社出版年份:2016-1-1页数:208内容简介:本书分三部分,共10章。第一部分(第1~2章)阐述ApacheZooKeeper这类系统的设计目的和动机,并介绍分布式系统的一些必要背景知识。第1章介绍ZooKeeper可以做什么,以及其设计如何支撑这些任务。第2章介绍基本概念和基本组成模块,并通过命令行工具的具体操作介绍了ZooKeeper可以做什么。第二部分(第3~8章)阐述开发人员所需要掌握的ZooKeeper库调用方法和编程技巧。第3章介绍Java语言的API.第4章解释如何跟踪和处理ZooKeeper中的状态变更情况。第5章介绍如何在系统或网络故障时恢复应用。第6章介绍需要注意来避免故障的一些繁杂却很重要的场景。第7章介绍C语言版的API接口,也可以作为非Java语言实现的ZooKeeperAPI的基础,对非Java语言的开发人员非常有帮助。第8章介绍一款更高层级的封装的ZooKeeper接口。第三部分(第9~10章)主要介绍ZooKeeper内部原理及如何运行ZooKeeper.第9章介绍ZooKeeper的作者们在设计时所采用的方案。第10章介绍如何对ZooKeeper进行配置。作者简介:作者介绍Flavio Junqueira 是微软研究院在英国剑桥大学的研究人员之一。他拥有美国加州大学圣地亚哥分校计算机科学博士学位。他的研究范围涉及分布式系统的各个方面,包括分布式算法、并发性和可扩展性。他是Apache项目如Apache ZooKeeper(PMC主席和提交者)和Apache BookKeeper(提交者)的积极贡献者。他一有空就喜欢睡觉。Benjamin Reed 是一位负责Facebook中所有细节工作的软件工程师。他以前的职位包括雅虎研究院首席研究科学家(负责所有大的方向)和IBM Almaden Research的研究人员(负责所有事情,无论大小)。他拥有加州大学圣克鲁斯分校计算机科学博士学位。他从事的工作涉及分布式计算、大数据处理、分布式存储、系统管理和嵌入式框架等领域。他参加了各种开源项目,如Hadoop和Linux操作系统等。他帮助启动了由Apache软件基金会主办的项目如Pig、ZooKeeper和BookKeeper。
2023-08-10 09:47:511

ZK为什么建议部署成奇数台

《从Paxos到Zookeeper:分布式一致性原理与实践》解释: 其实关于ZooKeeper集群服务器数,ZooKeeper官方确实给出了关于奇数的建议,但绝大部分ZooKeeper用户对这个建议认识有偏差。在本书前面提到的“过半存活即可用”特性中,我们已经了解了,一个ZooKeeper集群如果要对外提供可用的服务,那么集群中 必须要有过半的机器正常工作并且彼此之间能够正常通信 。基于这个特性,如果想搭建一个能够允许 F 台机器down掉的集群,那么就要部署一个由 2×F+1 台服务器构成的 ZooKeeper 集群。因此,一个由3台机器构成的ZooKeeper集群,能够在挂掉1台机器后依然正常工作,而对于一个由5台服务器构成的ZooKeeper集群,能够对2台机器挂掉的情况进行容灾。注意,如果是一个由6台服务器构成的ZooKeeper集群,同样只能够挂掉2台机器,因为如果挂掉3台,剩下的机器就无法实现过半了。 因此,从上面的讲解中,我们其实可以看出, 对于一个由6台机器构成的ZooKeeper集群来说,和一个由5台机器构成的ZooKeeper集群相比,其在容灾能力上并没有任何显著的优势。 基于这个原因,ZooKeeper集群通常设计部署成奇数台服务器即可。
2023-08-10 09:48:181

【Zookeeper系列】ZK命令基本使用

在了解 ZK 底层原理之前,咱们先简单了解常用的 ZK 命令,熟悉常用 ZK 命令有利于排查相关问题或了解基于 ZK 自研系统等场景。比如在开发的时候,发现有些Dubbo服务无法被调用,这有可能是服务没有注册到ZK或者断开连接;也有可能公司有自研的系统使用 ZK 作为配置中心,熟悉 ZK 命令就能知道是如何做到服务发现注册和配置动态更新。 话不多说,咱们先来了解常见的 ZK 命令吧! 实际上,ZK并没有help命令,你可以随意敲一两个字符也会这样显示,只不过基于使用Linux的习惯,姑且认为输入help能打印出ZK支持的命令吧。 ls 命令可以查看指定目录下的节点,使用可选的参数,能够更加详细的看到节点的相关信息 stat / 等价于 ls -s / 和 ls 命令相似的,加上-w参数添加监听 在ZK 3.5版本之后,新增了容器和TTL节点,分别是使用 -c 和 -t 创建。所以读者们要注意你当前使用的版本,如果版本低于3.5的,是没有容器和TTL节点。 特别说明一下容器节点和TTL节点的使用: 另外关于 TTL节点 的使用,需要特别注意的是,如果使用默认的配置文件启动zk,想创建有存活时间的节点,比如执行 create -t 10 /test 是会报 KeeperErrorCode = Unimplemented for XXX 这样的错误。解决办法是需要在ZK启动前,先在配置文件加上 extendedTypesEnabled=true 然后重启ZK(集群部署的话,所有ZK都需要修改配置文件再重启) 配置后重启,执行 create -t 10 /test 这样的命令就不会报错啦 例子:get -s /demo 例子:先查询节点版本号,模拟并发下修改同一节点 get -s /demo 可知当前 dataVersion = 1 客户端1:set -v 1 /demo demo-data1 客户端2:set -v 1 /demo demo-data2 客户端1比客户端2先执行,客户端2再执行的话,这时显示报错 -v version:和 set 命令相似,-v 参数用于判断当前操作的版本 例子:先创建一个delNode节点,然后删除 在前面使用create命令的时候,有一个acl参数是设置节点权限的,那么我们应该怎么设置? 举个例子: create /testAcl demo world:anyone:crwda 这行命令的意思是,创建 testAcl 这个节点,节点值为demo,其权限策略是所有人都可以执行 crwda 操作。那么接下来,咱们先看下 ACL 是什么东东? ACL 全称是 Access Control List ,也就是访问控制列表,ACL可以设置节点的操作权限。那么控制权限的粒度是怎样呢? 对于节点 ACL 权限控制,是通过使用: scheme:id:perm 来标识(也就是例子中的格式 -> world:anyone:crwda),其含义是: Scheme 有哪些授权策略? ID 授权对象有哪些? Permission 权限有哪些? 根据上面的参数可知,我们可以通过给所有人、特定的账号密码、特定的 ip 设置节点权限,这样能够更加方面地管理节点的访问。 值得注意的是,节点可以设置多种授权策略,但对于上下节点而言,权限的设置只对当前节点有效。换言之,权限不存在继承关系,即使节点被设置权限,但不会影响上下节点原来的权限! 上面执行了 create /testAcl demo world:anyone:crwda 命令给节点设置权限,那怎么看节点的权限咧? 很简单,执行 getAcl 节点路径 就可以查看对应节点的权限,比如 getAcl /testAcl,执行结果如下 除了在执行create命令创建节点的时候设置权限,还可以通过 setAcl 指定节点设置权限,比如我想指定/testAcl这个节点只可以通过特定 IP操作,并且限制执行权限为crdw,那么可以执行 setAcl /testAcl ip:127.0.0.1:crwd ,再次执行 getAcl /testAcl 结果如下: ZK 的命令还有部分没有演示,这并不阻碍咱们学习ZK的原理,先掌握常见的命令,如果日后有其他场景的话,再根据特定的命令学习就可以啦。 无意中发现有 Zookeeper的客户端,感兴趣的读者可以玩一下~ 友情提醒,可能在节点数量很多的时候,打开很慢,甚至卡死,所以这个可视化工具可以在自己本地玩玩,不建议应用在生产上哈。这也侧面的说明,学会 ZK 命令的重要性(认真脸.jpg) 解压缩后,进入ZooInspector的build目录,执行 java -jar zookeeper-dev-ZooInspector.jar 就可以启动工具。 连接上 ZK 后,就可以看到节点的信息和节点的ACL,具体玩法,可以再自己摸索哈~ 好了,以上是 ZK 常见命令的基本使用和可视化工具的基本使用。 参考资料: 《从Paxos到Zookeeper分布式一致性原理与实践》 如果觉得文章不错的话,麻烦点个赞哈,你的鼓励就是我的动力!对于文章有哪里不清楚或者有误的地方,欢迎在评论区留言~
2023-08-10 09:48:371

Zookeeper客户端Curator使用详解

[TOC] 维护多个博客比较麻烦,和博客园放弃维护,后续在个人博客持续更新: Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。Patrixck Hunt(Zookeeper)以一句“Guava is to Java that Curator to Zookeeper”给Curator予高度评价。 引子和趣闻: Zookeeper名字的由来是比较有趣的,下面的片段摘抄自《从PAXOS到ZOOKEEPER分布式一致性原理与实践》一书: Zookeeper最早起源于雅虎的研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型的系统需要依赖一个类似的系统进行分布式协调,但是这些系统往往存在分布式单点问题。所以雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架。在立项初期,考虑到很多项目都是用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。时任研究院的首席科学家Raghu Ramakrishnan开玩笑说:再这样下去,我们这儿就变成动物园了。此话一出,大家纷纷表示就叫动物园管理员吧——因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了,而Zookeeper正好用来进行分布式环境的协调——于是,Zookeeper的名字由此诞生了。 Curator无疑是Zookeeper客户端中的瑞士军刀,它译作"馆长"或者""管理者"",不知道是不是开发小组有意而为之,笔者猜测有可能这样命名的原因是说明Curator就是Zookeeper的馆长(脑洞有点大:Curator就是动物园的园长)。 Curator包含了几个包: curator-framework: 对zookeeper的底层api的一些封装 curator-client: 提供一些客户端的操作,例如重试策略等 curator-recipes: 封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等 Maven依赖(使用curator的版本:2.12.0,对应Zookeeper的版本为:3.4.x, 如果跨版本会有兼容性问题,很有可能导致节点操作失败 ): 一个例子如下: newClient静态工厂方法包含四个主要参数: 核心参数变为流式设置,一个列子如下: 为了实现不同的Zookeeper业务之间的隔离,需要为每个业务分配一个独立的命名空间( NameSpace ),即指定一个Zookeeper的根路径(官方术语: 为Zookeeper添加“Chroot”特性 )。例如(下面的例子)当客户端指定了独立命名空间为“/base”,那么该客户端对Zookeeper上的数据节点的操作都是基于该目录进行的。通过设置Chroot可以将客户端应用与Zookeeper服务端的一课子树相对应,在多个应用共用一个Zookeeper集群的场景下,这对于实现不同应用之间的相互隔离十分有意义。 当创建会话成功,得到client的实例然后可以直接调用其start( )方法: Zookeeper的节点创建模式: **创建一个节点,初始内容为空 ** 注意:如果没有设置节点属性,节点创建模式默认为持久化节点,内容默认为空 创建一个节点,附带初始化内容 创建一个节点,指定创建模式(临时节点),内容为空 创建一个节点,指定创建模式(临时节点),附带初始化内容 创建一个节点,指定创建模式(临时节点),附带初始化内容,并且自动递归创建父节点 这个creatingParentContainersIfNeeded()接口非常有用,因为一般情况开发人员在创建一个子节点必须判断它的父节点是否存在,如果不存在直接创建会抛出NoNodeException,使用creatingParentContainersIfNeeded()之后Curator能够自动递归创建所有所需的父节点。 删除一个节点 注意,此方法只能删除 叶子节点 ,否则会抛出异常。 删除一个节点,并且递归删除其所有的子节点 删除一个节点,强制指定版本进行删除 删除一个节点,强制保证删除 guaranteed()接口是一个保障措施,只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到删除节点成功。 注意: 上面的多个流式接口是可以自由组合的,例如: 读取一个节点的数据内容 注意,此方法返的返回值是byte[ ]; 读取一个节点的数据内容,同时获取到该节点的stat 更新一个节点的数据内容 注意:该接口会返回一个Stat实例 更新一个节点的数据内容,强制指定版本进行更新 注意:该方法返回一个Stat实例,用于检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath( )指定要操作的ZNode 注意:该方法的返回值为List<String>,获得ZNode的子节点Path列表。 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的父ZNode CuratorFramework的实例包含inTransaction( )接口方法,调用此方法开启一个ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交。一个例子如下: 上面提到的创建、删除、更新、读取等方法都是同步的,Curator提供异步接口,引入了 BackgroundCallback 接口用于处理异步接口调用之后服务端返回的结果信息。 BackgroundCallback 接口中一个重要的回调值为CuratorEvent,里面包含事件类型、响应吗和节点的详细信息。 CuratorEventType 响应码(#getResultCode()) 一个异步创建节点的例子如下: 注意:如果#inBackground()方法不指定executor,那么会默认使用Curator的EventThread去进行异步处理。 提醒:首先你必须添加curator-recipes依赖,下文仅仅对recipes一些特性的使用进行解释和举例,不打算进行源码级别的探讨 重要提醒:强烈推荐使用ConnectionStateListener监控连接的状态,当连接状态为LOST,curator-recipes下的所有Api将会失效或者过期,尽管后面所有的例子都没有使用到ConnectionStateListener。 Zookeeper原生支持通过注册Watcher来进行事件监听,但是开发者需要反复注册(Watcher只能单次注册单次使用)。Cache是Curator中对事件监听的包装,可以看作是对事件监听的本地缓存视图,能够自动为开发者处理反复注册监听。Curator提供了三种Watcher(Cache)来监听结点的变化。 Path Cache用来监控一个ZNode的子节点. 当一个子节点增加, 更新,删除时, Path Cache会改变它的状态, 会包含最新的子节点, 子节点的数据和状态,而状态的更变将通过PathChildrenCacheListener通知。 实际使用时会涉及到四个类: 通过下面的构造函数创建Path Cache: 想使用cache,必须调用它的 start 方法,使用完后调用 close 方法。 可以设置StartMode来实现启动的模式 ......to be continue
2023-08-10 09:48:451

大数据运营的核心课程都有哪些?

主要学习C语言程序设计、Linux服务器的配置和使用以及大数据商业应用等等。
2023-08-10 09:48:532

kafka 架构及其原理

kafka是一个 分布式 的、支持 分区的(partition )、多副本的 (replica ),基于 zookeeper 协调的 分布式消息系统。 从上面的描述中我们可以知道kafka的核心知识点:partition、replica 一个topic可以认为一个一类消息,每个topic将被分成多个partition。 在上图中我们的生产者会决定发送到哪个 Partition: 如果没有 Key 值则进行轮询发送。 如果有 Key 值,对 Key 值进行 Hash,然后对分区数量取余,保证了同一个 Key 值的会被路由到同一个分区。(所有系统的partition都是同一个路数) 在上图我们也可以看到,offset是跟partition走的,每个partition都有自己的offset。 总所周知,topic在物理层面以partition为分组,一个topic可以分成若干个partition,那么topic以及partition又是怎么存储的呢? 其实partition还可以细分为logSegment,一个partition物理上由多个logSegment组成,那么这些segment又是什么呢? LogSegment 文件由两部分组成,分别为“.index”文件和“.log”文件,分别表示为 Segment 索引文件和数据文件。 这两个文件的命令规则为:partition全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值,数值大小为64位,20位数字字符长度,没有数字用0填充,如下: 如上图,“.index”索引文件存储大量的元数据,“.log”数据文件存储大量的消息,索引文件中的元数据指向对应数据文件中message的物理偏移地址。其中以“.index”索引文件中的元数据[3, 348]为例,在“.log”数据文件表示第3个消息,即在全局partition中表示170410+3=170413个消息,该消息的物理偏移地址为348。 那么如何从partition中通过offset查找message呢? 以上图为例,读取offset=170418的消息,首先查找segment文件,其中00000000000000000000.index为最开始的文件,第二个文件为00000000000000170410.index(起始偏移为170410+1=170411),而第三个文件为00000000000000239430.index(起始偏移为239430+1=239431),所以这个offset=170418就落到了第二个文件之中。其他后续文件可以依次类推,以其实偏移量命名并排列这些文件,然后根据二分查找法就可以快速定位到具体文件位置。其次根据00000000000000170410.index文件中的[8,1325]定位到00000000000000170410.log文件中的1325的位置进行读取。 要是读取offset=170418的消息,从00000000000000170410.log文件中的1325的位置进行读取,那么怎么知道何时读完本条消息,否则就读到下一条消息的内容了? 这个就需要联系到消息的物理结构了,消息都具有固定的物理结构,包括:offset(8 Bytes)、消息体的大小(4 Bytes)、crc32(4 Bytes)、magic(1 Byte)、attributes(1 Byte)、key length(4 Bytes)、key(K Bytes)、payload(N Bytes)等等字段,可以确定一条消息的大小,即读取到哪里截止。 Kafka 的副本机制是多个服务端节点对其他节点的主题分区的日志进行复制。当集群中的某个节点出现故障,访问故障节点的请求会被转移到其他正常节点(这一过程通常叫 Reblance)。 Kafka 每个主题的每个分区都有一个主副本以及 0 个或者多个副本,副本保持和主副本的数据同步,当主副本出故障时就会被替代。 当producer向leader发送数据时,可以通过request.required.acks参数来设置数据可靠性的级别: 在kafka系统中,会涉及到多处选举机制,主要有这三方面:
2023-08-10 09:49:011

海康威视1——p6升级2——p7怎么面试?

电话面试:第一次面试关注的问题,1)java基础:jvm 内存回收,垃圾回收基本原理,Java并发包的线程池,Java8的新特性。nio 堆排序。conrenthashmap , concurrenthashmap 的size实现, spring的事务2)数据库基础:事务隔离级别,数据库连接池,锁性等。。MQ如何保证顺序性。spring事务传播性。 数据库跨库一致性数据库死锁的问题,一个删除昨天一个删除今天的,怎么死锁的。还有个延迟队列和队列排序的问题。3)如果项目中有用到框架:Redis,RPC、Kafaka、MQ 、Spring 等。问到的问题比如springmvc工作机制、Spring MVC的aop实现原理,Spring MVC 的请求过程,一个Controller是单例还是多实例。再比如Redis,在项目里面承担了核心缓存左右,选择的持久化方式是什么。redis恢复。Redis的内存废弃策略。redis高并发的key怎么处理。非常注重源代码,不管是jdk的,还是框架的还有比如spring,redis源代码的实现架构方面,分布式框架和中间件问题:dubbo原理zookeeper原理netty原理高并发综合策略 数据一致性处理策略4)线上问题处理经验5)表达对技术的钻研热情第二次电话面试是交叉面试,同上。第三次是现场技术终面+HR面P6的考察侧重点1、80后。2给人的感觉是上进心很强,努力学习精进技术的,不愿意混日子。过往的工作经验是owner一个独立的业务系统,负责系统的设计开发工作,可以不是架构。明确知道系统架构的情况,理解上下游关系。理解该系统的业务定位,该系统当前存在的问题和后续的规划发展有自己的见解。3 Java基础知识和分布式经验应该很熟悉,框架层面源码如果能研读可以加分。但是如果只是会用而不了解原理就要减分。4会重点考察分布式/服务化系统(不是大流量高并发)的设计原理,思路,关注点。要会理解一些分布式session、全局流水ID号、服务多次重试幂等、同步转异步、服务监控、最终一致性等原理和应用。P7的考察侧重点1 敢说敢做,有气场勇于承担事情2不是一个单纯的技术实现人员,而是一个有规划,有思考的人。主导一个复杂的系统(多个业务系统完整链路);或者负责一块五脏俱全的业务。3 对业务系统的理解会更多从商业价值角度去描述,熟悉这块产品链的模式和玩法,或者工业化成熟度较高的专业实现方案。对基础中间件系统可以描述常见竞品、实现原理算法、核心难点。4如果是电商交易类背景的,分布式系统设计原则要比P6的同学理解更深入:分库分表分布式事务、性能稳定性的实践。如果能描述分库分表中间件实现原理(SQLParse、语法树)、单元化/多机房灾备可以加分-就可以往P7+、P8去谈。5 P7的同学开放式的问题会比较多,会更多在答题思路和内容中去挖掘亮点。
2023-08-10 09:49:161

阿里P8推荐:《Netty、Redis、Zookeeper高并发实战》看完真不错

移动时代、5G时代、物联网时代的大幕已经开启,它们对于 高性能、高并发 的开发知识和技术的要求,抬升了 Java工程师的学习台阶和面试门槛。 大公司的面试题从某个侧面映射出生产场景中对专项技术的要求。高并发的面试题以前基本是BAT等大公司的专利,现在几乎蔓延至与Java项目相关的整个行业。例如,与 Java NIO、Reactor模式、高性能通信、分布式锁、分布式ID、分布式缓存、高并发架构等 技术相关的面试题,从以前的加分题变成了现在的基础题,这也映射出开发Java项目所必需的技术栈: 分布式Java框架、Redis缓存、分布式搜索ElasticSearch、分布式协调ZooKeeper、消息队列Kafka、高性能通信框架Netty。 《Netty、Redis、Zookeeper高并发实战》为了让大家扎稳高性能基础,浅显易懂地剖析高并发IO的底层原理,细致细腻地解析Reactor高性能模式,图文并茂地介绍Java异步回调模式。掌握这些基础原理,能够帮助大家解决Java后台开发的一些实际问题。 本书共12章,主要介绍高性能通信框架Netty,并详尽介绍Netty的EventLoop、Handler、Pipeline、ByteBuf、Decoder、Encoder等重要组件,然后介绍单体IM的实战设计和模块实现。本书对ZooKeeper、 Curator API、Redis、Jedis API的使用也进行详尽的介绍,让大家具备高并发、可扩展系统的设计和开发能力。 由于内容较多,本次将展示部分截图,如果看得不过瘾想更加深入地了解本笔记彻底掌握,只需转发后私信回复【666】即可来获取免费领取方式了!
2023-08-10 09:49:241

etcd是什么东西?它和ZooKeeper有什么区别

etcdetcd作为最近很火的一个高可用性?键值对服务发现系统被Kubernetes等系统广泛使用他相比与zookeeper来说更加简单,在面对较小集群时可能会效率更高些?,而且他的编写语言Go本身就是一种多线程编程语言,确实有很大吸引人的地方(虽然我不懂Go语言,但是在学习docker时也是一睹其风采了)在Raft中,任何时候一个服务器可以扮演下面角色之一:Leader: 处理所有客户端交互,日志复制等,一般一次只有一个Leader.Follower: 类似选民,完全被动Candidate候选人: 类似Proposer律师,可以被选为一个新的领导人。leader选举阶段消息同步阶段Leader要求Followe遵从他的指令,都将这个新的日志内容追加到他们各自日志中:大多数follower服务器将日志写入磁盘文件后,确认追加成功,发出Commited Ok:在下一个心跳heartbeat中,Leader会通知所有Follwer更新commited 项目。对于每个新的日志记录,重复上述过程。zookeeper:zookeeper是基于paxos的简化版zab,我觉得确实很难理解?,以前看了好多遍《从paxos到zookeper》才感觉似懂非懂了,然而过了几个月发现又一脸蒙蔽了,在这里在整理一下(仅表示我自己的理解)ZAB协议中存在着三种状态,每个节点都属于以下三种中的一种:Looking :系统刚启动时或者Leader崩溃后正处于选举状态Following :Follower节点所处的状态,Follower与Leader处于数据同步阶段;Leading :Leader所处状态,当前集群中有一个Leader为主进程;在开始时,所有的节点都是looking状态并且每个节点都希望自己能成为leader节点,所有每个节点都会向集群中发送一个提案内容是选取自己作为leader节点,提案编号是ZXID(ZAB协议中使用ZXID作为事务编号,ZXID为64位数字,低32位为一个递增的计数器,每一个客户端的一个事务请求时Leader产生新的事务后该计数器都会加1,高32位为Leader周期epoch编号,当新选举出一个Leader节点时Leader会取出本地日志中最大事务Proposal的ZXID解析出对应的epoch把该值加1作为新的epoch,将低32位从0开始生成新的ZXID;ZAB使用epoch来区分不同的Leader周期),如果得到的提案的zxid比自己的大则说明发出这个题案的节点数据更新,则进行同意的投票,否则继续投自己,先得到多数的同意的节点当选为leader现在leader就可以进行管理了,zookeeper也是两段提交的实现,客户端提交事务请求时Leader节点为每一个请求生成一个事务Proposal,将其发送给集群中所有的Follower节点,收到过半Follower的反馈后开始对事务进行提交,ZAB协议使用了原子广播协议
2023-08-10 09:49:312

NameNode HA实现原理

前言 :在Hadoop 1.x版本,HDFS集群的NameNode一直存在单点故障问题:集群只存在一个NameNode节点,它维护了HDFS所有的元数据信息,当该节点所在服务器宕机或者服务不可用,整个HDFS集群都将处于不可用状态,极大限制了HDFS在生产环境的应用场景。直到Hadoop 2.0版本才提出了高可用 (High Availability, HA) 解决方案,并且经过多个版本的迭代更新,已经广泛应用于生产环境。 解决方案 :在同一个HDFS集群,运行两个互为主备的NameNode节点。一台为主Namenode节点,处于Active状态,一台为备NameNode节点,处于Standby状态。其中只有Active NameNode对外提供读写服务,Standby NameNode会根据Active NameNode的状态变化,在必要时切换成Active状态。 【NameNode HA架构图】 HealthMonitor 定时调用NameNode的HAServiceProtocol RPC接口(monitorHealth和getServiceStatus),监控NameNode的健康状态并向ZKFC反馈; ActiveStandbyElector 接收ZKFC的选举请求,通过Zookeeper自动完成主备选举,选举完成后回调ZKFC的主备切换方法对NameNode进行Active和Standby状态的切换; JouranlNode集群 共享存储系统,负责存储HDFS的元数据,Active NameNode(写入)和Standby NameNode(读取)通过共享存储系统实现元数据同步,在主备切换过程中,新的Active NameNode必须确保元数据同步完成才能对外提供服务; ZKFailoverController在启动时同时会初始化HealthMonitor和ActiveStandbyElector服务,同时也会向HealthMonitor和ActiveStandbyElector注册相应的回调方法: HealthMonitor检测NameNode的两类状态,HealthMonitor.State和HealthMonitor.HAServiceStatus。在程序上启动一个线程循环调用NameNode的HAServiceProtocol RPC接口的方法来检测NameNode 的状态,并将状态的变化通过回调的方式来通知ZKFailoverController。 当HealthMonitor检测到NameNode的健康状态或角色状态发生变化时,ZKFC会根据状态的变化决定是否需要进行主备选举。 HealthMonitor.State状态变化导致的不同后续措施: HAServiceStatus在状态检测之中仅起辅助的作用,当HAServiceStatus发生变化时,ZKFC会判断NameNode返回的HAServiceStatus与ZKFC所期望的是否相同,如果不相同,ZKFC会调用ActiveStandbyElector的quitElection方法删除当前已经在ZK上建立的临时节点退出主备选举。 ZKFC通过ActiveStandbyElector的joinElection方法发起NameNode的主备选举,这个过程通过Zookeeper的写一致性和临时节点机制实现: a. 当发起一次主备选举时,Zookeeper会尝试创建临时节点 /hadoop-ha/${dfs.nameservices}/ActiveStandbyElectorLock ,Zookeeper的写一致性保证最终只会有一个ActiveStandbyElector创建成功,创建成功的 ActiveStandbyElector对应的NameNode就会成为主NameNode,ActiveStandbyElector回调ZKFC的方法将对应的NameNode切换为Active状态。而创建失败的ActiveStandbyElector对应的NameNode成为备NameNode,ActiveStandbyElector回调ZKFC的方法将对应的NameNode切换为Standby状态; b. 不管是否选举成功,所有ActiveStandbyElector都会向Zookeeper注册一个Watcher来监听这个节点的状态变化事件; c. 如果Active NameNode对应的HealthMonitor检测到NameNode状态异常时,ZKFC会删除在Zookeeper上创建的临时节点ActiveStandbyElectorLock,这样处于Standby NameNode的ActiveStandbyElector注册的Watcher就会收到这个节点的 NodeDeleted事件。收到这个事件后,会马上再次创建ActiveStandbyElectorLock,如果创建成功,则Standby NameNode被选举为Active NameNode。 【防止脑裂】 在分布式系统中脑裂又称为双主现象,由于Zookeeper的“假死”,长时间的垃圾回收或其它原因都可能导致双Active NameNode现象,此时两个NameNode都可以对外提供服务,无法保证数据一致性。对于生产环境,这种情况的出现是毁灭性的,必须通过自带的隔离(Fencing)机制预防这种现象的出现。 ActiveStandbyElector为了实现fencing隔离机制,在成功创建 hadoop-ha/dfs.nameservices/ActiveStandbyElectorLock 临时节点 后,会创建另外一个 /hadoopu2212ha/{dfs.nameservices}/ActiveBreadCrumb 持久节点 ,这个持久节点保存了Active NameNode的地址信息。当Active NameNode在正常的状态下断开Zookeeper Session (注意由于 /hadoop-ha/dfs.nameservices/ActiveStandbyElectorLock 是临时节点,也会随之删除),会一起删除持久节点 /hadoopu2212ha/{dfs.nameservices}/ActiveBreadCrumb 。但是如果ActiveStandbyElector在异常的状态下关闭Zookeeper Session,那么由于 /hadoop-ha/${dfs.nameservices}/ActiveBreadCrumb 是持久节点,会一直保留下来。当另一个NameNode (standy => active) 选主成功之后,会注意到上一个Active NameNode遗留下来的ActiveBreadCrumb节点,从而会回调ZKFailoverController的方法对旧的Active NameNode进行fencing。 ① 首先ZKFC会尝试调用旧Active NameNode的HAServiceProtocol RPC接口的transitionToStandby方法,看能否将状态切换为Standby; ② 如果调用transitionToStandby方法切换状态失败,那么就需要执行Hadoop自带的隔离措施,Hadoop目前主要提供两种隔离措施: sshfence:SSH to the Active NameNode and kill the process; shellfence:run an arbitrary shell command to fence the Active NameNode; 只有在成功地执行完成fencing之后,选主成功的ActiveStandbyElector才会回调ZKFC的becomeActive方法将对应的NameNode切换为Active,开始对外提供服务。 博客主页: https://www.jianshu.com/u/e97bb429f278
2023-08-10 09:49:391

搭建全分布式集群的原理是什么?

全分布式集群是指将系统的计算和存储资源分散到多台服务器上,通过网络互相连接,形成一个高可用、高可靠、高性能的分布式计算环境。搭建全分布式集群可以提高系统的计算能力、数据处理能力和容错能力。实现全分布式集群需要遵循以下原则:1. 水平扩展:将系统的计算和存储资源分散到多个节点上,可以根据业务需求按需增加或减少节点,从而方便地扩展系统的性能和容量。2. 节点均衡:每个节点都应该具有相同的硬件配置和软件环境,以保证节点之间的任务分配均衡,并且方便进行故障转移和负载均衡。3. 数据一致性:在分布式环境下,数据的一致性是非常重要的。为了保证数据的一致性,需要采用合适的同步机制,如数据复制、数据分片等。4. 故障容错:从节点故障恢复和任务重试等方面提供容错功能,使得系统可以在节点故障的情况下继续工作。5. 高性能通信:使用高速网络通信协议,如Infiniband、RDMA等,保证节点间的通信速度和吞吐量。搭建全分布式集群需要使用一些分布式系统的基础组件,如分布式文件系统、分布式数据库、分布式缓存、分布式任务调度等,并且需要根据实际业务需求进行选择和调整。常用的分布式平台包括Hadoop、Spark、HBase、Cassandra等。同时,为了更好地管理和监控集群,还需要使用一些集群管理工具,如Zookeeper、Ambari等。
2023-08-10 09:49:581

我也已经25岁其实就有转行的打算了,想转数据分析大数据行业,我大学本科是和这个专业相关的,

转行这个词汇,一直是职场上此起彼伏的一个热门话题,相信很多朋友都想过或已经经历过转行。工作可谓是我们生存乃至生活的主要收入来源,谁都希望拥有一份高薪又稳定的工作,以此来改善自己的生活和实现自己的大大小小的梦想!但又担心转行后的工作待遇达不到自己的预期,顾虑重重……不少想进入大数据分析行业的零基础学员经常会有这样一些疑问:大数据分析零基础应该怎么学习?自己适合学习大数据分析吗?人生,就是在不断地做选择,然后在这个选择过程中成长,让自己从一棵小树苗变成参天大树。就是我们每个对大数据充满幻想终于下定决心行动的学员的选择,我们给了自己4个月的时间,想要在大数据分析这个领域汲取养分,让自己壮大成长。【明确方向】通过国家的战略规划,看到BAT的大牛们都在大数据行业布局,新闻媒体追捧这大数据分析行业的项目和热点,我想如果我还没有能力独立判断的时候,跟着国家政策和互联网大佬们的步调走,这应该是错不了的。【付诸行动】明确了方向之后,我就整装待发,刚开始是在网络上购买了很多的视频教程,也买了很多书籍,但是最大的问题就在于,我不知道怎么入手,没关系,有信心有耐心肯定能战胜困难,我坚持了一个月,学习的节奏越来越乱,陆陆续续出现了很多的问题,没人指导,请教了几个业内的朋友,但对方工作繁忙,问了几次之后就不好意思了,自学陷入了死循环。意识到我学习效率的低下,以及无人指导的问题想想未来的康庄大道,咬咬牙告诉自己,一定好好好学,不然就浪费太多时间最后还会是一无所获。最后找到组织(AAA教育)一起学习进步!大数据分析零基础学习路线,有信心能坚持学习的话,那就当下开始行动吧!一、大数据技术基础1、linux操作基础linux系统简介与安装linux常用命令–文件操作linux常用命令–用户管理与权限linux常用命令–系统管理linux常用命令–免密登陆配置与网络管理linux上常用软件安装linux本地yum源配置及yum软件安装linux防火墙配置linux高级文本处理命令cut、sed、awklinux定时任务crontab2、shell编程shell编程–基本语法shell编程–流程控制shell编程–函数shell编程–综合案例–自动化部署脚本3、内存数据库redisredis和nosql简介redis客户端连接redis的string类型数据结构操作及应用-对象缓存redis的list类型数据结构操作及应用案例-任务调度队列redis的hash及set数据结构操作及应用案例-购物车redis的sortedset数据结构操作及应用案例-排行榜4、布式协调服务zookeeperzookeeper简介及应用场景zookeeper集群安装部署zookeeper的数据节点与命令行操作zookeeper的java客户端基本操作及事件监听zookeeper核心机制及数据节点zookeeper应用案例–分布式共享资源锁zookeeper应用案例–服务器上下线动态感知zookeeper的数据一致性原理及leader选举机制5、java高级特性增强Java多线程基本知识Java同步关键词详解java并发包线程池及在开源软件中的应用Java并发包消息队里及在开源软件中的应用Java JMS技术Java动态代理反射6、轻量级RPC框架开发RPC原理学习Nio原理学习Netty常用API学习轻量级RPC框架需求分析及原理分析轻量级RPC框架开发二、离线计算系统1、hadoop快速入门hadoop背景介绍分布式系统概述离线数据分析流程介绍集群搭建集群使用初步2、HDFS增强HDFS的概念和特性HDFS的shell(命令行客户端)操作HDFS的工作机制NAMENODE的工作机制java的api操作案例1:开发shell采集脚本3、MAPREDUCE详解自定义hadoop的RPC框架Mapreduce编程规范及示例编写Mapreduce程序运行模式及debug方法mapreduce程序运行模式的内在机理mapreduce运算框架的主体工作流程自定义对象的序列化方法MapReduce编程案例4、MAPREDUCE增强Mapreduce排序自定义partitionerMapreduce的combinermapreduce工作机制详解5、MAPREDUCE实战maptask并行度机制-文件切片maptask并行度设置倒排索引共同好友6、federation介绍和hive使用Hadoop的HA机制HA集群的安装部署集群运维测试之Datanode动态上下线集群运维测试之Namenode状态切换管理集群运维测试之数据块的balanceHA下HDFS-API变化hive简介hive架构hive安装部署hvie初使用7、hive增强和flume介绍HQL-DDL基本语法HQL-DML基本语法HIVE的joinHIVE 参数配置HIVE 自定义函数和TransformHIVE 执行HQL的实例分析HIVE最佳实践注意点HIVE优化策略HIVE实战案例Flume介绍Flume的安装部署案例:采集目录到HDFS案例:采集文件到HDFS三、流式计算1、Storm从入门到精通Storm是什么Storm架构分析Storm架构分析Storm编程模型、Tuple源码、并发度分析Storm WordCount案例及常用Api分析Storm集群部署实战Storm+Kafka+Redis业务指标计算Storm源码下载编译Strom集群启动及源码分析Storm任务提交及源码分析Storm数据发送流程分析Storm通信机制分析Storm消息容错机制及源码分析Storm多stream项目分析编写自己的流式任务执行框架2、Storm上下游及架构集成消息队列是什么Kakfa核心组件Kafka集群部署实战及常用命令Kafka配置文件梳理Kakfa JavaApi学习Kafka文件存储机制分析Redis基础及单机环境部署Redis数据结构及典型案例Flume快速入门Flume+Kafka+Storm+Redis整合四、内存计算体系Spark1、scala编程scala编程介绍scala相关软件安装scala基础语法scala方法和函数scala函数式编程特点scala数组和集合scala编程练习(单机版WordCount)scala面向对象scala模式匹配actor编程介绍option和偏函数实战:actor的并发WordCount柯里化隐式转换2、AKKA与RPCAkka并发编程框架实战:RPC编程实战3、Spark快速入门spark介绍spark环境搭建RDD简介RDD的转换和动作实战:RDD综合练习RDD高级算子自定义Partitioner实战:网站访问次数广播变量实战:根据IP计算归属地自定义排序利用JDBC RDD实现数据导入导出WorldCount执行流程详解4、RDD详解RDD依赖关系RDD缓存机制RDD的Checkpoint检查点机制Spark任务执行过程分析RDD的Stage划分5、Spark-Sql应用Spark-SQLSpark结合HiveDataFrame实战:Spark-SQL和DataFrame案例6、SparkStreaming应用实战Spark-Streaming简介Spark-Streaming编程实战:StageFulWordCountFlume结合Spark StreamingKafka结合Spark Streaming窗口函数ELK技术栈介绍ElasticSearch安装和使用Storm架构分析Storm编程模型、Tuple源码、并发度分析Storm WordCount案例及常用Api分析7、Spark核心源码解析Spark源码编译Spark远程debugSpark任务提交行流程源码分析Spark通信流程源码分析SparkContext创建过程源码分析DriverActor和ClientActor通信过程源码分析Worker启动Executor过程源码分析Executor向DriverActor注册过程源码分析Executor向Driver注册过程源码分析DAGScheduler和TaskScheduler源码分析Shuffle过程源码分析Task执行过程源码分析五、机器学习算法1、python及numpy库机器学习简介机器学习与pythonpython语言–快速入门python语言–数据类型详解python语言–流程控制语句python语言–函数使用python语言–模块和包phthon语言–面向对象python机器学习算法库–numpy机器学习必备数学知识–概率论2、常用算法实现knn分类算法–算法原理knn分类算法–代码实现knn分类算法–手写字识别案例lineage回归分类算法–算法原理lineage回归分类算法–算法实现及demo朴素贝叶斯分类算法–算法原理朴素贝叶斯分类算法–算法实现朴素贝叶斯分类算法–垃圾邮件识别应用案例kmeans聚类算法–算法原理kmeans聚类算法–算法实现kmeans聚类算法–地理位置聚类应用决策树分类算法–算法原理决策树分类算法–算法实现时下的大数据分析时代与人工智能热潮,相信有许多对大数据分析师非常感兴趣、跃跃欲试想着转行的朋友,但面向整个社会,最不缺的其实就是人才,对于是否转行大数据分析行列,对于能否勇敢一次跳出自己的舒适圈,不少人还是踌躇满志啊!毕竟好多决定,一旦做出了就很难再回头了。不过如果你已经转行到大数据分析领域,就不要后悔,做到如何脱颖而出才是关键。因此本文给出一些建议,针对想要转行大数据分析行列且是零基础转行的小伙伴们,希望对你们有所裨益,也希望你们将来学有所成,不后悔,更不灰心!相关推荐:《转行大数据分析师后悔了》、《ui设计培训四个月骗局大爆料》、《零基础学大数据分析现实吗》、《大数据分析十八般工具》、《大数据分析流程是什么》、《大数据分析12大就业方向》
2023-08-10 09:50:233

zookeeper什么意思

zookeeper是动物管理员的意思。ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。ZooKeeper包含一个简单的原语集,提供Java和C的接口。ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_homesrc ecipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。它的原理:ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos做了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。ZooKeeper的基本运转流程:1、选举Leader。2、同步数据。3、选举Leader过程中算法有很多,但要达到的选举标准是一致的。4、Leader要具有最高的执行ID,类似root权限。5、集群中大多数的机器得到响应并接受选出的Leader。
2023-08-10 09:51:411

为什么要使用ZooKeeper

记得在大约在2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。 但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中。当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑
2023-08-10 09:52:091

zookeeper 用到哪些设计模式

  ZooKeeper作为发现服务的问题  ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它 很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。  在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且, 作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。  作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能 因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的,如果你这么用就惨 了!  而且更何况,如果被用作Service发现服务,ZooKeeper本身并没有正确的处理网络分割的问题;而在云端,网络分割问题跟其他类型的故障一样的确会发生;所以最好提前对这个问题做好100%的准备。就像 Jepsen在 ZooKeeper网站上发布的博客中所说:在ZooKeeper中,如果在同一个网络分区(partition)的节点数(nodes)数达不到 ZooKeeper选取Leader节点的逗法定人数地时,它们就会从ZooKeeper中断开,当然同时也就不能提供Service发现服务了。  如果给ZooKeeper加上客户端缓存(注:给ZooKeeper节点配上本地缓存)或者其他类似技术的话可以缓解ZooKeeper因为网络故障造成节点同步信息错误的问题。 Pinterest与 Airbnb公 司就使用了这个方法来防止ZooKeeper故障发生。这种方式可以从表面上解决这个问题,具体地说,当部分或者所有节点跟ZooKeeper断开的情况 下,每个节点还可以从本地缓存中获取到数据;但是,即便如此,ZooKeeper下所有节点不可能保证任何时候都能缓存所有的服务注册信息。如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是逗健康地的,可以正常提供服务的;所以导致到达这些节点的服务请求 被丢失了。(注:这也是为什么ZooKeeper不满足CAP中A的原因)  更深层次的原因是,ZooKeeper是按照CP原则构建的,也就是说它能保证每个节点的数据保持一致,而为ZooKeeper加上缓存的做法的 目的是为了让ZooKeeper变得更加可靠(available);但是,ZooKeeper设计的本意是保持节点的数据一致,也就是CP。所以,这样一来,你可能既得不到一个数据一致的(CP)也得不到一个高可用的(AP)的Service发现服务了;因为,这相当于你在一个已有的CP系统上强制栓了 一个AP的系统,这在本质上就行不通的!一个Service发现服务应该从一开始就被设计成高可用的才行!  如果抛开CAP原理不管,正确的设置与维护ZooKeeper服务就非常的困难;错误会 经常发生, 导致很多工程被建立只是为了减轻维护ZooKeeper的难度。这些错误不仅存在与客户端而且还存在于ZooKeeper服务器本身。Knewton平台 很多故障就是由于ZooKeeper使用不当而导致的。那些看似简单的操作,如:正确的重建观察者(reestablishing watcher)、客户端Session与异常的处理与在ZK窗口中管理内存都是非常容易导致ZooKeeper出错的。同时,我们确实也遇到过 ZooKeeper的一些经典bug: ZooKeeper-1159 与 ZooKeeper-1576; 我们甚至在生产环境中遇到过ZooKeeper选举Leader节点失败的情况。这些问题之所以会出现,在于ZooKeeper需要管理与保障所管辖服务 群的Session与网络连接资源(注:这些资源的管理在分布式系统环境下是极其困难的);但是它不负责管理服务的发现,所以使用ZooKeeper当 Service发现服务得不偿失。  做出正确的选择:Eureka的成功  我们把Service发现服务从ZooKeeper切换到了Eureka平台,它是一个开 源的服务发现解决方案,由Netflix公司开发。(注:Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。)Eureka一开 始就被设计成高可用与可伸缩的Service发现服务,这两个特点也是Netflix公司开发所有平台的两个特色。( 他们都在讨论Eureka)。自从切换工作开始到现在,我们实现了在生产环境中所有依赖于Eureka的产品没有下线维护的记录。我们也被告知过,在云平台做服务迁移注定要遇到失败;但是我们从这个例子中得到的经验是,一个优秀的Service发现服务在其中发挥了至关重要的作用!  首先,在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务注册信息而已。所以,再也不用担心有逗掉队地的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广的网络分割故障,并实现逗0地宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新 的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。  但是,Eureka做到的不止这些。正常配置下,Eureka内置了心跳服务,用于淘汰一些逗濒死地的服务器;如果在Eureka中注册的服务, 它的逗心跳地变得迟缓时,Eureka会将其整个剔除出管理范围(这点有点像ZooKeeper的做法)。这是个很好的功能,但是当网络分割故障发生时,这也是非常危险的;因为,那些因为网络问题(注:心跳慢被剔除了)而被剔除出去的服务器本身是很地健康逗的,只是因为网络分割故障把Eureka集群分割 成了独立的子网而不能互访而已。  幸运的是,Netflix考虑到了这个缺陷。如果Eureka服务节点在短时间里丢失了大量的心跳连接(注:可能发生了网络故障),那么这个 Eureka节点会进入地自我保护模式逗,同时保留那些逗心跳死亡逗的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对于地死亡逗的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出地自我保护模式逗。所以Eureka的哲学是,同时保 留地好数据逗与地坏数据逗总比丢掉任何地好数据逗要更好,所以这种模式在实践中非常有效。  最后,Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解 决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。  Eureka的构架保证了它能够成为Service发现服务。它相对与ZooKeeper来说剔除了Leader节点的选取或者事务日志机制,这 样做有利于减少使用者维护的难度也保证了Eureka的在运行时的健壮性。而且Eureka就是为发现服务所设计的,它有独立的客户端程序库,同时提供心 跳服务、服务健康监测、自动发布服务与自动刷新缓存的功能。但是,如果使用ZooKeeper你必须自己来实现这些功能。Eureka的所有库都是开源 的,所有人都能看到与使用这些源代码,这比那些只有一两个人能看或者维护的客户端库要好。  维护Eureka服务器也非常的简单,比如,切换一个节点只需要在现有EIP下移除一个现有的节点然后添加一个新的就行。Eureka提供了一个 web-based的图形化的运维界面,在这个界面中可以查看Eureka所管理的注册服务的运行状态信息:是否健康,运行日志等。Eureka甚至提供 了Restful-API接口,方便第三方程序集成Eureka的功能。
2023-08-10 09:52:171

为什么不使用ZooKeeper

为什么不使用?我们公司项目就使用zookeeper,包括阿里的现在很多项目也使用zookeeper做分布式应用程序数据的一致性处理方案。
2023-08-10 09:52:263

为什么不使用ZooKeeper

ZooKeeper作为发现服务的问题ZooKeeper(注:ZooKeeper是著名Hadoop的一个子项目,旨在解决大规模分 布式应用场景下,服务协调同步(Coordinate Service)的问题;它可以为同在一个分布式系统中的其他服务提供:统一命名服务、配置管理、分布式锁服务、集群管理等功能)是个伟大的开源项目,它很成熟,有相当大的社区来支持它的发展,而且在生产环境得到了广泛的使用;但是用它来做Service发现服务解决方案则是个错误。在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个);ZooKeeper是个CP的,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就是在极端环境下,ZooKeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。但是别忘了,ZooKeeper是分布式协调服务,它的职责是保证数据(注:配置数据,状态数据)在其管辖下的所有服务之间保持同步、一致;所以就不难理解为什么ZooKeeper被设计成CP而不是AP特性的了,如果是AP的,那么将会带来恐怖的后果(注:ZooKeeper就像交叉路口的信号灯一样,你能想象在交通要道突然信号灯失灵的情况吗?)。而且,作为ZooKeeper的核心实现算法 Zab,就是解决了分布式系统下数据如何在多个服务之间保持同步问题的。作为一个分布式协同服务,ZooKeeper非常好,但是对于Service发现服务来说就不合适了;因为对于Service发现服务来说就算是 返回了包含不实的信息的结果也比什么都不返回要好;再者,对于Service发现服务而言,宁可返回某服务5分钟之前在哪几个服务器上可用的信息,也不能因为暂时的网络故障而找不到可用的服务器,而不返回任何结果。所以说,用ZooKeeper来做Service发现服务是肯定错误的,如果你这么用就惨了!而且更何况,如果被用作Service发现服务,ZooKeeper本身并没有正确的处理网络分割的问题;而在云端,网络分割问题跟其他类型的故障一样的确会发生;所以最好提前对这个问题做好100%的准备。就像 Jepsen在 ZooKeeper网站上发布的博客中所说:在ZooKeeper中,如果在同一个网络分区(partition)的节点数(nodes)数达不到 ZooKeeper选取Leader节点的“法定人数”时,它们就会从ZooKeeper中断开,当然同时也就不能提供Service发现服务了。如果给ZooKeeper加上客户端缓存(注:给ZooKeeper节点配上本地缓存)或者其他类似技术的话可以缓解ZooKeeper因为网络故障造成节点同步信息错误的问题。 Pinterest与 Airbnb公 司就使用了这个方法来防止ZooKeeper故障发生。这种方式可以从表面上解决这个问题,具体地说,当部分或者所有节点跟ZooKeeper断开的情况下,每个节点还可以从本地缓存中获取到数据;但是,即便如此,ZooKeeper下所有节点不可能保证任何时候都能缓存所有的服务注册信息。如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障(注:由于交换机故障导致交换机底下的子网间不能互访);那么ZooKeeper会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是“健康”的,可以正常提供服务的;所以导致到达这些节点的服务请求被丢失了。(注:这也是为什么ZooKeeper不满足CAP中A的原因)更深层次的原因是,ZooKeeper是按照CP原则构建的,也就是说它能保证每个节点的数据保持一致,而为ZooKeeper加上缓存的做法的 目的是为了让ZooKeeper变得更加可靠(available);但是,ZooKeeper设计的本意是保持节点的数据一致,也就是CP。所以,这样一来,你可能既得不到一个数据一致的(CP)也得不到一个高可用的(AP)的Service发现服务了;因为,这相当于你在一个已有的CP系统上强制栓了一个AP的系统,这在本质上就行不通的!一个Service发现服务应该从一开始就被设计成高可用的才行!如果抛开CAP原理不管,正确的设置与维护ZooKeeper服务就非常的困难;错误会 经常发生, 导致很多工程被建立只是为了减轻维护ZooKeeper的难度。这些错误不仅存在与客户端而且还存在于ZooKeeper服务器本身。Knewton平台很多故障就是由于ZooKeeper使用不当而导致的。那些看似简单的操作,如:正确的重建观察者(reestablishing watcher)、客户端Session与异常的处理与在ZK窗口中管理内存都是非常容易导致ZooKeeper出错的。同时,我们确实也遇到过 ZooKeeper的一些经典bug: ZooKeeper-1159 与 ZooKeeper-1576; 我们甚至在生产环境中遇到过ZooKeeper选举Leader节点失败的情况。这些问题之所以会出现,在于ZooKeeper需要管理与保障所管辖服务群的Session与网络连接资源(注:这些资源的管理在分布式系统环境下是极其困难的);但是它不负责管理服务的发现,所以使用ZooKeeper当Service发现服务得不偿失。做出正确的选择:Eureka的成功我们把Service发现服务从ZooKeeper切换到了Eureka平台,它是一个开 源的服务发现解决方案,由Netflix公司开发。(注:Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。)Eureka一开始就被设计成高可用与可伸缩的Service发现服务,这两个特点也是Netflix公司开发所有平台的两个特色。( 他们都在讨论Eureka)。自从切换工作开始到现在,我们实现了在生产环境中所有依赖于Eureka的产品没有下线维护的记录。我们也被告知过,在云平台做服务迁移注定要遇到失败;但是我们从这个例子中得到的经验是,一个优秀的Service发现服务在其中发挥了至关重要的作用!首先,在Eureka平台中,如果某台服务器宕机,Eureka不会有类似于ZooKeeper的选举leader的过程;客户端请求会自动切换 到新的Eureka节点;当宕机的服务器重新恢复后,Eureka会再次将其纳入到服务器集群管理之中;而对于它来说,所有要做的无非是同步一些新的服务注册信息而已。所以,再也不用担心有“掉队”的服务器恢复以后,会从Eureka服务器集群中剔除出去的风险了。Eureka甚至被设计用来应付范围更广的网络分割故障,并实现“0”宕机维护需求。当网络分割故障发生时,每个Eureka节点,会持续的对外提供服务(注:ZooKeeper不会):接收新的服务注册同时将它们提供给下游的服务发现请求。这样一来,就可以实现在同一个子网中(same side of partition),新发布的服务仍然可以被发现与访问。但是,Eureka做到的不止这些。正常配置下,Eureka内置了心跳服务,用于淘汰一些“濒死”的服务器;如果在Eureka中注册的服务, 它的“心跳”变得迟缓时,Eureka会将其整个剔除出管理范围(这点有点像ZooKeeper的做法)。这是个很好的功能,但是当网络分割故障发生时,这也是非常危险的;因为,那些因为网络问题(注:心跳慢被剔除了)而被剔除出去的服务器本身是很”健康“的,只是因为网络分割故障把Eureka集群分割成了独立的子网而不能互访而已。幸运的是,Netflix考虑到了这个缺陷。如果Eureka服务节点在短时间里丢失了大量的心跳连接(注:可能发生了网络故障),那么这个 Eureka节点会进入”自我保护模式“,同时保留那些“心跳死亡“的服务注册信息不过期。此时,这个Eureka节点对于新的服务还能提供注册服务,对于”死亡“的仍然保留,以防还有客户端向其发起请求。当网络故障恢复后,这个Eureka节点会退出”自我保护模式“。所以Eureka的哲学是,同时保留”好数据“与”坏数据“总比丢掉任何”好数据“要更好,所以这种模式在实践中非常有效。最后,Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。 所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。Eureka的构架保证了它能够成为Service发现服务。它相对与ZooKeeper来说剔除了Leader节点的选取或者事务日志机制,这 样做有利于减少使用者维护的难度也保证了Eureka的在运行时的健壮性。而且Eureka就是为发现服务所设计的,它有独立的客户端程序库,同时提供心跳服务、服务健康监测、自动发布服务与自动刷新缓存的功能。但是,如果使用ZooKeeper你必须自己来实现这些功能。Eureka的所有库都是开源的,所有人都能看到与使用这些源代码,这比那些只有一两个人能看或者维护的客户端库要好。维护Eureka服务器也非常的简单,比如,切换一个节点只需要在现有EIP下移除一个现有的节点然后添加一个新的就行。Eureka提供了一个 web-based的图形化的运维界面,在这个界面中可以查看Eureka所管理的注册服务的运行状态信息:是否健康,运行日志等。Eureka甚至提供了Restful-API接口,方便第三方程序集成Eureka的功能。
2023-08-10 09:52:362

IT技术人员转行大数据应该考虑哪些问题

转行这个词汇,一直是职场上此起彼伏的一个热门话题,相信很多朋友都想过或已经经历过转行。工作可谓是我们生存乃至生活的主要收入来源,谁都希望拥有一份高薪又稳定的工作,以此来改善自己的生活和实现自己的大大小小的梦想!但又担心转行后的工作待遇达不到自己的预期,顾虑重重……不少想进入大数据分析行业的零基础学员经常会有这样一些疑问:大数据分析零基础应该怎么学习?自己适合学习大数据分析吗?人生,就是在不断地做选择,然后在这个选择过程中成长,让自己从一棵小树苗变成参天大树。就是我们每个对大数据充满幻想终于下定决心行动的学员的选择,我们给了自己4个月的时间,想要在大数据分析这个领域汲取养分,让自己壮大成长。【明确方向】通过国家的战略规划,看到BAT的大牛们都在大数据行业布局,新闻媒体追捧这大数据分析行业的项目和热点,我想如果我还没有能力独立判断的时候,跟着国家政策和互联网大佬们的步调走,这应该是错不了的。【付诸行动】明确了方向之后,我就整装待发,刚开始是在网络上购买了很多的视频教程,也买了很多书籍,但是最大的问题就在于,我不知道怎么入手,没关系,有信心有耐心肯定能战胜困难,我坚持了一个月,学习的节奏越来越乱,陆陆续续出现了很多的问题,没人指导,请教了几个业内的朋友,但对方工作繁忙,问了几次之后就不好意思了,自学陷入了死循环。意识到我学习效率的低下,以及无人指导的问题想想未来的康庄大道,咬咬牙告诉自己,一定好好好学,不然就浪费太多时间最后还会是一无所获。最后找到组织一起学习进步!大数据分析零基础学习路线,有信心能坚持学习的话,那就当下开始行动吧!一、大数据技术基础1、linux操作基础linux系统简介与安装linux常用命令–文件操作linux常用命令–用户管理与权限linux常用命令–系统管理linux常用命令–免密登陆配置与网络管理linux上常用软件安装linux本地yum源配置及yum软件安装linux防火墙配置linux高级文本处理命令cut、sed、awklinux定时任务crontab2、shell编程shell编程–基本语法shell编程–流程控制shell编程–函数shell编程–综合案例–自动化部署脚本3、内存数据库redisredis和nosql简介redis客户端连接redis的string类型数据结构操作及应用-对象缓存redis的list类型数据结构操作及应用案例-任务调度队列redis的hash及set数据结构操作及应用案例-购物车redis的sortedset数据结构操作及应用案例-排行榜4、布式协调服务zookeeperzookeeper简介及应用场景zookeeper集群安装部署zookeeper的数据节点与命令行操作zookeeper的java客户端基本操作及事件监听zookeeper核心机制及数据节点zookeeper应用案例–分布式共享资源锁zookeeper应用案例–服务器上下线动态感知zookeeper的数据一致性原理及leader选举机制5、java高级特性增强Java多线程基本知识Java同步关键词详解java并发包线程池及在开源软件中的应用Java并发包消息队里及在开源软件中的应用Java JMS技术Java动态代理反射6、轻量级RPC框架开发RPC原理学习Nio原理学习Netty常用API学习轻量级RPC框架需求分析及原理分析轻量级RPC框架开发二、离线计算系统1、hadoop快速入门hadoop背景介绍分布式系统概述离线数据分析流程介绍集群搭建集群使用初步2、HDFS增强HDFS的概念和特性HDFS的shell(命令行客户端)操作HDFS的工作机制NAMENODE的工作机制java的api操作案例1:开发shell采集脚本3、MAPREDUCE详解自定义hadoop的RPC框架Mapreduce编程规范及示例编写Mapreduce程序运行模式及debug方法mapreduce程序运行模式的内在机理mapreduce运算框架的主体工作流程自定义对象的序列化方法MapReduce编程案例4、MAPREDUCE增强Mapreduce排序自定义partitionerMapreduce的combinermapreduce工作机制详解5、MAPREDUCE实战maptask并行度机制-文件切片maptask并行度设置倒排索引共同好友6、federation介绍和hive使用Hadoop的HA机制HA集群的安装部署集群运维测试之Datanode动态上下线集群运维测试之Namenode状态切换管理集群运维测试之数据块的balanceHA下HDFS-API变化hive简介hive架构hive安装部署hvie初使用7、hive增强和flume介绍HQL-DDL基本语法HQL-DML基本语法HIVE的joinHIVE 参数配置HIVE 自定义函数和TransformHIVE 执行HQL的实例分析HIVE最佳实践注意点HIVE优化策略HIVE实战案例Flume介绍Flume的安装部署案例:采集目录到HDFS案例:采集文件到HDFS三、流式计算1、Storm从入门到精通Storm是什么Storm架构分析Storm架构分析Storm编程模型、Tuple源码、并发度分析Storm WordCount案例及常用Api分析Storm集群部署实战Storm+Kafka+Redis业务指标计算Storm源码下载编译Strom集群启动及源码分析Storm任务提交及源码分析Storm数据发送流程分析Storm通信机制分析Storm消息容错机制及源码分析Storm多stream项目分析编写自己的流式任务执行框架2、Storm上下游及架构集成消息队列是什么Kakfa核心组件Kafka集群部署实战及常用命令Kafka配置文件梳理Kakfa JavaApi学习Kafka文件存储机制分析Redis基础及单机环境部署Redis数据结构及典型案例Flume快速入门Flume+Kafka+Storm+Redis整合四、内存计算体系Spark1、scala编程scala编程介绍scala相关软件安装scala基础语法scala方法和函数scala函数式编程特点scala数组和集合scala编程练习(单机版WordCount)scala面向对象scala模式匹配actor编程介绍option和偏函数实战:actor的并发WordCount柯里化隐式转换2、AKKA与RPCAkka并发编程框架实战:RPC编程实战3、Spark快速入门spark介绍spark环境搭建RDD简介RDD的转换和动作实战:RDD综合练习RDD高级算子自定义Partitioner实战:网站访问次数广播变量实战:根据IP计算归属地自定义排序利用JDBC RDD实现数据导入导出WorldCount执行流程详解4、RDD详解RDD依赖关系RDD缓存机制RDD的Checkpoint检查点机制Spark任务执行过程分析RDD的Stage划分5、Spark-Sql应用Spark-SQLSpark结合HiveDataFrame实战:Spark-SQL和DataFrame案例6、SparkStreaming应用实战Spark-Streaming简介Spark-Streaming编程实战:StageFulWordCountFlume结合Spark StreamingKafka结合Spark Streaming窗口函数ELK技术栈介绍ElasticSearch安装和使用Storm架构分析Storm编程模型、Tuple源码、并发度分析Storm WordCount案例及常用Api分析7、Spark核心源码解析Spark源码编译Spark远程debugSpark任务提交行流程源码分析Spark通信流程源码分析SparkContext创建过程源码分析DriverActor和ClientActor通信过程源码分析Worker启动Executor过程源码分析Executor向DriverActor注册过程源码分析Executor向Driver注册过程源码分析DAGScheduler和TaskScheduler源码分析Shuffle过程源码分析Task执行过程源码分析五、机器学习算法1、python及numpy库机器学习简介机器学习与pythonpython语言–快速入门python语言–数据类型详解python语言–流程控制语句python语言–函数使用python语言–模块和包phthon语言–面向对象python机器学习算法库–numpy机器学习必备数学知识–概率论2、常用算法实现knn分类算法–算法原理knn分类算法–代码实现knn分类算法–手写字识别案例lineage回归分类算法–算法原理lineage回归分类算法–算法实现及demo朴素贝叶斯分类算法–算法原理朴素贝叶斯分类算法–算法实现朴素贝叶斯分类算法–垃圾邮件识别应用案例kmeans聚类算法–算法原理kmeans聚类算法–算法实现kmeans聚类算法–地理位置聚类应用决策树分类算法–算法原理决策树分类算法–算法实现时下的大数据分析时代与人工智能热潮,相信有许多对大数据分析师非常感兴趣、跃跃欲试想着转行的朋友,但面向整个社会,最不缺的其实就是人才,对于是否转行大数据分析行列,对于能否勇敢一次跳出自己的舒适圈,不少人还是踌躇满志啊!毕竟好多决定,一旦做出了就很难再回头了。不过如果你已经转行到大数据分析领域,就不要后悔,做到如何脱颖而出才是关键。因此本文给出一些建议,针对想要转行大数据分析行列且是零基础转行的小伙伴们,希望对你们有所裨益,也希望你们将来学有所成,不后悔,更不灰心!相关推荐:《大数据分析师工作内容》、《转行大数据分析师后悔了》、《零基础学大数据分析现实吗》、《大数据分析要学什么》、《大数据分析方法》、《浅析大数据分析技术》、《大数据分析流程是什么》、《大数据分析十八般工具》、《大数据分析12大就业方向》
2023-08-10 09:52:472

同时写文件和数据库,如何保证数据一致性?

1.计算文件 md5 ; 2.记日志(比如某张表中插入一条记录包含 md5, filepath ;或者日志文件 -> md5 为文件名,内容 filepath ); ----优化 思考: 考虑到zookeeper的数据一致性原理,有个机制是3PC, paxos算法 leader 选举,server 接受leader 的 事务请求,给予响应,leader 接收到大多数的成功响应,再次给server发送事物提交请求,同时告诉client,事物ok 这是对多节点的一个事物操作,而题目是对单节点的一个事物的操作,事物分为多个步骤。
2023-08-10 09:52:541

大数据需要掌握哪些技能

想学习大数据技术,是不是首先要知道大数据技术有哪些呢?也好知道自己未来应该往哪个方向发展,应该重点学习哪些知识?抽象而言,各种大数据技术无外乎分布式存储 + 并行计算。具体体现为各种分布式文件系统和建立在其上的并行运算框架。这些软件程序都部署在多个相互连通、统一管理的物理或虚拟运算节点之上,形成集群(cluster)。因此不妨说,云计算是大数据的基础。下面介绍几种当前比较流行的大数据技术:1.HadoopHadoop无疑是当前很知名的大数据技术了。2003年到2004年间,Google发布了关于GFS、MapReduce和BigTable三篇技术论文(这几篇论文成为了后来云计算、大数据领域发展的重要基石)。当时一位因公司倒闭赋闲在家的程序员Doug Cutting根据前两篇论文,开发出了一个简化的山寨版GFS – HDFS,以及基于其的MapReduce计算框架,这就是Hadoop当初的版本。后来Cutting被Yahoo雇佣,得以依赖Yahoo的资源改进Hadoop,并将其贡献给了Apache开源社区。简单描述Hadoop原理:数据分布式存储,运算程序被发派到各个数据节点进行分别运算(Map),再将各个节点的运算结果进行合并归一(Reduce),生成结果。相对于动辄TB级别的数据,计算程序一般在KB – MB的量级,这种移动计算不移动数据的设计节约了大量网络带宽和时间,并使得运算过程可以充分并行化。在其诞生后的近10年里,Hadoop凭借其简单、易用、高效、免费、社区支持丰富等特征成为众多企业云计算、大数据实施的首选。2.StormHadoop虽好,却有其“死穴”.其一:它的运算模式是批处理。这对于许多有实时性要求的业务就无法做到很好的支持。因此,Twitter推出了他们自己的基于流的运算框架——Storm。不同于Hadoop一次性处理所有数据并得出统一结果的作业(job),Storm对源源导入的数据流进行持续不断的处理,随时得出增量结果。3.SparkHadoop的另一个致命弱点是:它的所有中间结果都需要进行硬盘存储,I/O消耗巨大,这就使得它很不适合多次迭代的运算。而大多数机器学习算法,恰恰要求大量迭代运算。2010年开始,UC Berkeley AMP Lab开始研发分布式运算的中间过程全部内存存储的Spark框架,由此在迭代计算上大大提高了效率。也因此成为了Hadoop的强有力竞争者。4.NoSQL 数据库NoSQL数据库可以泛指非关系型数据库,不过一般用来指称那些建立在分布式文件系统(例如HDFS)之上,基于key-value对的数据管理系统。相对于传统的关系型数据库,NoSQL数据库中存储的数据无需主键和严格定义的schema。于是,大量半结构化、非结构化数据可以在未经清洗的情况下直接进行存储。这一点满足了处理大量、高速、多样的大数据的需求。当前比较流行的NoSQL数据库有MongoDB,Redis,Cassandra,HBase等。NoSQL并不是没有SQL,而是不仅仅有(not only)SQL的意思。为了兼容之前许多运行在关系型数据库上的业务逻辑,有很多在NoSQL数据库上运行SQL的工具涌现出来,典型的例如Hive和Pig,它们将用户的SQL语句转化成MapReduce作业,在Hadoop上运行。大数据产业已进入发展的“快车道”,急需大量优秀的大数据人才作为后盾。能够在大数据行业崛起的初期进入到这个行业当中来,才有机会成为时代的弄潮儿。
2023-08-10 09:53:114

Hbase 启动报错 class org.apache.hadoop.hbase.master.HMaster

抱歉碰不到机器可能无法确定问题的具体原因,但从你的问题看出你可能走入了一个误区——认为Hbase启动或安装出现问题从原理上讲,在集群中Zookeeper中会通过投票方式选举出一个Zookeeper为主,其余类似于主的热备而主Zookeeper会指定Hmaster,并由指定的Hmaster来进行Hbase的操作现在你的报错是ZooKeeper create failed after 4 attempts(Zookeeper尝试创建并失败4次导致最终无法创建)带来的后果就是你的Hmaster未选举出(并离线),使得你的Hbase无法管理大概原因可能有两种一种是因为各机器间无法正常通信导致集群脑裂Zookeeper无法进行选举或是各主机之间权限不足导致声明Master的短命节点文件无法被创建(可能性较低)(也许干脆就是集群数量过小无法选举?)大概是这些可能,我也还在学习阶段无法给出太过明确的答案,不过建议你从集群互相的通讯(包括每个节点上的Zookeeper安装情况以及互信、网络情况来入手考虑一下?我和很多朋友在安装过程中因为各个节点的软件源以及互信以及软件仓库网络配置等问题纠结了很多天,还有些安装包本身是有问题的(文件损坏或是唯独nagios安装包权限为222导致错误),你可以从这方面入手试试
2023-08-10 09:53:431

如何保证数据库缓存的最终一致性?

对于互联网业务来说,传统的直接访问数据库方式,主要通过数据分片、一主多从等方式来扛住读写流量,但随着数据量的积累和流量的激增,仅依赖数据库来承接所有流量,不仅成本高、效率低、而且还伴随着稳定性降低的风险。 鉴于大部分业务通常是读多写少(读取频率远远高于更新频率),甚至存在读操作数量高出写操作多个数量级的情况。因此, 在架构设计中,常采用增加缓存层来提高系统的响应能力 ,提升数据读写性能、减少数据库访问压力,从而提升业务的稳定性和访问体验。 根据 CAP 原理,分布式系统在可用性、一致性和分区容错性上无法兼得,通常由于分区容错无法避免,所以一致性和可用性难以同时成立。对于缓存系统来说, 如何保证其数据一致性是一个在应用缓存的同时不得不解决的问题 。 需要明确的是,缓存系统的数据一致性通常包括持久化层和缓存层的一致性、以及多级缓存之间的一致性,这里我们仅讨论前者。持久化层和缓存层的一致性问题也通常被称为双写一致性问题,“双写”意为数据既在数据库中保存一份,也在缓存中保存一份。 对于一致性来说,包含强一致性和弱一致性 ,强一致性保证写入后立即可以读取,弱一致性则不保证立即可以读取写入后的值,而是尽可能的保证在经过一定时间后可以读取到,在弱一致性中应用最为广泛的模型则是最终一致性模型,即保证在一定时间之后写入和读取达到一致的状态。对于应用缓存的大部分场景来说,追求的则是最终一致性,少部分对数据一致性要求极高的场景则会追求强一致性。 为了达到最终一致性,针对不同的场景,业界逐步形成了下面这几种应用缓存的策略。 — 1 — Cache-Aside Cache-Aside 意为旁路缓存模式,是应用最为广泛的一种缓存策略。下面的图示展示了它的读写流程,来看看它是如何保证最终一致性的。在读请求中,首先请求缓存,若缓存命中(cache hit),则直接返回缓存中的数据;若缓存未命中(cache miss),则查询数据库并将查询结果更新至缓存,然后返回查询出的数据(demand-filled look-aside )。在写请求中,先更新数据库,再删除缓存(write-invalidate)。 1、为什么删除缓存,而不是更新缓存? 在 Cache-Aside 中,对于读请求的处理比较容易理解,但在写请求中,可能会有读者提出疑问,为什么要删除缓存,而不是更新缓存?站在符合直觉的角度来看,更新缓存是一个容易被理解的方案,但站在性能和安全的角度,更新缓存则可能会导致一些不好的后果。 首先是性能 ,当该缓存对应的结果需要消耗大量的计算过程才能得到时,比如需要访问多张数据库表并联合计算,那么在写操作中更新缓存的动作将会是一笔不小的开销。同时,当写操作较多时,可能也会存在刚更新的缓存还没有被读取到,又再次被更新的情况(这常被称为缓存扰动),显然,这样的更新是白白消耗机器性能的,会导致缓存利用率不高。 而等到读请求未命中缓存时再去更新,也符合懒加载的思路,需要时再进行计算。删除缓存的操作不仅是幂等的,可以在发生异常时重试,而且写-删除和读-更新在语义上更加对称。 其次是安全 ,在并发场景下,在写请求中更新缓存可能会引发数据的不一致问题。参考下面的图示,若存在两个来自不同线程的写请求,首先来自线程 1 的写请求更新了数据库(step 1),接着来自线程 2 的写请求再次更新了数据库(step 3),但由于网络延迟等原因,线程 1 可能会晚于线程 2 更新缓存(step 4 晚于 step 3),那么这样便会导致最终写入数据库的结果是来自线程 2 的新值,写入缓存的结果是来自线程 1 的旧值,即缓存落后于数据库,此时再有读请求命中缓存(step 5),读取到的便是旧值。 2、为什么先更新数据库,而不是先删除缓存? 另外,有读者也会对更新数据库和删除缓存的时序产生疑问,那么为什么不先删除缓存,再更新数据库呢?在单线程下,这种方案看似具有一定合理性,这种合理性体现在删除缓存成功。 但更新数据库失败的场景下,尽管缓存被删除了,下次读操作时,仍能将正确的数据写回缓存,相对于 Cache-Aside 中更新数据库成功,删除缓存失败的场景来说,先删除缓存的方案似乎更合理一些。那么,先删除缓存有什么问题呢? 问题仍然出现在并发场景下,首先来自线程 1 的写请求删除了缓存(step 1),接着来自线程 2 的读请求由于缓存的删除导致缓存未命中,根据 Cache-Aside 模式,线程 2 继而查询数据库(step 2),但由于写请求通常慢于读请求,线程 1 更新数据库的操作可能会晚于线程 2 查询数据库后更新缓存的操作(step 4 晚于 step 3),那么这样便会导致最终写入缓存的结果是来自线程 2 中查询到的旧值,而写入数据库的结果是来自线程 1 的新值,即缓存落后于数据库,此时再有读请求命中缓存( step 5 ),读取到的便是旧值。 另外,先删除缓存,由于缓存中数据缺失,加剧数据库的请求压力,可能会增大缓存穿透出现的概率。 3、如果选择先删除缓存,再更新数据库,那如何解决一致性问题呢? 为了避免“先删除缓存,再更新数据库”这一方案在读写并发时可能带来的缓存脏数据,业界又提出了延时双删的策略,即在更新数据库之后,延迟一段时间再次删除缓存,为了保证第二次删除缓存的时间点在读请求更新缓存之后,这个延迟时间的经验值通常应稍大于业务中读请求的耗时。 延迟的实现可以在代码中 sleep 或采用延迟队列。显而易见的是,无论这个值如何预估,都很难和读请求的完成时间点准确衔接,这也是延时双删被诟病的主要原因。 4、那么 Cache-Aside 存在数据不一致的可能吗? 在 Cache-Aside 中,也存在数据不一致的可能性。在下面的读写并发场景下,首先来自线程 1 的读请求在未命中缓存的情况下查询数据库(step 1),接着来自线程 2 的写请求更新数据库(step 2),但由于一些极端原因,线程 1 中读请求的更新缓存操作晚于线程 2 中写请求的删除缓存的操作(step 4 晚于 step 3),那么这样便会导致最终写入缓存中的是来自线程 1 的旧值,而写入数据库中的是来自线程 2 的新值,即缓存落后于数据库,此时再有读请求命中缓存(step 5),读取到的便是旧值。 这种场景的出现,不仅需要缓存失效且读写并发执行,而且还需要读请求查询数据库的执行早于写请求更新数据库,同时读请求的执行完成晚于写请求。足以见得,这种 不一致场景产生的条件非常严格,在实际的生产中出现的可能性较小 。 除此之外,在并发环境下,Cache-Aside 中也存在读请求命中缓存的时间点在写请求更新数据库之后,删除缓存之前,这样也会导致读请求查询到的缓存落后于数据库的情况。 虽然在下一次读请求中,缓存会被更新,但如果业务层面对这种情况的容忍度较低,那么可以采用加锁在写请求中保证“更新数据库&删除缓存”的串行执行为原子性操作(同理也可对读请求中缓存的更新加锁)。 加锁势必会导致吞吐量的下降,故采取加锁的方案应该对性能的损耗有所预期。 — 2 — 补偿机制 我们在上面提到了,在 Cache-Aside 中可能存在更新数据库成功,但删除缓存失败的场景,如果发生这种情况,那么便会导致缓存中的数据落后于数据库,产生数据的不一致的问题。 其实,不仅 Cache-Aside 存在这样的问题,在延时双删等策略中也存在这样的问题。针对可能出现的删除失败问题,目前业界主要有以下几种补偿机制。 1、删除重试机制 由于同步重试删除在性能上会影响吞吐量,所以常通过引入消息队列,将删除失败的缓存对应的 key 放入消息队列中,在对应的消费者中获取删除失败的 key ,异步重试删除。这种方法在实现上相对简单,但由于删除失败后的逻辑需要基于业务代码的 trigger 来触发 ,对业务代码具有一定入侵性。 鉴于上述方案对业务代码具有一定入侵性,所以需要一种更加优雅的解决方案,让缓存删除失败的补偿机制运行在背后,尽量少的耦合于业务代码。一个简单的思路是通过后台任务使用更新时间戳或者版本作为对比获取数据库的增量数据更新至缓存中,这种方式在小规模数据的场景可以起到一定作用,但其扩展性、稳定性都有所欠缺。 一个相对成熟的方案是基于 MySQL 数据库增量日志进行解析和消费,这里较为流行的是阿里巴巴开源的作为 MySQL binlog 增量获取和解析的组件 canal(类似的开源组件还有 Maxwell、Databus 等)。 canal sever 模拟 MySQL slave 的交互协议,伪装为 MySQL slave,向 MySQL master 发送 dump 协议,MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal sever ),canal sever 解析 binary log 对象(原始为 byte 流),可由 canal client 拉取进行消费,同时 canal server 也默认支持将变更记录投递到 MQ 系统中,主动推送给其他系统进行消费。 在 ack 机制的加持下,不管是推送还是拉取,都可以有效的保证数据按照预期被消费。当前版本的 canal 支持的 MQ 有 Kafka 或者 RocketMQ。另外, canal 依赖 ZooKeeper 作为分布式协调组件来实现 HA ,canal 的 HA 分为两个部分: 那么,针对缓存的删除操作便可以在 canal client 或 consumer 中编写相关业务代码来完成。这样,结合数据库日志增量解析消费的方案以及 Cache-Aside 模型,在读请求中未命中缓存时更新缓存(通常这里会涉及到复杂的业务逻辑),在写请求更新数据库后删除缓存,并基于日志增量解析来补偿数据库更新时可能的缓存删除失败问题,在绝大多数场景下,可以有效的保证缓存的最终一致性。 另外需要注意的是,还应该隔离事务与缓存,确保数据库入库后再进行缓存的删除操作。 比如考虑到数据库的主从架构,主从同步及读从写主的场景下,可能会造成读取到从库的旧数据后便更新了缓存,导致缓存落后于数据库的问题,这就要求对缓存的删除应该确保在数据库操作完成之后。所以,基于 binlog 增量日志进行数据同步的方案,可以通过选择解析从节点的 binlog,来避免主从同步下删除缓存过早的问题。 3、数据传输服务 DTS — 3 — Read-Through Read-Through 意为读穿透模式,它的流程和 Cache-Aside 类似,不同点在于 Read-Through 中多了一个访问控制层,读请求只和该访问控制层进行交互,而背后缓存命中与否的逻辑则由访问控制层与数据源进行交互,业务层的实现会更加简洁,并且对于缓存层及持久化层交互的封装程度更高,更易于移植。 — 4 — Write-Through Write-Through 意为直写模式,对于 Write-Through 直写模式来说,它也增加了访问控制层来提供更高程度的封装。不同于 Cache-Aside 的是,Write-Through 直写模式在写请求更新数据库之后,并不会删除缓存,而是更新缓存。 这种方式的 优势在于读请求过程简单 ,不需要查询数据库更新缓存等操作。但其劣势也非常明显,除了上面我们提到的更新数据库再更新缓存的弊端之外,这种方案还会造成更新效率低,并且两个写操作任何一次写失败都会造成数据不一致。 如果要使用这种方案, 最好可以将这两个操作作为事务处理,可以同时失败或者同时成功,支持回滚,并且防止并发环境下的不一致 。另外,为了防止缓存扰动的频发,也可以给缓存增加 TTL 来缓解。 站在可行性的角度,不管是 Write-Through 模式还是 Cache-Aside 模式,理想状况下都可以通过分布式事务保证缓存层数据与持久化层数据的一致性,但在实际项目中,大多都对一致性的要求存在一些宽容度,所以在方案上往往有所折衷。 Write-Through 直写模式适合写操作较多,并且对一致性要求较高的场景,在应用 Write-Through 模式时,也需要通过一定的补偿机制来解决它的问题。首先,在并发环境下,我们前面提到了先更新数据库,再更新缓存会导致缓存和数据库的不一致,那么先更新缓存,再更新数据库呢? 这样的操作时序仍然会导致下面这样线程 1 先更新缓存,最后更新数据库的情况,即由于线程 1 和 线程 2 的执行不确定性导致数据库和缓存的不一致。这种由于线程竞争导致的缓存不一致,可以通过分布式锁解决,保证对缓存和数据库的操作仅能由同一个线程完成。对于没有拿到锁的线程,一是通过锁的 timeout 时间进行控制,二是将请求暂存在消息队列中顺序消费。 在下面这种并发执行场景下,来自线程 1 的写请求更新了数据库,接着来自线程 2 的读请求命中缓存,接着线程 1 才更新缓存,这样便会导致线程 2 读取到的缓存落后于数据库。同理,先更新缓存后更新数据库在写请求和读请求并发时,也会出现类似的问题。面对这种场景,我们也可以加锁解决。 另在,在 Write-Through 模式下,不管是先更新缓存还是先更新数据库,都存在更新缓存或者更新数据库失败的情况,上面提到的重试机制和补偿机制在这里也是奏效的。 — 5 — Write-Behind Write behind 意为异步回写模式,它也具有类似 Read-Through/Write-Through 的访问控制层,不同的是,Write behind 在处理写请求时,只更新缓存而不更新数据库,对于数据库的更新,则是通过批量异步更新的方式进行的,批量写入的时间点可以选在数据库负载较低的时间进行。 在 Write-Behind 模式下,写请求延迟较低,减轻了数据库的压力,具有较好的吞吐性。但数据库和缓存的一致性较弱,比如当更新的数据还未被写入数据库时,直接从数据库中查询数据是落后于缓存的。同时,缓存的负载较大,如果缓存宕机会导致数据丢失,所以需要做好缓存的高可用。显然,Write behind 模式下适合大量写操作的场景,常用于电商秒杀场景中库存的扣减。 — 6 — Write-Around 如果一些非核心业务,对一致性的要求较弱,可以选择在 cache aside 读模式下增加一个缓存过期时间,在写请求中仅仅更新数据库,不做任何删除或更新缓存的操作,这样,缓存仅能通过过期时间失效。这种方案实现简单,但缓存中的数据和数据库数据一致性较差,往往会造成用户的体验较差,应慎重选择。 — 7 — 总结 在解决缓存一致性的过程中,有多种途径可以保证缓存的最终一致性,应该根据场景来设计合适的方案,读多写少的场景下,可以选择采用“Cache-Aside 结合消费数据库日志做补偿”的方案,写多的场景下,可以选择采用“Write-Through 结合分布式锁”的方案 ,写多的极端场景下,可以选择采用“Write-Behind”的方案。
2023-08-10 09:53:501

说一下Dubbo的工作原理?注册中心挂了可以继续通信吗?

答案是肯定可以的,我将从下面几点进行说明: 1.dubbo 的调用流程 2.Dubbo整体设计 3.从源码上说明注册中心挂了还是可以继续通信的 Dubbo 调用流程 架构图 流程说明: 1.Provider(提供者)绑定指定端口并启动服务 2.提供者连接注册中心,并发本机IP、端口、应用信息和提供服务信息发送至注册中心存储 3.Consumer(消费者),连接注册中心 ,并发送应用信息、所求服务信息至注册中心 4.注册中心根据 消费 者所求服务信息匹配对应的提供者列表发送至Consumer 应用缓存。 5.Consumer 在发起远程调用时基于缓存的消费者列表择其一发起调用。 6.Provider 状态变更会实时通知注册中心、在由注册中心实时推送至Consumer 这么设计的意义: Dubbo 整体设计 其协作流程如下: 从源码上说明注册中心挂了还是可以继续通信的 首先要把消费者注册到Zookeeper注册中心 然后使用RegistryDirectory 监听一下几个目录(会自动触发一次去获取这些目录上的当前数据) 当前所引入的服务的动态配置目录:/dubbo/config/dubbo/org.apache.dubbo.demo.DemoService:1.1.1:g1.configurators 比如监控providers 目录: 当有服务提供者注册,zookeeper会自动推动给订阅的消费者,然后转换为invoker存储到缓存中 我们在看调用时的代码: 我们看到 FailoverClusterInvoker 的doInvoke方法 Invoker invoker = select(loadbalance, invocation, copyInvokers, invoked); 此方法根据负载均衡器去缓存中获取一个invoker, 上面的 copyInvokers 就是上面我们缓存进去的 List invokers = routerChain.route(getConsumerUrl(), invocation); 总结 在我们系统启动时,已经缓存了注册中心上的所有服务,后续的注册中心挂了只会影响到后续则注册,不会影响调用! Dubbo分布式的RPC,微服务框架, 包括三个关键功能:基于接口的远程调用,容错与负载均衡,服务自动注册与发现。 Dubbo使得调用远程服务就像调用本地java服务一样简单。 参考Dubbo官方文档:包括实现细节,远程调用细节,服务提供者暴露服务。 主要流程。 1、provider向注册中心去注册 2、consumer从注册中心订阅服务,注册中心会通知consumer注册好的服务 3、consumer调用provider 4、consumer和provider都异步的通知监控中心 基于zk作为注册中心: 【提供者】在【启动】时,向注册中心zk 【注册】自己提供的服务。 【消费者】在【启动】时,向注册中心zk 【订阅】自己所需的服务。 所以是可以的,消费者在启动时,消费者会从zk拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用,消费者本地有一个生产者的列表,他会按照列表继续工作,倒是无法从注册中心去同步最新的服务列表,短期的注册中心挂掉是不要紧的,但一定要尽快修复,挂掉是不要紧的,但前提是你没有增加新的服务,如果你要调用新的服务,则是不能办到的
2023-08-10 09:53:591

学习编程都学些什么内容?

,编程就是为了借助于计算机来达到某一目的或解决某个问题,而使用某种程序设计语言编写程序代码,并最终得到结果的过程。 计算机虽然功能十分强大。
2023-08-10 09:54:104

kafka leader选举机制原理

关注《大数据技术进阶》微信公众号,及时查看更多大数据技术干活! kafka在所有broker中选出一个controller,所有Partition的Leader选举都由controller决定。controller会将Leader的改变直接通过RPC的方式(比Zookeeper Queue的方式更高效)通知需为此作出响应的Broker。同时controller也负责增删Topic以及Replica的重新分配。 1.Controller在Zookeeper注册Watch,一旦有Broker宕机(这是用宕机代表任何让系统认为其die的情景,包括但不限于机器断电,网络不可用,GC导致的Stop The World,进程crash等),其在Zookeeper对应的znode会自动被删除,Zookeeper会fire Controller注册的watch,Controller读取最新的幸存的Broker 2.Controller决定set_p,该集合包含了宕机的所有Broker上的所有Partition 3.对set_p中的每一个Partition 3.1 从/brokers/topics/[topic]/partitions/[partition]/state读取该Partition当前的ISR 3.2 决定该Partition的新Leader。如果当前ISR中有至少一个Replica还幸存,则选择其中一个作为新Leader,新的ISR则包含当前ISR中所有幸存的Replica (选举算法的实现类似于微软的PacificA) 。否则选择该Partition中任意一个幸存的Replica作为新的Leader以及ISR(该场景下可能会有潜在的数据丢失)。如果该Partition的所有Replica都宕机了,则将新的Leader设置为-1。 3.3 将新的Leader,ISR和新的leader_epoch及controller_epoch写入/brokers/topics/[topic]/partitions/[partition]/state。注意,该操作只有其version在3.1至3.3的过程中无变化时才会执行,否则跳转到3.1 4. 直接通过RPC向set_p相关的Broker发送LeaderAndISRRequest命令。Controller可以在一个RPC操作中发送多个命令从而提高效率。 1.若请求中controllerEpoch小于当前最新的controllerEpoch,则直接返回ErrorMapping.StaleControllerEpochCode。2.对于请求中partitionStateInfos中的每一个元素,即((topic, partitionId), partitionStateInfo): 2.1 若partitionStateInfo中的leader epoch大于当前ReplicManager中存储的(topic, partitionId)对应的partition的leader epoch,则: 2.1.1 若当前brokerid(或者说replica id)在partitionStateInfo中,则将该partition及partitionStateInfo存入一个名为partitionState的HashMap中 2.1.2否则说明该Broker不在该Partition分配的Replica list中,将该信息记录于log中2.2否则将相应的Error code(ErrorMapping.StaleLeaderEpochCode)存入Response中 3.筛选出partitionState中Leader与当前Broker ID相等的所有记录存入partitionsTobeLeader中,其它记录存入partitionsToBeFollower中。 4.若partitionsTobeLeader不为空,则对其执行makeLeaders方。 5.若partitionsToBeFollower不为空,则对其执行makeFollowers方法 6.若highwatermak线程还未启动,则将其启动,并将hwThreadInitialized设为true。 7.关闭所有Idle状态的Fetcher。 LeaderAndIsrRequest处理过程如下图所示 对于收到的LeaderAndIsrRequest,Broker主要通过ReplicaManager的becomeLeaderOrFollower处理,流程如下: 上文提到,在ISR中至少有一个follower时,Kafka可以确保已经commit的数据不丢失,但如果某个Partition的所有Replica都宕机了,就无法保证数据不丢失了。这种情况下有两种可行的方案: 1.等待ISR中的任一个Replica“活”过来,并且选它作为Leader 2.选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader 这就需要在可用性和一致性当中作出一个简单的折衷。如果一定要等待ISR中的Replica“活”过来,那不可用的时间就可能会相对较长。而且如果ISR中的所有Replica都无法“活”过来了,或者数据都丢失了,这个Partition将永远不可用。选择第一个“活”过来的Replica作为Leader,而这个Replica不是ISR中的Replica,那即使它并不保证已经包含了所有已commit的消息,它也会成为Leader而作为consumer的数据源(前文有说明,所有读写都由Leader完成)。Kafka0.8.*使用了第二种方式。根据Kafka的文档,在以后的版本中,Kafka支持用户通过配置选择这两种方式中的一种,从而根据不同的使用场景选择高可用性还是强一致性。 unclean.leader.election.enable 参数决定使用哪种方案,默认是true,采用第二种方案 参考:
2023-08-10 09:54:381

有没有大佬,知道java分布式怎么实现单列模式。描述一个大概的原理就OK。感谢!

首先一点,我觉得你问了一个不存在的问题,而且你问的这个问题很奇怪,根本原因是你的知识面受限!其次,如果你要想在分布式中实现类似单个虚拟机中的单例模式,你应该是要转换思路,也就是说寻找其他可行的办法来解决你遇到需要在分布式下想用单例模式来解决的问题!最后,单例模式在实际应用中,一个单例模式的对象,各方面都要只有一个的,包括对象只有一个、对象锁只有一个等等,而在分布式环境下,即多个JVM(虚拟机)中不可能能实现多个JVM共享一个对象,也没有这个必要!
2023-08-10 09:54:482

Redis哨兵机制原理浅析

上一篇文章Redis主从复制原理中简要地说明了主从复制的一个基本原理,包含全量复制、复制积压缓冲区与增量复制等内容,有兴趣的同学可以先看下。 利用主从复制,可以实现读写分离、数据备份等功能。但如果主库宕机后,需要运维人员手动地将一个从库提升为新主库,并将其他从库slaveof新主库,以此来实现故障恢复。 因此, 主从模式的一个缺点,就在于无法实现自动化地故障恢复 。Redis后来引入了哨兵机制,哨兵机制大大提升了系统的高可用性。 哨兵,就是站岗放哨的,时刻监控周围的一举一动,在第一时间发现敌情并发出及时的警报。 Redis中的哨兵(Sentinel), 则是一个特殊的Redis实例 ,不过它并不存储数据。也就是说,哨兵在启动时,不会去加载RDB文件。 关于Redis的持久化,可以参考我的另外一篇文章 谈谈Redis的持久化——AOF日志与RDB快照 上图就是一个典型的哨兵架构,由数据节点与哨兵节点构成,通常会部署多个哨兵节点。 哨兵主要具有三个作用, 监控、选主与通知 。 监控:哨兵会利用心跳机制,周期性不断地检测主库与从库的存活性 选主:哨兵检测到主库宕机后,选择一个从库将之切换为新主库 通知:哨兵会将新主库的地址通知到所有从库,使得所有从库与旧主库slaveof新主库,也会将新主库的地址通知到客户端上 我会在下文详细讲一下监控与选主的过程 哨兵系统是通过3个定时任务,来完成对主库、从库与哨兵之间的探活。 首先我们会在配置文件中配置主库地址,这样哨兵在启动后,会以 每隔10秒 的频率向主库发送info命令,从而获得当前的主从拓扑关系,这样就拿到了所有从库的地址。 接着 每隔2秒 ,会使用pub/sub(发布订阅)机制,在主库上的 sentinel :hello的频道上发布消息,消息内容包括哨兵自己的ip、port、runid与主库的配置。 每个哨兵都会订阅该频道,在该频道上发布与消费消息,从而实现哨兵之间的互相感知。 利用启动配置与info命令可以获取到主从库地址,利用发布订阅可以感知到其余的哨兵节点。 在此基础上,哨兵会 每隔1秒 向主库、从库与其他哨兵节点发送PING命令,因此来进行互相探活。 当某个哨兵在 **down-after-milliseconds(默认是30秒) **配置的连续时间内,仍然没有收到主库的正确响应,则当前哨兵会认为主库 主观下线 ,并将其标记为sdown(subjective down) 为了避免当前哨兵对主库的误判,因此这个时候还需要参考其他哨兵的意见。 接着当前哨兵会向其他哨兵发送 sentinel is-master-down-by-addr 命令, 如果有半数以上(由quorum参数决定)的哨兵认为主库确实处于主观下线状态,则当前哨兵认为主库客观下线 ,标记为odown(objective down) 一旦某个主库被认定为客观下线时,这个时候需要进行哨兵选举,选举出一个领导者哨兵,来完成主从切换的过程。 哨兵A在向其他哨兵发送 sentinel is-master-down-by-addr 命令时,同时要求其他哨兵同意将其设置为Leader,也就是想获得其他哨兵的投票。 在每一轮选举中,每个哨兵仅有一票。投票遵循先来先到的原则,如果某个哨兵没有投给别人,就会投给哨兵A。 首先获得半数以上投票的哨兵,将被选举称为Leader。 这里的哨兵选举,采用的是Raft算法。这里不对Raft做详细的探讨,有兴趣的同学,可以参考我的另外一篇文章 22张图,带你入门分布式一致性算法Raft 该文章采用大量的图例,相信你可以从中学习到全新的知识,从而打开分布式一致性算法的大门,大伙们记得等我搞完Paxos与Zab。 过半投票机制也常用于很多算法中,例如RedLock,在半数以上的节点上加锁成功,才代表申请到了分布式锁,具体可参考这篇文章的最后 我用了上万字,走了一遍Redis实现分布式锁的坎坷之路,从单机到主从再到多实例,原来会发生这么多的问题 在Zookeeper选举中,同样也用到了过半投票机制,在这篇文章中 面试官:能给我画个Zookeeper选举的图吗? 我从源码角度分析了Zookeeper选举的过程。 在选举到领导者哨兵后,将由该哨兵完成故障恢复工作。 故障恢复分为以下两步: 详细说一下第一步,挑选是有条件的。首先要过滤出不健康的节点,再按某种规则排序,最后取第一个从库,我们直接从源码入手: 因此,以下从库会被过滤出: 剩下的节点,就是健康的节点,此时再执行一次快速排序,排序的规则如下: 本文算是Redis哨兵的一个入门文章,主要讲了哨兵的作用,例如监控、选主和通知。 在Redis读写分离的情况下,使用哨兵可以很轻松地做到故障恢复,提升了整体的可用性。 但哨兵无法解决Redis单机写的瓶颈,这就需要引入集群模式,相应的文章也被列为明年的写作计划中。 </article>
2023-08-10 09:56:091

大数据技术包括哪些

什么是大数据工程师集群运维ETL系统开发阶段一:Linux基础阶段二:数据库SQL基础阶段三:java基础阶段四:Hadoop编程开发阶段五:Hive大数据分析阶段六:Hbase数据快速读写阶段七:Spark大数据分析与编程阶段八:大数据项目实战
2023-08-10 09:56:2315

JAVA 为什么不同注册中心(zookeeper,Eurake) 注册的服务不能互相调用

底层实现服务注册与发现的原理都不一样。。。你要改狠多东西才可以互相调用的。。
2023-08-10 09:57:352

Hbase扩容原理

Hbase是Hadoop的一个存储组件可以提供低延迟的读写操作,它一般构建在HDFS之上,可以处理海量的数据。Hbase有个很好的特性是可以自动分片,也就是意味着当表的数据量变得很大的时候,系统可以自动的分配这些数据。 Hbase的基本存储单位是Region,Region是表数据的子集,多个Region的数据集合可以组成一张完成的表数据。Region本质上存储的一些排好序的,连续的行数据。最初的时候一张表只有一个Region,当Region变得非常大的时候,Region就会从中间分裂成两个基本等大的Region。 在Hbase中,slave也被称作RegionServer,每个RegionServer负责管理一些Region,同时一个Region只能属于一个RegionServer。 一个RegionServer可以服务一个或多个Region,每个Region在Region Server启动的时候被分配。Master可以决定将一些Region从一个RegionServer中移动到令一个RegionServer里面,以便更好的负载均衡。当某个RegionServer故障的时候,Master也可以将它的Region分配给其他的RegionServer。 Region与RegionServer之间的映射关系存储在Zookeeper中的META表中,通过读取META表,你就可以知道那个Region可以负责处理你的rowkey操作,其实这也代表着在HBase读写操作的时候是不用经过Master节点的,你可以之间联系RegionServer。 如图,在客户端进行scan的时候,它可以之间联系多个RegionServer处理当前的操作。 Meta表是用来跟踪Region的,它包含服务器的名称,Region的名称,表名,还有Region的startkey。通过startkey的范围,客户端就可以定位到当前的key要去哪一个Region了。 客户端在请求过META表之后,一般会将表缓存起来,防止每次操作都去获取。在Region进行分裂的时候,客户端去RegionServer操作Region的时候回返回异常,然后客户端会重新获取最新的META表信息。 Hbase的Java客户端API有两个主要的接口: 通过上面介绍,可以知道HBase虽然是Master/Slave架构的,但是并不是每次操作都经过Master的,读写数据的时候HBase只需要直接联系RegionServer即可。这也是HBase可以“无限扩容”的原因。在吞吐量不够的时候,通过增加RegionServer节点,可以增加吞吐量。
2023-08-10 09:57:511

大型互联网架构概述,看完文章又涨知识了

1. 大型网站系统的特点 2. 大型网站架构演化历程 2.1. 初始阶段架构 问题:网站运营初期,访问用户少,一台服务器绰绰有余。 特征:应用程序、数据库、文件等所有的资源都在一台服务器上。 描述:通常服务器操作系统使用 linux,应用程序使用 PHP 开发,然后部署在 Apache 上,数据库使用 Mysql,通俗称为 LAMP。汇集各种免费开源软件以及一台廉价服务器就可以开始系统的发展之路了。 2.2. 应用服务和数据服务分离 问题:越来越多的用户访问导致性能越来越差,越来越多的数据导致存储空间不足,一台服务器已不足以支撑。 特征:应用服务器、数据库服务器、文件服务器分别独立部署。 描述:三台服务器对性能要求各不相同:应用服务器要处理大量业务逻辑,因此需要更快更强大的 CPU;数据库服务器需要快速磁盘检索和数据缓存,因此需要更快的硬盘和更大的内存;文件服务器需要存储大量文件,因此需要更大容量的硬盘。 2.3. 使用缓存改善性能 问题:随着用户逐渐增多,数据库压力太大导致访问延迟。 特征:由于网站访问和财富分配一样遵循二八定律:80% 的业务访问集中在 20% 的数据上。将数据库中访问较集中的少部分数据缓存在内存中,可以减少数据库的访问次数,降低数据库的访问压力。 描述:缓存分为两种:应用服务器上的本地缓存和分布式缓存服务器上的远程缓存,本地缓存访问速度更快,但缓存数据量有限,同时存在与应用程序争用内存的情况。分布式缓存可以采用集群方式,理论上可以做到不受内存容量限制的缓存服务。 2.4. 使用应用服务器集群 问题:使用缓存后,数据库访问压力得到有效缓解。但是单一应用服务器能够处理的请求连接有限,在访问高峰期,成为瓶颈。 特征:多台服务器通过负载均衡同时向外部提供服务,解决单一服务器处理能力和存储空间不足的问题。 描述:使用集群是系统解决高并发、海量数据问题的常用手段。通过向集群中追加资源,提升系统的并发处理能力,使得服务器的负载压力不再成为整个系统的瓶颈。 2.5. 数据库读写分离 问题:网站使用缓存后,使绝大部分数据读操作访问都可以不通过数据库就能完成,但是仍有一部分读操作和全部的写操作需要访问数据库,在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈。 特征:目前大部分的主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到一台服务器上。网站利用数据库的主从热备功能,实现数据库读写分离,从而改善数据库负载压力。 描述:应用服务器在写操作的时候,访问主数据库,主数据库通过主从复制机制将数据更新同步到从数据库。这样当应用服务器在读操作的时候,访问从数据库获得数据。为了便于应用程序访问读写分离后的数据库,通常在应用服务器端使用专门的数据访问模块,使数据库读写分离的对应用透明。 2.6. 反向代理和 CDN 加速 问题:中国网络环境复杂,不同地区的用户访问网站时,速度差别也极大。 特征:采用 CDN 和反向代理加快系统的静态资源访问速度。 描述:CDN 和反向代理的基本原理都是缓存,区别在于 CDN 部署在网络提供商的机房,使用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据;而反向代理则部署在网站的中心机房,当用户请求到达中心机房后,首先访问的服务器时反向代理服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户。 2.7. 分布式文件系统和分布式数据库 问题:随着大型网站业务持续增长,数据库经过读写分离,从一台服务器拆分为两台服务器,依然不能满足需求。 特征:数据库采用分布式数据库,文件系统采用分布式文件系统。 描述:分布式数据库是数据库拆分的最后方法,只有在单表数据规模非常庞大的时候才使用。不到不得已时,更常用的数据库拆分手段是业务分库,将不同的业务数据库部署在不同的物理服务器上。 2.8. 使用 NoSQL 和搜索引擎 问题:随着网站业务越来越复杂,对数据存储和检索的需求也越来越复杂。 特征:系统引入 NoSQL 数据库及搜索引擎。 描述:NoSQL 数据库及搜索引擎对可伸缩的分布式特性具有更好的支持。应用服务器通过统一数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。 2.9. 业务拆分 问题:大型网站的业务场景日益复杂,分为多个产品线。 特征:采用分而治之的手段将整个网站业务分成不同的产品线。系统上按照业务进行拆分改造,应用服务器按照业务区分进行分别部署。 描述:应用之间可以通过超链接建立关系,也可以通过消息队列进行数据分发,当然更多的还是通过访问同一个数据存储系统来构成一个关联的完整系统。 纵向拆分:将一个大应用拆分为多个小应用,如果新业务较为独立,那么就直接将其设计部署为一个独立的 Web 应用系统。纵向拆分相对较为简单,通过梳理业务,将较少相关的业务剥离即可。 横向拆分:将复用的业务拆分出来,独立部署为分布式服务,新增业务只需要调用这些分布式服务横向拆分需要识别可复用的业务,设计服务接口,规范服务依赖关系。 2.10. 分布式服务 问题:随着业务越拆越小,存储系统越来越庞大,应用系统整体复杂程度呈指数级上升,部署维护越来越困难。由于所有应用要和所有数据库系统连接,最终导致数据库连接资源不足,拒绝服务。 特征:公共业务提取出来,独立部署。由这些可复用的业务连接数据库,通过分布式服务提供共用业务服务。 3. 大型网站架构模式 3.1. 分层 大型网站架构中常采用分层结构,将软件系统分为应用层、服务层、数据层: 分层架构的约束:禁止跨层次的调用(应用层直接调用数据层)及逆向调用(数据层调用服务层,或者服务层调用应用层)。 分层结构内部还可以继续分层,如应用可以再细分为视图层和业务逻辑层;服务层也可以细分为数据接口层和逻辑处理层。 3.2. 分割 将不同的功能和服务分割开来,包装成高内聚低耦合的模块单元。这有助于软件的开发和维护,便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力。 3.3. 分布式 大于大型网站,分层和分割的一个主要目的是为了切分后的模块便于分布式部署,即将不同模块部署在不同的服务器上,通过远程调用协同工作。 分布式意味可以用更多的机器工作,那么 CPU、内存、存储资源也就更丰富,能够处理的并发访问和数据量就越大,进而能够为更多的用户提供服务。 分布式也引入了一些问题: 常用的分布式方案: 3.4. 集群 集群即多台服务器部署相同应用构成一个集群,通过负载均衡设备共同对外提供服务。 集群需要具备伸缩性和故障转移机制:伸缩性是指可以根据用户访问量向集群添加或减少机器;故障转移是指,当某台机器出现故障时,负载均衡设备或失效转移机制将请求转发到集群中的其他机器上,从而不影响用户使用。 3.5. 缓存 缓存就是将数据存放在距离最近的位置以加快处理速度。缓存是改善软件性能的第一手段。 网站应用中,缓存除了可以加快数据访问速度以外,还可以减轻后端应用和数据存储的负载压力。 常见缓存手段: 使用缓存有两个前提: 3.6. 异步 软件发展的一个重要目标和驱动力是降低软件耦合性。事物之间直接关系越少,彼此影响就越小,也就更容易独立发展。 大型网站架构中,系统解耦的手段除了分层、分割、分布式等,还有一个重要手段——异步。 业务间的消息传递不是同步调用,而是将一个业务操作拆分成多阶段,每个阶段间通过共享数据的方式异步执行进行协作。 异步架构是典型的生产者消费模式,二者不存在直接调用。异步消息队列还有如下特性: 3.7. 冗余 大型网站,出现服务器宕机是必然事件。要保证部分服务器宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份。这样当某台服务器宕机是,可以将其上的服务和数据访问转移到其他机器上。 访问和负载很小的服务也必须部署 至少两台服务器构成一个集群,目的就是通过冗余实现服务高可用。数据除了定期备份,存档保存,实现 冷备份 外;为了保证在线业务高可用,还需要对数据库进行主从分离,实时同步实现 热备份。 为了抵御地震、海啸等不可抗因素导致的网站完全瘫痪,某些大型网站会对整个数据中心进行备份,全球范围内部署 灾备数据中心。网站程序和数据实时同步到多个灾备数据中心。 3.8. 自动化 大型网站架构的自动化架构设计主要集中在发布运维方面: 3.9. 安全 4. 大型网站核心架构要素 架构 的一种通俗说法是:最高层次的规划,难以改变的决定。 4.1. 性能 性能问题无处不在,所以网站性能优化手段也十分繁多: 4.2. 可用性 可用性指部分服务器出现故障时,还能否对用户提供服务 4.3. 伸缩性 衡量伸缩的标准就是是否可以用多台服务器构建集群,是否容易向集群中增删服务器节点。增删服务器节点后是否可以提供和之前无差别的服务。集群中可容纳的总服务器数是否有限制。 4.4. 扩展性 衡量扩展性的标准就是增加新的业务产品时,是否可以实现对现有产品透明无影响,不需要任何改动或很少改动,既有功能就可以上线新产品。主要手段有:事件驱动架构和分布式服务。 4.5. 安全性 安全性保护网站不受恶意攻击,保护网站重要数据不被窃取。 欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!
2023-08-10 09:59:041

zookeeper的snapshot可以删除吗

2006年的时候Google出了Chubby来解决分布一致性的问题(distributed consensus problem),所有集群中的服务器通过Chubby最终选出一个Master Server ,最后这个Master Server来协调工作。简单来说其原理就是:在一个分布式系统中,有一组服务器在运行同样的程序,它们需要确定一个Value,以那个服务器提供的信息为主/为准,当这个服务器经过n/2+1的方式被选出来后,所有的机器上的Process都会被通知到这个服务器就是主服务器 Master服务器,大家以他提供的信息为准。很想知道Google Chubby中的奥妙,可惜人家Google不开源,自家用。但是在2009年3年以后沉默已久的Yahoo在Apache上推出了类似的产品ZooKeeper,并且在Google原有Chubby的设计思想上做了一些改进,因为ZooKeeper并不是完全遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,如图所示:ZooKeeper跟Chubby一样用来存放一些相互协作的信息(Coordination),这些信息比较小一般不会超过1M,在zookeeper中是以一种hierarchical tree的形式来存放,这些具体的Key/Value信息就store在tree node中。当有事件导致node数据,例如:变更,增加,删除时,Zookeeper就会调用 triggerWatch方法,判断当前的path来是否有对应的监听者(watcher),如果有watcher,会触发其process方法,执行process方法中的业务逻辑
2023-08-10 09:59:321

Kafka面试题

Kafka是分布式发布-订阅消息系统,它最初是由LinkedIn公司开发的,之后成为Apache项目的一部分,Kafka是一个分布式,可划分的,冗余备份的持久性的日志服务,它主要用于处理流式数据。 为什么要使用 kafka,为什么要使用消息队列 消息发送 解决方案 1.配置ack=all/-1,tries > 1,unclean.leader.election.enable = false producer发送完消息,等待follower同步完成再返回,如果异常则重试,副本数量可能影响吞吐量 不允许选举ISR的副本作为leader 2.配置min.insync.replicas>1 副本指定必须写操作成功的最小副本数量,如果不能满足这个最小值,则生产者引发一个异常(NotEnoughReplicash或者NotEnoughReplicashAfterAppend) 消费 先commit再处理消息,如果处理消息的时候异常了,但offset已经提交了,这条消息对于消费者来说丢失了 broker的刷盘 减少刷盘的间隔 kafka如何保证不重复消费又不丢失数据 1.必须要求至少一个 Follower 在 ISR 列表里。 2.第二条,每次写入数据的时候,要求 Leader 写入成功以外,至少一个 ISR 里的 Follower 也写成功。 pull模式 push模式 缺点:速率固定,忽略了consumer的消费能力,可能导致拒绝服务或者网络阻塞等情况 1. Broker注册 Broker是分布式部署并且相互之间相互独立,但是需要有一个注册系统能够将整个集群中的Broker管理起来 /brokers/ids 2. Topic注册 在Kafka中,同一个Topic的消息会被分成多个分区并将其分布在多个Broker上,这些分区信息及与Broker的对应关系也都是由Zookeeper在维护 /borkers/topics 3. 生产者负载均衡 由于同一个Topic消息会被分区并将其分布在多个Broker上,因此,生产者需要将消息合理地发送到这些分布式的Broker上,那么如何实现生产者的负载均衡,Kafka支持传统的四层负载均衡,也支持Zookeeper方式实现负载均衡。 4. 消费者负载均衡 与生产者类似,Kafka中的消费者同样需要进行负载均衡来实现多个消费者合理地从对应的Broker服务器上接收消息,每个消费者分组包含若干消费者,每条消息都只会发送给分组中的一个消费者,不同的消费者分组消费自己特定的Topic下面的消息,互不干扰。 5. 分区与消费者 的关系 在Kafka中,规定了每个消息分区 只能被同组的一个消费者进行消费,因此,需要在 Zookeeper 上记录 消息分区 与 Consumer 之间的关系,每个消费者一旦确定了对一个消息分区的消费权力,需要将其Consumer ID 写入到 Zookeeper 对应消息分区的临时节点上,例如: /consumers/[group_id]/owners/[topic]/[broker_id-partition_id] 其中,[broker_id-partition_id]就是一个 消息分区 的标识,节点内容就是该 消息分区 上 消费者的Consumer ID。 6. 消息消费进度Offset 记录 在消费者对指定消息分区进行消息消费的过程中,需要定时地将分区消息的消费进度Offset记录到Zookeeper上,以便在该消费者进行重启或者其他消费者重新接管该消息分区的消息消费后,能够从之前的进度开始继续进行消息消费。Offset在Zookeeper中由一个专门节点进行记录,其节点路径为: /consumers/[group_id]/offsets/[topic]/[broker_id-partition_id] 节点内容就是Offset的值。 7. 消费者注册 消费者服务器在初始化启动时加入消费者分组的步骤如下 注册到消费者分组。每个消费者服务器启动时,都会到Zookeeper的指定节点下创建一个属于自己的消费者节点,例如/consumers/[group_id]/ids/[consumer_id],完成节点创建后,消费者就会将自己订阅的Topic信息写入该临时节点。 Kafka不基于内存,而是硬盘存储,因此消息堆积能力更强 1.顺序写磁盘(相比磁盘的随机写快很多)。如果你是追加文件末尾按照顺序的方式来写数据的话,那么这种磁盘顺序写的性能基本上可以跟写内存的性能本身也是差不多的。 2.利用Page Cache(页高速缓冲存储器,简称页高缓)空中接力的方式来实现高效读写,操作系统本身有一层缓存,叫做page cache,是在内存里的缓存,我们也可以称之为os cache,意思就是操作系统自己管理的缓存。原理就是Page Cache可以把磁盘中的数据缓存到内存中,把对磁盘的访问改为对内存的访问。 3.零拷贝 零拷贝技术是一种避免CPU将数据从一块存储拷贝到另一块存储的技术。Kafka使用零拷贝技术将数据直接从磁盘复制到网卡设备缓冲区中,而不需要经过应用程序的转发。 通常应用程序将磁盘上的数据传送至网卡需要经过4步: -调用read(),将数据从磁盘复制到内核模式的缓冲区; -CPU会将数据从内核模式复制到用户模式下的缓冲区; -调用write(),将数据从用户模式下复制到内核模式下的Socket缓冲区; -将数据从内核模式的Socket缓冲区复制到网卡设备。 上面的步骤中,第2、3步将数据从内核模式经过用户模式再绕回内核模式,浪费了两次复制过程。采用零拷贝技术,Kafka可以直接请求内核把磁盘中的数据复制到Socket缓冲区,而不用再经过用户模式 Rebalance 本质上是一种协议,规定了一个 Consumer Group 下的所有consumer如何达成一致,来分配订阅 Topic 的每个分区。 Rebalance 的触发条件有3个 Rebalance 发生时,Group 下所有 consumer 实例都会协调在一起共同参与,kafka 能够保证尽量达到最公平的分配。但是 Rebalance 过程对 consumer group 会造成比较严重的影响。在 Rebalance 的过程中 consumer group 下的所有消费者实例都会停止工作,等待 Rebalance 过程完成。 GroupCoordinator(协调者):协调消费者组完成消费者Rebalance的重要组件,每一个broker都会启动一个GroupCoodinator,Kafka 按照消费者组的名称将其分配给对应的GroupCoodinator进行管理;每一个GroupCoodinator只负责管理一部分消费者组,而非集群中全部的消费者组。通常是partition的leader节点的broker 如果C1消费消息超时,出入rebalance,重新分配后该消息被其他消费者消费,此时C1消费完成提交offset,导致错误 解决:Coordinator每次进行rebalance,会标记一个generation给consumer,每次rebalance该generation会+1,consumer提交offset时,会对比generation,不一致则拒绝提交。 ISR :In-Sync Replicas 副本同步队列 AR :Assigned Replicas 所有副本 ISR是由leader维护,follower从leader同步数据有一些延迟(包括延迟时间replica.lag.time.max.ms和延迟条数replica.lag.max.messages两个维度, 当前最新的版本0.10.x中只支持replica.lag.time.max.ms这个维度),任意一个超过阈值都会把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也会先存放在OSR中。AR=ISR+OSR。 在 Kafka 中,每个 主题分区下的每条消息都被赋予了一个唯一的 ID 数值,用于标识它在分区中的位置。这个 ID 数值,就被称为位移,或者叫偏移量。一旦消息被写入到分区日志,它的位移值将不能被修改。 auto.offset.reset:消费规则,默认earliest 。 earliest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 latest: 当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 none: topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常 Kafka 副本当前分为领导者副本和追随者副本。只有Leader副本才能 对外提供读写服务,响应Clients端的请求。Follower 副本只是采用拉(PULL)的方 式,被动地同步Leader副本中的数据,并且在Leader副本所在的 Broker 宕机后,随时准备应聘 Leader 副本。 kafka在所有broker中选出一个controller,所有Partition的Leader选举都由controller决定。controller会将Leader的改变直接通过RPC的方式(比Zookeeper Queue的方式更高效)通知需为此作出响应的Broker。同时controller也负责增删Topic以及Replica的重新分配。 分区的 Leader 副本选举对用户是完全透明的,它是由 Controller 独立完成的。你需要回答的是,在哪些场景下,需要执行分区 Leader 选举。每一种场景对应于一种选举策略。当前,Kafka 有 4 种分区 Leader 选举策略。 集群 partition 备份 Kafka 支持设置针对每个 partition 备份,可以将 partition 备份到不同的 broker 上,其中 leader partition 负责读写,其他 follower 仅负责同步,当 leader 挂掉后会从 follower 中选取新的 leader 。 消息消费顺序 一个 partition 同一时刻在一个 consumer group 中只能有一个 consumer 实例在消费,从而保证了消费顺序。consumer group 中的 consumer 实例的数量不能比一个 topic 中的 partition 的数量多,否则,多出来的 consumer 无法消费到消息。Kafka 的消息在单个 partition 上是可以保证顺序的,但是在整体上无法保证顺序消费 消息消费模式 关于消费模式,Kafka 通过 消费组的概念可以灵活设置。如常见的 队列模式 即 所有的 consumer 在同一个 consumer group 下。发布订阅模式 则设置多个 consumer group 进行消费即可 acks:消息的确认机制,默认值是0。 acks=0:如果设置为0,生产者不会等待kafka的响应。 acks=1:这个配置意味着kafka会把这条消息写到本地日志文件中,但是不会等待集群中其他机器的成功响应。 acks=all:这个配置意味着leader会等待所有的follower同步完成。这个确保消息不会丢失,除非kafka集群中所有机器挂掉。这是最强的可用性保证。
2023-08-10 09:59:551

大数据学习难吗?

大数据学习只能说不轻松,Java语言是大数据学习的基础,你有Java的基础,那么你学习起来就会很轻松。
2023-08-10 10:00:064

求java学习路线图?

xml2、JAVA SE3、JAVA EE,包括Servlet、JSP、框架至于数据库的学习,在JAVA之前,之中,之后都可以,建议在JAVA之前,至少在JAVA EE之前。
2023-08-10 10:00:341

什么是 flume 日志收集,flume的原理是什么,flume会遇到什么问题

、Flume介绍Flume是一个分布式、可靠、和高可用的海量日志聚合的系统,支持在系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力。flume可以搜集数据,合并数据。合并到什么地方,可以是hdfs。也就是flume可以与hadoop相结合复制代码设计目标:(1) 可靠性当节点出现故障时,日志能够被传送到其他节点上而不会丢失。Flume提供了三种级别的可靠性保障,从强到弱依次分别为:end-to-end(收到数据agent首先将event写到磁盘上,当数据传送成功后,再删除;如果数据发送失败,可以重新发送。),Store on failure(这也是scribe采用的策略,当数据接收方crash时,将数据写到本地,待恢复后,继续发送),Best effort(数据发送到接收方后,不会进行确认)。(2) 可扩展性采用了三层架构,分别为agent,collector和storage,每一层均可以水平扩展。其中,所有agent和collector由master统一管理,这使得系统容易监控和维护,且master允许有多个(使用ZooKeeper进行管理和负载均衡),这就避免了单点故障问题。(3) 可管理性所有agent和colletor由master统一管理,这使得系统便于维护。多master情况,Flume利用ZooKeeper和gossip,保证动态配置数据的一致性。用户可以在master上查看各个数据源或者数据流执行情况,且可以对各个数据源配置和动态加载。Flume提供了web 和shell script command两种形式对数据流进行管理。(4) 功能可扩展性
2023-08-10 10:01:481

大数据时代需要学习什么技术?

大数据技术的学习内容有很多,包括:基础阶段:Linux、Docker、KVM、MySQL基础、Oracle基础、MongoDB、redis。hadoop mapreduce hdfs yarn:hadoop:Hadoop 概念、版本、历史,HDFS工作原理,YARN介绍及组件介绍。大数据存储阶段:hbase、hive、sqoop。大数据架构设计阶段:Flume分布式、Zookeeper、Kafka。大数据实时计算阶段:Mahout、Spark、storm。大数据数据采集阶段:Python、Scala。大数据商业实战阶段:实操企业大数据处理业务场景,分析需求、解决方案实施,综合技术实战应用。
2023-08-10 10:02:004