1、Zookeeper—分布式应用程序协调服务
1.1 构架
Zookeeper主要提供以下四点功能:统一命名服务、配置管理(数据发布与订阅)、集群管理(分布式协调/通知)、共享锁和队列管理,用于高效的管理集群的运行。
- 统一命名服务:命名服务指通过指定的名字获取资源或者服务提供者的信息。分布式应用中,通常需要有一套完整的命名规则,使用树形的名称结构能够产生唯一的名称又便于识别和记忆。
- 配置管理:配置的管理包含发布和订阅两个过程,顾名思义就是将数据发布到ZK节点上,供订阅者动态获取数据,实现配置信息的集中管理和动态更新。
- 集群管理:主要是集群监控和Leader选举。
1.2 几种实际运用场景
场景一:有一组服务器向客户端提供某种服务(例如:我前面做的分布式网站的服务端,就是由四台服务器组成的集群,向前端集群提供服务),我们希望客户端每次请求服务端都可以找到服务端集群中某一台服务器,这样服务端就可以向客户端提供客户端所需的服务。对于这种场景,我们的程序中一定有一份这组服务器的列表,每次客户端请求时候,都是从这份列表里读取这份服务器列表。那么这分列表显然不能存储在一台单节点的服务器上,否则这个节点挂掉了,整个集群都会发生故障,我们希望这份列表时高可用的。高可用的解决方案是:这份列表是分布式存储的,它是由存储这份列表的服务器共同管理的,如果存储列表里的某台服务器坏掉了,其他服务器马上可以替代坏掉的服务器,并且可以把坏掉的服务器从列表里删除掉,让故障服务器退出整个集群的运行,而这一切的操作又不会由故障的服务器来操作,而是集群里正常的服务器来完成。这是一种主动的分布式数据结构,能够在外部情况发生变化时候主动修改数据项状态的数据机构。Zookeeper框架提供了这种服务。这种服务名字就是:统一命名服务,它和javaEE里的JNDI服务很像。
场景二:分布式锁服务。当分布式系统操作数据,例如:读取数据、分析数据、最后修改数据。在分布式系统里这些操作可能会分散到集群里不同的节点上,那么这时候就存在数据操作过程中一致性的问题,如果不一致,我们将会得到一个错误的运算结果,在单一进程的程序里,一致性的问题很好解决,但是到了分布式系统就比较困难,因为分布式系统里不同服务器的运算都是在独立的进程里,运算的中间结果和过程还要通过网络进行传递,那么想做到数据操作一致性要困难的多。Zookeeper提供了一个锁服务解决了这样的问题,能让我们在做分布式数据运算时候,保证数据操作的一致性。
场景三:配置管理。在分布式系统里,我们会把一个服务应用分别部署到n台服务器上,这些服务器的配置文件是相同的(例如:我设计的分布式网站框架里,服务端就有4台服务器,4台服务器上的程序都是一样,配置文件都是一样),如果配置文件的配置选项发生变化,那么我们就得一个个去改这些配置文件,如果我们需要改的服务器比较少,这些操作还不是太麻烦,如果我们分布式的服务器特别多,比如某些大型互联网公司的hadoop集群有数千台服务器,那么更改配置选项就是一件麻烦而且危险的事情。这时候zookeeper就可以派上用场了,我们可以把zookeeper当成一个高可用的配置存储器,把这样的事情交给zookeeper进行管理,我们将集群的配置文件拷贝到zookeeper的文件系统的某个节点上,然后用zookeeper监控所有分布式系统里配置文件的状态,一旦发现有配置文件发生了变化,每台服务器都会收到zookeeper的通知,让每台服务器同步zookeeper里的配置文件,zookeeper服务也会保证同步操作原子性,确保每个服务器的配置文件都能被正确的更新。
场景四:为分布式系统提供故障修复的功能。集群管理是很困难的,在分布式系统里加入了zookeeper服务,能让我们很容易的对集群进行管理。集群管理最麻烦的事情就是节点故障管理,zookeeper可以让集群选出一个健康的节点作为master,master节点会知道当前集群的每台服务器的运行状况,一旦某个节点发生故障,master会把这个情况通知给集群其他服务器,从而重新分配不同节点的计算任务。Zookeeper不仅可以发现故障,也会对有故障的服务器进行甄别,看故障服务器是什么样的故障,如果该故障可以修复,zookeeper可以自动修复或者告诉系统管理员错误的原因让管理员迅速定位问题,修复节点的故障。大家也许还会有个疑问,master故障了,那怎么办了?zookeeper也考虑到了这点,zookeeper内部有一个“选举领导者的算法”,master可以动态选择,当master故障时候,zookeeper能马上选出新的master对集群进行管理。
1.3 安装及配置
下载zookeeper的包到linux下:
(1):wget wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz ;
(2):解压到当前目录,tar -zxvf zookeeper-3.4.6.tar.gz
(3):在/usr/local/ 目录下新建目录 mkdir zookeeper-cluster目录
(4):将解压的zookeeper移动到刚刚新建的目录下mv zookeeper-3.4.6 /usr/local/zookeeper-cluster/zookeeper-3.4.6-node1下。
注:下面的zookeeper-3.4.6-node1,zookeeper-3.4.6-node2,zookeeper-3.4.6-node3,在文字中简写为node1,node2,node3
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper-cluster/zookeeper-3.4.6-node2/data ###不同点
clientPort=2182 ###不同点
server.1=localhost:2887:3887
server.2=localhost:2888:3888
server.3=localhost:2889:3889
1.4 大型分布式系统中的应用
1.4.1 Hadoop中的应用
ZooKeeper主要用于实现HA(Hive Availability),包括HDFS的NamaNode和YARN(MapReduce)的ResourceManager的HA.
YARN主要由ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)和Container四部分组成。其中最核心的就是ResourceManager.
为了实现HA,必须有多个ResourceManager并存(一般就两个),并且只有一个ResourceManager处于Active状态,其他的则处于Standby状态,当Active节点无法正常工作(如机器宕机或重启)时,处于Standby的就会通过竞争选举产生新的Active节点。
1.4.2 HBase中的应用
HBase主要用ZooKeeper来实现HMaster选举与主备切换、系统容错、RootRegion管理、Region状态管理和分布式SplitWAL任务管理等。http://blog.jobbole.com/110388/
1.5 核心-Leader选举
Leader选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。
(1) 服务器初始化启动。
(2) 服务器运行期间无法和Leader保持连接。
- 每个Server发出一个投票。由于是初始情况,都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示。
- 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器
- 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下:1)优先检查ZXID。ZXID比较大的服务器优先作为Leader,2) 如果ZXID相同,那么就比较myid。myid较大的服务器作为Leader服务器
- 统计投票。半数通过
- 改变服务器状态。
服务器具有四种状态,分别是LOOKING、FOLLOWING、LEADING、OBSERVING。
LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。
FOLLOWING:跟随者状态。表明当前服务器角色是Follower。
LEADING:领导者状态。表明当前服务器角色是Leader。
OBSERVING:观察者状态。表明当前服务器角色是Observer。
投票(Vote)在Zookeeper中包含字段:
id:被推举的Leader的SID
zxid:被推举的Leader事务ID
electionEpoch:逻辑时钟,用来判断多个投票是否在同一轮选举周期中
peerEpoch:被推举的Leader的epoch
state:当前服务器的状态
2、HDFS-分布式文件系统(Hadoop Distributed File System)
2.1 初识
Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
HDFS集群是由一个中心节点(NameNode)和多个数据节点(DataNode)组成的,中心节点负责管理整个集群,如果中心节点瘫痪那么整个集群就无法使用,上面我们给出设置备份中心节点的解决办法,但是为了进一步确保稳定性通常会选用一台高性能配置好的服务器作为中心节点。
- 数据文件大的文件切块分散存储:HDFS将数据以Block块存储,每一个Block块在搭建HDFS的时候可以被设置,如果数据文件大到超出了Block块设定的大小,就会将这个文件按Block块大小切分为多个文件块存储在HDFS中。
- 元数据和数据分开存储:HDFS的寻找文件地址通过从Root中找到元数据,再从Meta找到文件存储的服务器和地址。其中NameNode主要管理存放到DataNode中数据的元数据。
- 一次写入多次读取:HDFS中存储的文件只允许一次写入,写入之后就不能被修改,如有修改只能在文件中追加数据。
- 移动计算比移动数据更划算:分布式系统计算过程中距离数据越近,计算性能越好,尤其是在数据量特别大的时候。移动计算却是非常划算,将计算的方法分发给集群中DataNode节点负责数据计算,DataNode节点将计算结果回传给中心节点,中心节点负责将回传的结果汇总成结果。
读取与写入:
3、HBase-Hadoop Database分布式存储系统
3.1 初识
Hbase是分布式、面向列的开源数据库(其实准确的说是面向列族)。HDFS为Hbase提供可靠的底层数据存储服务,MapReduce为Hbase提供高性能的计算能力,Zookeeper为Hbase提供稳定服务和Failover机制,因此我们说Hbase是一个通过大量廉价的机器解决海量数据的高速存储和读取的分布式数据库解决方案。
B+树原理:B+树是一种树数据结构,是一个n叉树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点。B+树查找通过父节点->子节点->...->叶子节点,这样执行查询效率非常高。
- HBase中存储了一套HDFS的索引,通过表名->行健->列族->列限定符->时间版本这一套索引来定位数据的位置。HBase通常以集群部署,数据被分散到多个节点存储,当客户端发起查询请求的时候,集群里面多个节点并行执行查询操作,最后将不同节点的查询结果进行合并返回给客户端。
- Base通常采用集群模式,大量的索引文件被切分为很多块(block)分散存放在不同的节点上面,这些块(block)存放在HDFS上面,由于HDFS的数据冗余机制,当存放块的某一个节点宕机,HBase可以从其他节点取出宕机机器存储的数据,这样可以保证这些数据的高可用性,而且当集群数量越大高可用性越高。
- HBase将数据以HFile文件形式存储,这些文件在磁盘上面连续存储,由于磁盘的磁头不需要尽心大量的寻址操作,HBase在进行数据写入和数据加载的时候可以很快速将某一列族数据加载到内存中。
- HBase是一个无模式的数据库。HBase不同于传统的关系型数据库,使用HBase不需要预先定义表中有多少列,也不需要定义每一列存储的数据类型,HBase在需要的时候可以动态增加列和指定存储数据类型。对于从不同数据源爬取的数据不一致,可以动态的新增列而不需要预先就设计好存储的表结构,以应对数据结构多种多样的情况。
3.2 架构
1. Client:包含了访问Hbase的接口,另外Client还维护了对应的cache来加速Hbase的访问;
2. Zookeeper:Hbase通过Zookeeper来做master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作;
3. Hmaster:为RegionServer分配Region、维护整个集群的负载均衡、维护集群的元数据信息、发现失效的Region,并将失效的Region分配到正常的RegionServer上、当RegionSever失效的时候,协调对应Hlog的拆分;
4. HregionServer:直接对接用户的读写请求。管理master为其分配的Region、处理来自客户端的读写请求、负责和底层HDFS的交互,存储数据到HDFS、负责Region变大以后的拆分、负责Storefile的合并工作;
5. HDFS:为Hbase提供最终的底层数据存储服务,提供元数据和表数据的底层分布式存储服务,数据多副本,保证的高可靠和高可用性;
4、Dubbo-分布式服务框架
4.1 初识
maven引用:(推荐的注册中心为zookeeper)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
5、Kafka-分布式发布订阅消息系统
5.1 初识
kafka 是一个分布式的消息队列,也是一个分布式的发布-订阅系统,有两种类型的消息模式可用 - 一种是点对点,另一种是发布 - 订阅(pub-sub)消息系统;
Zookeeper是Kafka代理和消费者之间的协调接口。 Kafka服务器通过Zookeeper集群共享信息。 Kafka在Zookeeper中存储基本元数据,例如关于主题,代理,消费者偏移(队列读取器)等的信息。
Kafka主要设计目标如下:
1、以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能。
2、高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输。
3、支持Kafka Server间的消息分区,及分布式消费,同时保证每个partition内的消息顺序传输。
4、同时支持离线数据处理和实时数据处理。
kafka集群
一个典型的kafka集群中包含若干producer,若干broker,若干consumer,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在consumer group发生变化时进行rebalance。producer使用push模式将消息发布到broker,consumer使用pull模式从broker订阅并消费消息。
Kafka专用术语:
Broker:消息中间件处理结点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群。
Topic:一类消息,Kafka集群能够同时负责多个topic的分发。
Partition:topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队列。
Segment:partition物理上由多个segment组成。
offset:每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息都有一个连续的序列号叫做offset,用于partition唯一标识一条消息。
Producer:负责发布消息到Kafka broker。
Consumer:消息消费者,向Kafka broker读取消息的客户端。
Consumer Group:每个Consumer属于一个特定的Consumer Group。
5.2 工作流程
发布 - 订阅消息的工作流程:
- 生产者定期向主题发送消息;
- Kafka代理存储为该特定主题配置的分区中的所有消息。它确保消息在分区之间平等共享。 如果生产者发送两个消息并且有两个分区,Kafka将在第一分区中存储一个消息,在第二分区中存储第二消息;
- 消费者订阅特定主题;
- 一旦消费者订阅主题,Kafka将向消费者提供主题的当前偏移,并且还将偏移保存在Zookeeper系综中;
- 消费者将定期请求Kafka(如100 Ms)新消息;
- 一旦Kafka收到来自生产者的消息,它将这些消息转发给消费者;
- 消费者将收到消息并进行处理;
- 一旦消息被处理,消费者将向Kafka代理发送确认;
- 一旦Kafka收到确认,它将偏移更改为新值,并在Zookeeper中更新它。 由于偏移在Zookeeper中维护,消费者可以正确地读取下一封邮件,即使在服务器暴力期间;
- 以上流程将重复,直到消费者停止请求。
- 消费者可以随时回退/跳到所需的主题偏移量,并阅读所有后续消息。
安装步骤:
(1)先安装jdk,zookeeper
(2)启动ZooKeeper服务器 $ bin/zkServer.sh start
(3)启动CLI $ bin/zkCli.sh
(4)下载kafka,https://www.apache.org/dyn/closer.cgi?path=/kafka/0.9.0.0/kafka_2.11-0.9.0.0.tgz
(5)解压tar文件
(6)启动kafka服务器,$ bin/kafka-server-start.sh config/server.properties