-
2020-01-16 12:29:36
HBase伪分布式模式
1)HBase使用HDFS存储数据,所有进程运行在同一个节点上,不同的HBase或ZooKeeper守护进程运行在不同的JVM(Java Virtual Machine)中2)使用HBase内置的ZooKeeper
3)比较适用于在硬件配置一般的用于开发的计算机上运行,适用于HBase的开发和测试环境实验前提:HBase伪分布式部署依赖于Hadoop伪分布式部署,本实验紧接Hadoop伪分布式实验,在Hadoop伪分布式部署完成并运行成功的基础上,继续进行Hbase伪分布式部署实验
实验目标:在单台Linux虚拟机主机上部署伪分布式数据库HBase ,用于教学演示
实验环境: 虚拟机VirtualBox 操作系统 Centos7 Hadoop版本 hadoop-2.6.0-cdh5.7.0 Hbase版本 hbase-1.2.0-cdh5.7.0.tar.gz 由于HBase依赖于HDFS,所以选择安装包版本时必须注意HBase和Hadoop的版本兼容性,官方发布的HBase各版本对JDK和Hadoop各版本的支持情况参考(版本兼容性):https://blog.csdn.net/e_wsq/article/details/81365029
集群规划: 无需复制虚拟机,直接利用Hadoop伪分布式的单台主机hadoop完成Hbase伪分布式部署主机IP 主机名 集群角色(进程名称) 192.168.56.20 hadoop NameNode DataNode SecondaryNameNode
HMaster HRegionServer
HQuorumPeer(HBase自带的ZooKeeper进程)〇 首先要部署完成并运行成功Hadoop伪分布式集群
1)启动伪分布式集群中的单台主机hadoop
2)在win7用XSHELL远程登录Linux,注意VirtualBox主机网络管理器的虚拟网卡IP(192.168.56.1)地址和虚拟机Linux处于一个网段
3)上传HBase安装包到Linux的/root目录,解压缩hbase-1.2.0-cdh5.7.0.tar.gz安装包到指定目录/usr/local
tar -zxvf /root/hbase-1.2.0-cdh5.7.0.tar.gz -C /usr/local/ 解压缩到/usr/local目录
4)设置HBase环境变量并使之生效
vi /etc/profile 在配置文件profile的末尾增加以下内容:
# hbase
export HBASE_HOME=/usr/local/hbase-1.2.0-cdh5.7.0
export PATH=$PATH:$HBASE_HOME/bin执行source /etc/profile命令使得HBase环境变量生效
5)关闭防火墙firewall和SeLinux
执行关闭防火墙命令 systemctl disable firewalld 执行关闭SeLinux命令 setenforce 0
6)检查hadoop主机到自己的SSH免密登录(特别重要)
执行ssh hadoop命令,检查免密登录是否成功,免密登录成功后,必须输入exit退出并返回原会话,以免搞混
7)修改HBase的配置文件(关键步骤)
cd /usr/local/hbase-1.2.0-cdh5.7.0/conf 切换到HBase的配置文件所在目录
a)先修改配置文件hbase-env.sh
vi hbase-env.sh 修改以下配置参数:
export JAVA_HOME=/usr/local/java/jdk1.8
export HBASE_MANAGES_ZK=true # 使用HBase内置的Zookeeper!!!
执行source hbase-env.sh命令使得HBase配置参数生效
b)修改配置文件hbase-site.xml
vi hbase-site.xml修改以下参数:
在<configuration> </configuration>之间增加蓝色字体配置参数
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop:8020/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/root/hbase/zookeeper</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property><property>
<name>hbase.zookeeper.quorum</name>
<value>hadoop</value>
</property>
</configuration>参数说明:
hbase.cluster.distributed:HBase群集的模式,对于单机模式值为false,对于伪分布式和完全分布式模式值为true。如果为false,将在同一个JVM中运行所有HBase和ZooKeeper守护进程
hbase.rootdir:用于指定HBase数据在HDFS的存储路径
hbase.zookeeper.property.dataDir:用于指定HBase自带的ZooKeeper存储数据的本地路径
c)修改regionservers文件
vi regionservers
删除原有行,新添加一行:
hadoop
8)创建ZooKeeper存放数据的目录
cd /root 切换到root目录
执行命令mkdir -p /root/hbase/zookeeper 在root目录下创建两级子目录hbase/zookeeper
路径/root/hbase/zookeeper和hbase-site.xml文件中的hbase.zookeeper.property.dataDir参数值相同
注意:经过实际测试发现,以上三级子目录zookeeper 可以不事先创建,只需要在/root目录下执行mkdir hbase命令创建二级子目录hbase即可,启动HBase时会自动创建三级子目录zookeeper
9)启动HDFS
执行start-dfs.sh脚本命令启动HDFS
10)启动HBase
执行start-hbase.sh脚本命令启动HBase
11)执行java进程查看命令jps,hadoop主机出现以下进程,说明HDFS,HBase自带的ZooKeeper以及HBase都已启动成功:
[root@hadoop ~]# jps
3985 Jps
3075 HRegionServer
2276 DataNode
2184 NameNode
2936 HMaster
2860 HQuorumPeer
2462 SecondaryNameNode12)在win7下,用chrome浏览器访问HBase自带的web配置网站 http://192.168.56.20:60010 ,能出现如下页面说明访问成功:
14)测试一下HBase是否成功连接HDFS
测试方法:如果HBase成功连接HDFS,会在HDFS上创建目录路径/hbase
执行hadoop fs -ls /命令,检查HDFS根目录下是否存在hbase子目录
15)执行命令hbase shell进入hbase的shell命令行环境
16)HBase Shell命令的简单测试
执行命令create 'testTable', 'testFamily' 创建一张表testTable,包含一个列族testFamily
执行命令list 列出HBase中的所有表
执行命令describe 'testTable' 描述表testTable的属性信息
更多相关内容 -
大数据技术基础实验报告-Zookeeper的安装配置和应用实践.doc
2021-08-21 08:57:48大数据技术基础实验报告-Zookeeper的安装配置和应用实践 -
部署全分布模式Hadoop集群 实验报告
2022-04-18 14:25:27部署全分布模式Hadoop集群 实验报告一、实验目的 1. 熟练掌握 Linux 基本命令。 2. 掌握静态 IP 地址的配置、主机名和域名映射的修改。 3. 掌握 Linux 环境下 Java 的安装、环境变量的配置、Java 基本命令的使用。 ... -
ZooKeeper(分布式协调服务)使用介绍
2021-11-08 21:05:22ZooKeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护...ZooKeeper 可以用于实现分布式系统中常见的发布/订阅、负载均衡、命令服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。ZooKeeper(分布式协调服务)使用介绍
一、ZooKeeper 简介
ZooKeeper 是一个开源的分布式协调服务,目前由 Apache 进行维护。ZooKeeper 可以用于实现分布式系统中常见的发布/订阅、负载均衡、命令服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。 它具有以下特性:
- 顺序一致性: 来自客户端的更新操作将会按照顺序被应用;
- 原子性: 即要么全部更新成功,要么要不更新失败,没有部分的结果;
- 统一的系统镜像: 即不管客户端连接的是哪台服务器,都能看到同样的服务视图(也就是无状态的)
- 可靠性: 一旦写入操作被执行,那么这个状态将会被持久化,直到其它客户端的修改生效。
- 实时性: 一旦一个事务被成功应用,ZooKeeper 可以保证客户端立即读取到这个事务变更后的最新状态的数据。
1.ZooKeeper 设计目标
- ZooKeeper 致力于为那些高吞吐的大型分布式系统提供一个高性能、高可用、且具有严格顺序访问控制能力的分布式协调服务。
1)简单的数据模型:
- ZooKeeper 通过树形结构来存储数据,它由一系列被称为 ZNode 的数据节点组成,类似于常见的文件系统;
- 不过和常见的文件系统不同,ZooKeeper 将数据全量存储在内存中,以此来实现高吞吐,减少访问延迟。
2)可配置 Cluster:
- 为了保证高可用,最好是以集群形态部署 ZooKeeper,这样只要集群中大部分机器是可用的,那么 ZooKeeper 本身仍然可用。
上图中每一个 Server 代表一个安装 ZooKeeper 服务的服务器,组成 ZooKeeper 服务的服务器都会在内存中维护当前的服务器状态,并且每台服务器间都保持着通信。并通过Zab
协议来保持数据的一致性。3)顺序访问:
- 对于来自客户端的每个更新请求,ZooKeeper 都会分配一个全局唯一的递增 ID,这个 ID 决定了所有事务操作的先后顺序。
4)高性能高可用
- ZooKeeper 将数据全量存储在内存中以保持高性能,并通过服务集群来实现高可用;
- 由于 ZooKeeper 的所有更新和删除都是基于事务的,所以其在读多写少的应用场景中有着很高的性能表现。
2.核心概念
Cluster 角色:
角色 作用 Leader
提供读写服务,并维护集群状态(经过选举产生) Follower
提供读写服务,并定期向 Leader 汇报自己的节点状态(同时也参加 过半写成功 的策略和 Leader 的选举) OBServer
提供读写服务,并定期向 Leader 汇报自己的节点状态(因为不参加策略和选举,所以可以在不影响写性能的情况下提升集群的读性能) 1)Session 会话
当 Client 通过 TCP 长连接 连接到 ZooKeeper 服务器时,Session 便开始建立连接,并通过
tickTime
(心跳检测)机制来保持有效的会话状态。通过这个连接,Client 可以发送请求并接收响应,同时也可以接收到 Watch 事件的通知。另外,当由于网络故障或者 Client 主动断开等原因,导致连接断开,此时只要在会话超时时间之内重新建立连接,则之间创建的会话依然有效。(这个取决于
tickTime
配置)2)数据节点
ZooKeeper 数据模型是由一系列基本数据单元 ZNode(数据节点)组成的节点树,其中根节点为
/
(每个节点上都会保存自己的数据和节点信息);ZooKeeper 中的节点可以分为两大类:- 持久节点: 节点一旦创建,除非被主动删除,否则一直存在。
- 临时节点: 一旦创建该节点的客户端会话(Session)失效,则所有该客户端创建的临时节点都会被删除。
3)Watcher
ZooKeeper 中一个常用的功能是 Watcher(事件监听器),它允许用户在指定节点上针对感兴趣的事件注册监听,当事件发生时,监听器会被触发,并将事件推送到客户端。该机制是 ZooKeeper 实现分布式协调服务的重要特性。
4)ACL
ZooKeeper 采用 ACL(Access Control Lists)策略来进行权限控制,类似于 Unix 文件系统的控制权限:
命令 作用 create
可以进行创建操作 read
可以进行查看操作 write
可以对创建的内容进行写入操作 delete
可以进行删除操作 admin
可以进行配置权限操作 3.Zab 协议介绍
- Zab(
ZooKeeper Atomic Broadcast
原子广播)协议是为分布式协调服务 ZooKeeper 专门设计的一种 支持崩溃恢复的原子广播协议; - 在 ZooKeeper 中,主要依赖 Zab 协议来实现分布式数据一致性;
- 基于 Zab 协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本间的数据一致性。
二、ZooKeeper Cluster 安装
准备工作:
主机名 操作系统 IP 地址 ZooKeeper CentOS 7.4 192.168.1.1 安装 JDK:下载地址(需要创建 Oracle 账号) [root@ZooKeeper ~]# ls anaconda-ks.cfg jdk-8u181-linux-x64.tar.gz [root@ZooKeeper ~]# tar zxf jdk-8u181-linux-x64.tar.gz [root@ZooKeeper ~]# ls anaconda-ks.cfg jdk1.8.0_181 jdk-8u181-linux-x64.tar.gz [root@ZooKeeper ~]# mv jdk1.8.0_181 /usr/local/java [root@ZooKeeper ~]# cat <<"END" >> /etc/profile export JAVA_HOME=/usr/local/java export PATH=$PATH:$JAVA_HOME/bin END [root@ZooKeeper ~]# source /etc/profile [root@ZooKeeper ~]# java -version
1.安装 ZooKeeper
[root@ZooKeeper ~]# wget http://dlcdn.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz [root@ZooKeeper ~]# ls anaconda-ks.cfg apache-zookeeper-3.6.3-bin.tar.gz jdk-8u181-linux-x64.tar.gz [root@ZooKeeper ~]# tar zxf apache-zookeeper-3.6.3-bin.tar.gz [root@ZooKeeper ~]# mv apache-zookeeper-3.6.3-bin /usr/local/zookeeper [root@ZooKeeper ~]# mkdir /usr/local/zookeeper/data [root@ZooKeeper ~]# cat <<END >> /usr/local/zookeeper/conf/zoo.cfg tickTime=2000 initLimit=10 syncLimit=5 dataDir=/usr/local/zookeeper/data clientPort=2181 END
注解:
tickTime
:Client 和服务器间的通信会话限制(相当于健康检查,tickTime
的时间为ms (1s = 1000ms)
)initLimit
:Leader 和 Follower 间初始通信限制。syncLimit
:Leader 和 Follower 间同步通信限制(当响应时间超于syncLimit * tickTime
时,Leader 便会将 Follower 进行移除)dataDir
:此目录用于存放保存在内存数据库中的快照信息(当未配置dataLogDir
参数时,日志信息也会存放到此目录)clientPort
:ZooKeeper 监听的端口,用于客户端连接使用。
启动 ZooKeeper
[root@ZooKeeper ~]# /usr/local/zookeeper/bin/zkServer.sh start # 启动 [root@ZooKeeper ~]# /usr/local/zookeeper/bin/zkServer.sh status # 查看状态
连接到 ZooKeeper[root@ZooKeeper ~]# /usr/local/zookeeper/bin/zkCli.sh -server 127.0.0.1:2181 Welcome to ZooKeeper! JLine support is enabled WATCHER:: WatchedEvent state:SyncConnected type:None path:null [zk: 127.0.0.1:2181(CONNECTED) 0]
- 当连接成功后,系统会输出 ZooKeeper 的相关配置信息和相关环境,并在屏幕上输出
Welcome to ZooKeeper!
等信息。
2.使用 Golang 连接 ZooKeeper 的 API 接口
- 安装 Golang:安装
[root@ZooKeeper ~]# git clone https://github.com/samuel/go-zookeeper.git [root@ZooKeeper ~]# mv go-zookeeper /usr/local/go/src/
package main import ( "fmt" "time" "go-zookeeper/zk" ) func main() { Hosts := []string{"192.168.1.1:2181"} conn, _, err := zk.Connect(Hosts,time.Second * 5) defer conn.Close() if err != nil { fmt.Println(err) return } }
通过 Golang 实现对 ZooKeeper 的增删改查:package main import ( "fmt" "time" "go-zookeeper/zk" ) var ( path = "/Zzz" ) //增 func add(conn *zk.Conn) { var data = []byte("Hello ZooKeeper") // flags 的四种取值方式: // 0 (永久.除非手动删除) // zk.FlagEphemeral = 1 (短暂. session 断开则该节点也被删除) // zk.FlagSequence = 2 (会自动在节点后面添加序号) // 3 (Ephemeral 和 Sequence. 即短暂且自动添加序号) var flags int32 = 0 // 获取访问控制权限 acls := zk.WorldACL(zk.PermAll) create, err := conn.Create(path,data,flags,acls) if err != nil { fmt.Printf("创建失败: %v\n",err) return } fmt.Printf("创建: %v 成功\n",create) } // 查 func get(conn *zk.Conn) { data, _, err := conn.Get(path) if err != nil { fmt.Printf("查询 %s 失败,err: %v\n",path,err) return } fmt.Printf("%s 的值为 %s\n",path,string(data)) } // 删除与增加不同在于其函数中的 Version 参数. 其中 Version 使用 CAS 支持 (可以通过此种方式保证原子性) // 改 func modify(conn *zk.Conn) { new_data := []byte("This is ZooKeeper") _, sate, _ := conn.Get(path) _, err := conn.Set(path,new_data,sate.Version) if err != nil { fmt.Printf("数据修改失败: %v\n",err) return } fmt.Println("数据修改成功") } // 删 func del(conn *zk.Conn) { _, sate, _ := conn.Get(path) err := conn.Delete(path,sate.Version) if err != nil { fmt.Printf("数据删除失败: %v\n",err) return } fmt.Println("数据删除成功") } func main() { hosts := []string{"192.168.1.1:2181"} conn, _, err := zk.Connect(hosts,time.Second * 5) defer conn.Close() if err != nil { fmt.Println(err) return } /* 增删改查 */ add(conn) get(conn) modify(conn) get(conn) del(conn) }
3.配置 ZooKeeper Cluster
- 在原来的基础上,在增加两台服务器:
主机名 操作系统 IP 地址 ZooKeeper-2 CentOS 7.4 192.168.1.2 ZooKeeper-3 CentOS 7.4 192.168.1.3 1)将 Java 和 ZooKeeper 传给新的服务器: [root@ZooKeeper ~]# scp -r /usr/local/java root@192.168.1.2:/usr/local/ [root@ZooKeeper ~]# scp -r /usr/local/zookeeper root@192.168.1.2:/usr/local/
2)在新的服务器上启动 ZooKeeper:
[root@ZooKeeper ~]# cat <<END >> /etc/profile export JAVA_HOME=/usr/local/java export PATH=$PATH:$JAVA_HOME/bin END [root@ZooKeeper ~]# source /etc/profile [root@ZooKeeper ~]# /usr/local/zookeeper/bin/zkServer.sh start
3)配置 Cluster 集群(三台服务器上操作一样)
[root@ZooKeeper ~]# cat <<END >> /usr/local/zookeeper/conf/zoo.cfg server.1=192.168.1.1:2888:3888 server.2=192.168.1.2:2889:3889 server.3=192.168.1.3:2890:3890 END
4)创建
myid
文件[root@ZooKeeper ~]# echo "1" > /usr/local/zookeeper/data/myid [root@ZooKeeper-2 ~]# echo "2" > /usr/local/zookeeper/data/myid [root@ZooKeeper-2 ~]# echo "3" > /usr/local/zookeeper/data/myid
- 需要确保每台服务器的
myid
文件中数字不同,并且和自己所在机器的zoo.cfg
中server.id=host:port:port
的id
值一样。 - 另外,
id
的范围是1 ~ 255
。
5)重启 ZooKeeper 服务
[root@ZooKeeper ~]# /usr/local/zookeeper/bin/zkServer.sh restart # 三台服务器都要重启
查看 ZooKeeper 状态:
验证:
-
学习搭建Hadoop+HBase+ZooKeeper分布式集群环境
2016-05-04 16:51:38由于集群至少需要三台服务器,我就拿上次做的MongoDB Master, Slave, Arbiter环境来做Hadoop集群。服务器还是ibmcloud 免费提供的。其中Arbiter在这里做的也是slave的角色。 Hostname IP Server ...Hostname IP Server Type Master 192.168.0.28 Centos6.2 Slave 192.168.0.29 Ubuntu14.04 Arbiter 192.168.0.30 Ubuntu14.04 $
cat
/etc/hosts
127.0.0.1 localhost Database-Master localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.0.28 Database-Master master
192.168.0.29 Database-Slave slave
192.168.0.30 Database-Arbiter arbiter
export
JAVA_HOME=
/usr/java/jdk1
.8.0_73
export
PATH=$JAVA_HOME
/bin
:$PATH
export
CLASSPATH=.:$JAVA_HOME
/lib/dt
.jar:$JAVA_HOME
/lib/tool
.jar
<property>
<name>fs.default.name<
/name
>
<value>hdfs:
//master
:9000<
/value
>
<
/property
>
<
/configuration
>
<configuration>
<property>
<name>dfs.name.
dir
<
/name
>
<value>
/home/ibmcloud/hadoop/name
<
/value
>
<
/property
>
<property>
<name>dfs.data.
dir
<
/name
>
<value>
/home/ibmcloud/hadoop/data
<
/value
>
<
/property
>
<property>
<name>dfs.replication<
/name
>
<value>3<
/value
>
<
/property
>
<
/configuration
>
<configuration>
<property>
<name>mapred.job.tracker<
/name
>
<value>master:9001<
/value
>
<
/property
>
<
/configuration
>
echo
"master"
>~
/hadoop/etc/hadoop/master
echo
-e
"slave\narbiter"
>~
/hadoop/etc/hadoop/slaves
$ jps
23076 NameNode
20788 ResourceManager
23302 SecondaryNameNode
27559 Jps
$
egrep
-
v
'^$|^#'
zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=
/home/ibmcloud/zookeeper/data
clientPort=2181
server.1=192.168.0.28:2888:3888
server.2=192.168.0.29:2888:3888
server.3=192.168.0.30:2888:3888
2016-03-15 06:43:01,755 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:57379
2016-03-15 06:43:01,757 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:57379
2016-03-15 06:43:01,760 [myid:1] - INFO [CommitProcessor:1:ZooKeeperServer@645] - Established session 0x15378e1050a0006 with negotiated timeout 40000
for
client
/192
.168.0.28:57379
2016-03-15 06:43:02,211 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:57383
2016-03-15 06:43:02,215 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:57383
2016-03-15 06:43:02,217 [myid:1] - INFO [CommitProcessor:1:ZooKeeperServer@645] - Established session 0x15378e1050a0007 with negotiated timeout 40000
for
client
/192
.168.0.28:57383
2016-03-15 06:46:57,531 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@1008] - Closed socket connection
for
client
/192
.168.0.28:57379
which
had sessionid 0x15378e1050a0006
2016-03-15 06:46:57,544 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@1008] - Closed socket connection
for
client
/192
.168.0.28:57383
which
had sessionid 0x15378e1050a0007
2016-03-15 06:46:57,555 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@1008] - Closed socket connection
for
client
/192
.168.0.28:57372
which
had sessionid 0x15378e1050a0005
2016-03-15 06:47:10,171 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.30:60866
2016-03-15 06:47:10,184 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.30:60866
2016-03-15 06:47:10,186 [myid:1] - INFO [CommitProcessor:1:ZooKeeperServer@645] - Established session 0x15378e1050a0008 with negotiated timeout 40000
for
client
/192
.168.0.30:60866
2016-03-15 06:47:10,625 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:58169
2016-03-15 06:47:10,626 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:58169
2016-03-15 06:47:10,629 [myid:1] - INFO [CommitProcessor:1:ZooKeeperServer@645] - Established session 0x15378e1050a0009 with negotiated timeout 40000
for
client
/192
.168.0.28:58169
2016-03-15 06:47:11,199 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.30:60867
2016-03-15 06:47:11,200 [myid:1] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.30:60867
2016-03-15 06:47:11,204 [myid:1] - INFO [CommitProcessor:1:ZooKeeperServer@645] - Established session
2016-03-15 06:43:02,667 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:58604
2016-03-15 06:43:02,667 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:58604
2016-03-15 06:43:02,670 [myid:2] - INFO [CommitProcessor:2:ZooKeeperServer@645] - Established session 0x25378e0edf00006 with negotiated timeout 40000
for
client
/192
.168.0.28:58604
2016-03-15 06:46:55,407 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:59328
2016-03-15 06:46:55,410 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:59328
2016-03-15 06:46:55,415 [myid:2] - INFO [CommitProcessor:2:ZooKeeperServer@645] - Established session 0x25378e0edf00007 with negotiated timeout 40000
for
client
/192
.168.0.28:59328
2016-03-15 06:46:57,242 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@1008] - Closed socket connection
for
client
/192
.168.0.28:59328
which
had sessionid 0x25378e0edf00007
2016-03-15 06:46:57,928 [myid:2] - WARN [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@357] - caught end of stream exception
EndOfStreamException: Unable to
read
additional data from client sessionid 0x25378e0edf00006, likely client has closed socket
at org.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:230)
at org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:203)
at java.lang.Thread.run(Thread.java:745)
2016-03-15 06:46:57,929 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@1008] - Closed socket connection
for
client
/192
.168.0.28:58604
which
had sessionid 0x25378e0edf00006
2016-03-15 06:47:08,780 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:59377
2016-03-15 06:47:08,786 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:59377
2016-03-15 06:47:08,789 [myid:2] - INFO [CommitProcessor:2:ZooKeeperServer@645] - Established session 0x25378e0edf00008 with negotiated timeout 40000
for
client
/192
.168.0.28:59377
2016-03-15 06:49:57,202 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxnFactory@192] - Accepted socket connection from
/192
.168.0.28:59911
2016-03-15 06:49:57,212 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:ZooKeeperServer@900] - Client attempting to establish new session at
/192
.168.0.28:59911
2016-03-15 06:49:57,215 [myid:2] - INFO [CommitProcessor:2:ZooKeeperServer@645] - Established session 0x25378e0edf00009 with negotiated timeout 40000
for
client
/192
.168.0.28:59911
2016-03-15 06:52:15,489 [myid:2] - WARN [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@357] - caught end of stream exception
EndOfStreamException: Unable to
read
additional data from client sessionid 0x25378e0edf00009, likely client has closed socket
at org.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:230)
at org.apache.zookeeper.server.NIOServerCnxnFactory.run(NIOServerCnxnFactory.java:203)
at java.lang.Thread.run(Thread.java:745)
2016-03-15 06:52:15,490 [myid:2] - INFO [NIOServerCxn.Factory:0.0.0.0
/0
.0.0.0:2181:NIOServerCnxn@1008] - Closed socket connection
for
client
/192
.168.0.28:59911
which
had sessionid 0x25378e0edf00009
$ jps
23076 NameNode
20788 ResourceManager
30821 Jps
23302 SecondaryNameNode
30538 QuorumPeerMain
$
egrep
-
v
'^$|^#'
hbase-
env
.sh
export
JAVA_HOME=
/usr/java/jdk1
.8.0_73
export
HBASE_CLASSPATH=
/home/ibmcloud/hadoop/etc/hadoop
export
HBASE_OPTS=
"-XX:+UseConcMarkSweepGC"
export
HBASE_MASTER_OPTS=
"$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m"
export
HBASE_REGIONSERVER_OPTS=
"$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m"
export
HBASE_MANAGES_ZK=
false
<
configuration
>
<
property
>
<
name
>hbase.rootdir</
name
>
<
value
>hdfs://master:9000/hbase</
value
>
</
property
>
<
property
>
<
name
>hbase.master</
name
>
<
value
>master</
value
>
</
property
>
<
property
>
<
name
>hbase.cluster.distributed</
name
>
<
value
>true</
value
>
</
property
>
<
property
>
<
name
>hbase.zookeeper.property.clientPort</
name
>
<
value
>2181</
value
>
</
property
>
<
property
>
<
name
>hbase.zookeeper.quorum</
name
>
<
value
>master,slave,arbiter</
value
>
</
property
>
<
property
>
<
name
>zookeeper.session.timeout</
name
>
<
value
>60000000</
value
>
</
property
>
<
property
>
<
name
>dfs.support.append</
name
>
<
value
>true</
value
>
</
property
>
</
configuration
>
$ hadoop
/sbin/start-all
.sh
This script is Deprecated. Instead use start-dfs.sh and start-yarn.sh
16
/03/15
07:33:09 WARN util.NativeCodeLoader: Unable to load native-hadoop library
for
your platform... using
builtin
-java classes where applicable
Starting namenodes on [master]
master: namenode running as process 23076. Stop it first.
arbiter: datanode running as process 2111. Stop it first.
slave: datanode running as process 19992. Stop it first.
Starting secondary namenodes [0.0.0.0]
0.0.0.0: secondarynamenode running as process 23302. Stop it first.
16
/03/15
07:33:16 WARN util.NativeCodeLoader: Unable to load native-hadoop library
for
your platform... using
builtin
-java classes where applicable
starting yarn daemons
resourcemanager running as process 20788. Stop it first.
arbiter: starting nodemanager, logging to
/home/ibmcloud/hadoop/logs/yarn-ibmcloud-nodemanager-Database-Arbiter
.out
slave: starting nodemanager, logging to
/home/ibmcloud/hadoop/logs/yarn-ibmcloud-nodemanager-Database-Slave
.out
$ hbase
/bin/start-hbase
.sh
master running as process 10144. Stop it first.
arbiter: regionserver running as process 3515. Stop it first.
slave: starting regionserver, logging to
/home/ibmcloud/hbase/bin/
..
/logs/hbase-ibmcloud-regionserver-Database-Slave
.out
slave: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed
in
8.0
slave: Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128m; support was removed
in
8.0
# ibmcloud at Database-Master in ~ [7:33:44]
$ jps
10144 HMaster
23076 NameNode
20788 ResourceManager
20773 Jps
23302 SecondaryNameNode
30538 QuorumPeerMain
# ibmcloud at Database-Slave in ~/hbase/bin [6:47:55]
$ jps
19992 DataNode
26794 Jps
16397 QuorumPeerMain
26526 HRegionServer
# ibmcloud at Database-Arbiter in ~/hbase/bin [6:46:34]
$ jps
2016 QuorumPeerMain
3515 HRegionServer
3628 Jps
2111 DataNode
$ hbase
/bin/hbase
shell
2016-03-15 07:35:04,687 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library
for
your platform... using
builtin
-java classes where applicable
HBase Shell; enter
'help<RETURN>'
for
list of supported commands.
Type
"exit<RETURN>"
to leave the HBase Shell
Version 1.2.0, r25b281972df2f5b15c426c8963cbf77dd853a5ad, Thu Feb 18 23:01:49 CST 2016
hbase(main):001:0>
hbase(main):002:0* status
ERROR: org.apache.hadoop.hbase.PleaseHoldException: Master is initializing
-
zookeeper分布式协调服务
2019-08-27 23:58:21zookeeper 主要是解决分布式环境下的服务协调问题而产生的,如果我们要去实现一个 zookeeper 这样的中间件, 我们需要做什么? 1. 防止单点故障 如果要防止 zookeeper 这个中间件的单点故障,那就势必要做集群。...zookeeper 的设计猜想
zookeeper 主要是解决分布式环境下的服务协调问题而产生的,如果我们要去实现一个 zookeeper 这样的中间件, 我们需要做什么?
1. 防止单点故障
如果要防止 zookeeper 这个中间件的单点故障,那就势必要做集群。而且这个集群如果要满足高性能要求的话,还得是一个高性能高可用的集群。高性能意味着这个集群能够分担客户端的请求流量,高可用意味着集群中的某一个节点宕机以后,不影响整个集群的数据和继续提供服务的可能性。
结论: 所以这个中间件需要考虑到集群,而且这个集群还需要分摊客户端的请求流量
2. 接着上面那个结论再来思考,如果要满足这样的一个高性能集群,我们最直观的想法应该是,每个节点都能接收到请求,并且每个节点的数据都必须要保持一致。要实现各个节点的数据一致性,就势必要一个 leader 节点负责协调和数据同步操作。这个我想大家都知道,如果在这样一个集群中没有 leader 节点,每个节点都可以接收所有请求,那么这个集群的数据同步的复杂度是非常大。
结论:所以这个集群中涉及到数据同步以及会存在leader 节点
3. 继续思考,如何在这些节点中选举出 leader 节点,以及leader 挂了以后,如何恢复呢?
结论:所以 zookeeper 用了基于 paxos 理论所衍生出来的 ZAB 协议
4. leader 节点如何和其他节点保证数据一致性,并且要求是强一致的。在分布式系统中,每一个机器节点虽然都能够明确知道自己进行的事务操作过程是成功和失败, 但是却无法直接获取其他分布式节点的操作结果。所以当一个事务操作涉及到跨节点的时候,就需要用到分布式事务,分布式事务的数据一致性协议有 2PC协议和3PC 协议。
基于这些猜想,我们基本上知道 zookeeper 为什么要用到zab 理论来做选举、为什么要做集群、为什么要用到分布式事务来实现数据一致性了。
关于 2PC 提交
(Two Phase Commitment Protocol)当一个事务操作需要跨越多个分布式节点的时候,为了保持事务处理的ACID特性,就需要引入一个“协调者”(TM)来统一调度所有分布式节点的执行逻辑,这些被调度的分布式节点被称为 AP。
TM 负责调度 AP 的行为,并最终决定这些 AP 是否要把事务真正进行提交;因为整个事务是分为两个阶段提交,所以叫 2pc
阶段一:提交事务请求(投票)
1. 事务询问
协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应
2. 执行事务
各个参与者节点执行事务操作,并将 Undo 和 Redo 信息记录到事务日志中,尽量把提交过程中所有消耗时间的操作和准备都提前完成确保后面 100%成功提交事务
3. 各个参与者向协调者反馈事务询问的响应
如果各个参与者成功执行了事务操作,那么就反馈给参与者yes 的响应,表示事务可以执行;如果参与者没有成功执行事务,就反馈给协调者 no 的响应,表示事务不可以执行,上面这个阶段有点类似协调者组织各个参与者对一次事务操作的投票表态过程,因此 2pc 协议的第一个阶段称为“投票阶段”,即各参与者投票表名是否需要继续执行接下去的事务提交操作。
阶段二:执行事务提交
在这个阶段,协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作,正常情况下包含两种可能:执行事务、中断事务
zookeeper 的集群
在 zookeeper 中,客户端会随机连接到 zookeeper 集群中的一个节点,如果是读请求,就直接从当前节点中读取数据,如果是写请求,那么请求会被转发给 leader 提交事务, 然后 leader 会广播事务,只要有超过半数节点写入成功, 那么写请求就会被提交(类 2PC 事务)
所有事务请求必须由一个全局唯一的服务器来协调处理,这个服务器就是 Leader 服务器,其他的服务器就是follower。leader 服务器把客户端的失去请求转化成一个事务 Proposal(提议),并把这个 Proposal 分发给集群中的所有 Follower 服务器。之后 Leader 服务器需要等待所有Follower 服务器的反馈,一旦超过半数的 Follower 服务器进行了正确的反馈,那么 Leader 就会再次向所有的Follower 服务器发送 Commit 消息,要求各个 follower 节点对前面的一个 Proposal 进行提交;
集群角色
Leader 角色
Leader 服务器是整个 zookeeper 集群的核心,主要的工作任务有两项
1. 事物请求的唯一调度和处理者,保证集群事物处理的顺序性
2. 集群内部各服务器的调度者
Follower 角色
Follower 角色的主要职责是
1. 处理客户端非事物请求、转发事物请求给 leader 服务器
2. 参与事物请求 Proposal 的投票(需要半数以上服务器通过才能通知 leader commit 数据; Leader 发起的提案, 要求 Follower 投票)
- 参与 Leader 选举的投票
Observer 角色
Observer 是 zookeeper3.3 开始引入的一个全新的服务器角色,从字面来理解,该角色充当了观察者的角色。 观察 zookeeper 集群中的最新状态变化并将这些状态变化同步到 observer 服务器上。Observer 的工作原理与follower 角色基本一致,而它和 follower 角色唯一的不同在于 observer 不参与任何形式的投票,包括事物请求Proposal的投票和leader选举的投票。简单来说,observer服务器只提供非事物请求服务,通常在于不影响集群事物处理能力的前提下提升集群非事物处理的能力
集群组成
通常 zookeeper 是由 2n+1 台 server 组成,每个 server 都知道彼此的存在。对于 2n+1 台 server,只要有 n+1 台(大多数)server 可用,整个系统保持可用。我们已经了解到,一个 zookeeper 集群如果要对外提供可用的服务,那么集群中必须要有过半的机器正常工作并且彼此之间能够正常通信,基于这个特性,如果向搭建一个能够允许 F 台机器 down 掉的集群,那么就要部署 2*F+1 台服务器构成的zookeeper 集群。因此 3 台机器构成的 zookeeper 集群,
能够在挂掉一台机器后依然正常工作。一个 5 台机器集群的服务,能够对 2 台机器怪调的情况下进行容灾。如果一台由 6 台服务构成的集群,同样只能挂掉 2 台机器。因此,5 台和 6 台在容灾能力上并没有明显优势,反而增加了网络通信负担。系统启动时,集群中的 server 会选举出一台server 为 Leader,其它的就作为 follower(这里先不考虑observer 角色)。
之所以要满足这样一个等式,是因为一个节点要成为集群中的 leader,需要有超过及群众过半数的节点支持,这个涉及到 leader 选举算法。同时也涉及到事务请求的提交投票
ZAB 协议
ZAB(Zookeeper Atomic Broadcast) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。
zab 协议介绍
ZAB 协议包含两种基本模式,分别是
1. 崩溃恢复
2. 原子广播当整个集群在启动时,或者当 leader 节点出现网络中断、崩溃等情况时,ZAB 协议就会进入恢复模式并选举产生新的 Leader,当 leader 服务器选举出来后,并且集群中有过半的机器和该 leader 节点完成数据同步后(同步指的是数据同步,用来保证集群中过半的机器能够和 leader 服务器的数据状态保持一致),ZAB 协议就会退出恢复模式。 当集群中已经有过半的 Follower 节点完成了和 Leader 状态同步以后,那么整个集群就进入了消息广播模式。这个时候,在 Leader 节点正常工作时,启动一台新的服务器加入到集群,那这个服务器会直接进入数据恢复模式,和 leader 节点进行数据同步。同步完成后即可正常对外提供非事务请求的处理。
消息广播的实现原理
如果大家了解分布式事务的 2pc 和 3pc 协议的话(不了解也没关系,我们后面会讲),消息广播的过程实际上是一个简化版本的二阶段提交过程
1. leader 接收到消息请求后,将消息赋予一个全局唯一的64 位自增 id,叫:zxid,通过 zxid 的大小比较既可以实现因果有序这个特征
2. leader 为每个 follower 准备了一个 FIFO 队列(通过 TCP协议来实现,以实现了全局有序这一个特点)将带有 zxid的消息作为一个提案(proposal)分发给所有的 follower
3. 当 follower 接收到 proposal,先把 proposal 写到磁盘, 写入成功以后再向 leader 回复一个 ack
4. 当 leader 接收到合法数量(超过半数节点)的 ACK 后,leader 就会向这些 follower 发送 commit 命令,同时会在本地执行该消息
5. 当 follower 收到消息的 commit 命令以后,会提交该消息
leader 的投票过程,不需要 Observer 的 ack,也就是Observer 不需要参与投票过程,但是 Observer 必须要同步 Leader 的数据从而在处理请求的时候保证数据的一致性
崩溃恢复(数据恢复)
ZAB 协议的这个基于原子广播协议的消息广播过程,在正常情况下是没有任何问题的,但是一旦 Leader 节点崩溃,或者由于网络问题导致 Leader 服务器失去了过半的Follower 节点的联系(leader 失去与过半 follower 节点联系,可能是 leader 节点和 follower 节点之间产生了网络分区,那么此时的 leader 不再是合法的 leader 了),那么就会进入到崩溃恢复模式。在 ZAB 协议中,为了保证程序的正确运行,整个恢复过程结束后需要选举出一个新的Leader为了使 leader 挂了后系统能正常工作,需要解决以下两个问题
1. 已经被处理的消息不能丢失
当 leader 收到合法数量 follower 的 ACKs 后,就向各个 follower 广播COMMIT 命令,同时也会在本地执行 COMMIT 并向连接的客户端返回「成功」。但是如果在各个 follower 在收到 COMMIT 命令前 leader 就挂了,导致剩下的服务器并没有执行都这条消息。
leader 对事务消息发起 commit 操作,但是该消息在follower1 上执行了,但是 follower2 还没有收到 commit,就已经挂了,而实际上客户端已经收到该事务消息处理成功的回执了。所以在 zab 协议下需要保证所有机器都要执行这个事务消息
2. 被丢弃的消息不能再次出现
当 leader 接收到消息请求生成 proposal 后就挂了,其他 follower 并没有收到此 proposal,因此经过恢复模式重新选了 leader 后,这条消息是被跳过的。 此时,之前挂了的 leader 重新启动并注册成了 follower,他保留了被跳过消息的 proposal 状态,与整个系统的状态是不一致的,需要将其删除。
ZAB 协议需要满足上面两种情况,就必须要设计一个 leader 选举算法:能够确保已经被 leader 提交的事务 ,Proposal能够提交、同时丢弃已经被跳过的事务Proposal。
针对这个要求
1. 如果 leader 选举算法能够保证新选举出来的 Leader 服务器拥有集群中所有机器最高编号(ZXID 最大)的事务Proposal,那么就可以保证这个新选举出来的 Leader 一定具有已经提交的提案。因为所有提案被 COMMIT 之前必须有超过半数的 follower ACK,即必须有超过半数节点的服务器的事务日志上有该提案的 proposal,因此,只要有合法数量的节点正常工作,就必然有一个节点保存了所有被 COMMIT 消息的 proposal 状态 ;另外一个,zxid 是 64 位,高 32 位是 epoch 编号,每经过一次 Leader 选举产生一个新的 leader,新的 leader 会将epoch 号+1,低 32 位是消息计数器,每接收到一条消息这个值+1,新 leader 选举后这个值重置为 0.这样设计的好处在于老的 leader 挂了以后重启,它不会被选举为 leader, 因此此时它的 zxid 肯定小于当前新的 leader。当老的leader 作为 follower 接入新的 leader 后,新的 leader 会 让它将所有的拥有旧的 epoch 号的未被 COMMIT 的proposal 清除
关于 ZXID
zxid,也就是事务 id,为了保证事务的顺序一致性,zookeeper 采用了递增的事务 id 号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了 zxid。实现中 zxid 是一个 64 位的数字,它高 32 位是 epoch(ZAB 协议通过 epoch 编号来区分 Leader 周期变化的策略)用来标识 leader 关系是否改变,每次一个 leader 被选出来,它都会有一个新的 epoch=(原来的 epoch+1),标识当前属于那个 leader 的统治时期。低 32 位用于递增计数。epoch:可以理解为当前集群所处的年代或者周期,每个leader 就像皇帝,都有自己的年号,所以每次改朝换代,leader 变更之后,都会在前一个年代的基础上加 1。这样就算旧的 leader 崩溃恢复之后,也没有人听他的了,因为 follower 只听从当前年代的 leader 的命令。*
epoch 的变化大家可以做一个简单的实验,
1. 启动一个 zookeeper 集群。
2. 在 /tmp/zookeeper/VERSION-2 路 径 下 会 看 到 一 个 currentEpoch 文件。文件中显示的是当前的 epoch
3. 把 leader 节点停机,这个时候在看 currentEpoch 会有变化。 随着每次选举新的 leader,epoch 都会发生变化
leader 选举
Leader 选举会分两个过程
启动的时候的 leader 选举、 leader 崩溃的时候的的选举
服务器启动时的 leader 选举
每个节点启动的时候状态都是 LOOKING,处于观望状态, 接下来就开始进行选主流程进行 Leader 选举,至少需要两台机器(具体原因前面已经讲过了),我们选取 3 台机器组成的服务器集群为例。在集群初始化阶段,当有一台服务器 Server1 启动时,它本身是无法进行和完成 Leader 选举,当第二台服务器 Server2 启动时,这个时候两台机器可以相互通信,每台机器都试图找到 Leader,于是进入 Leader 选举过程。选举过程如下
(1) 每个 Server 发出一个投票。由于是初始情况,Server1 和 Server2 都会将自己作为 Leader 服务器来进行投票,每次投票会包含所推举的服务器的 myid 和 ZXID、 epoch,使用(myid, ZXID,epoch)来表示,此时 Server1 的投票为(1, 0),Server2 的投票为(2, 0),然后各自将这个投票发给集群中其他机器。
(2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自LOOKING状态的服务器。
(3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行 PK,PK 规则如下
i. 优先检查 ZXID。ZXID 比较大的服务器优先作为Leader
ii. 如果 ZXID 相同,那么就比较 myid。myid 较大的服务器作为 Leader 服务器。 对于 Server1 而言,它的投票是(1, 0),接收 Server2 的投票为(2, 0),首先会比较两者的 ZXID,均为 0,再比较 myid,此时 Server2 的 myid 最大,于是更新自己的投票为(2, 0),然后重新投票,对于 Server2 而言, 它不需要更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
(4) 统计投票。每次投票后,服务器都会统计投票信息, 判断是否已经有过半机器接受到相同的投票信息,对于 Server1、Server2 而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了 Leader。
(5) 改变服务器状态。一旦确定了 Leader,每个服务器就会更新自己的状态,如果是 Follower,那么就变更为 FOLLOWING,如果是 Leader,就变更为 LEADING。
运行过程中的 leader 选举
当集群中的 leader 服务器出现宕机或者不可用的情况时, 那么整个集群将无法对外提供服务,而是进入新一轮的Leader 选举,服务器运行期间的 Leader 选举和启动时期的 Leader 选举基本过程是一致的。
(1) 变更状态。Leader 挂后,余下的非 Observer 服务器都会将自己的服务器状态变更为 LOOKING,然后开始进入 Leader 选举过程。
(2) 每个 Server 会发出一个投票。在运行期间,每个服务器上的 ZXID 可能不同,此时假定 Server1 的 ZXID 为123,Server3的ZXID为122;在第一轮投票中,Server1 和 Server3 都会投自己,产生投票(1, 123),(3, 122), 然后各自将投票发送给集群中所有机器。接收来自各个服务器的投票。与启动时过程相同。
(3) 处理投票。与启动时过程相同,此时,Server1 将会成为 Leader。
(4) 统计投票。与启动时过程相同。
(5) 改变服务器的状态。与启动时过程相同
Leader 选举源码分析
有了理论基础以后,我们先带大家读一下源码,看看他的实现逻辑。然后我们再通过图形的方式帮助大家理解。
从入口函数 QUORUMPEERMAIN 开始
启动主线程,QuorumPeer 重写了 Thread.start 方法
调用 QUORUMPEER 的 START 方法
loaddatabase, 主要是从本地文件中恢复数据,以及获取最新的 zxid
初始化 LEADERELECTION
配置选举算法,选举算法有 3 种,可以通过在 zoo.cfg 里面进行配置,默认是 fast 选举
继续看 FastLeaderElection 的初始化动作,主要初始化了业务层的发送队列和接收队列
接下来调用 fle.start() , 也就是会调用 FastLeaderElection .start()方法,该方法主要是对发送线程和接收线程的初始化 ,左边是 FastLeaderElection 的 start,右边是messager.start()
wsThread 和 wrThread 的 初 始 化 动 作 在FastLeaderElection 的 starter 方法里面进行,这里面有两个内部类,一个是 WorkerSender,一个是WorkerReceiver, 负责发送投票信息和接收投票信息
然后再回到 QuorumPeer.java。 FastLeaderElection 初始化完成以后,调用 super.start(),最终运行 QuorumPeer 的run 方法
前面部分主要是做 JMX 监控注册
重要的代码在这个 while 循环里
调用 setCurrentVote(makeLEStrategy().lookForLeader());最终根据策略应该运行 FastLeaderElection 中的选举算法
LOOKFORLEADER 开始选举
消息如何广播,看 SENDNOTIFICATIONS
WORKERSENDER
FastLeaderElection 选举过程
其实在这个投票过程中就涉及到几个类,FastLeaderElection:FastLeaderElection 实现了 Election 接口,实现各服务器之间基于 TCP 协议进行选举Notification:内部类,Notification 表示收到的选举投票信息(其他服务器发来的选举投票信息),其包含了被选举者的 id、zxid、选举周期等信息
ToSend:ToSend表示发送给其他服务器的选举投票信息,也包含了被选举者的 id、zxid、选举周期等信息
Messenger : Messenger 包 含 了 WorkerReceiver 和WorkerSender 两个内部类; WorkerReceiver 实现了 Runnable 接口,是选票接收器。其会不断地从 QuorumCnxManager 中获取其他服务器发来的选举消息,并将其转换成一个选票,然后保存到recvqueue 中 ;WorkerSender 也实现了 Runnable 接口,为选票发送器,其会不断地从 sendqueue 中获取待发送的选票,并将其传递到底层 QuorumCnxManager 中
-
Hadoop集群搭建实验(5) _部署分布式协调服务ZooKeeper
2019-09-30 08:45:29实验目标:在3台主机组成的小型集群上部署分布式协调服务ZooKeeper,用于教学演示环境要求: 虚拟机...集群规划:无需复制虚拟机,直接利用完全分布式集群的3台主机master,slave1,slave2完成部署, 需要特别说明: Zo... -
HBase集群搭建实验(3)_完全分布式部署(使用内置ZooKeeper,非HMaster HA)
2020-01-18 12:57:19HBase完全分布式模式: 1)不同的HBase进程分别独立运行在多台硬件配置较高的服务器主机构成的集群中,适合HBase的运维和生产环境 ...实验前提:HBase完全分布式部署方式依赖Hadoop,本实验紧接Hadoop... -
Zookeeper学习总结
2022-02-28 19:14:50Zookeeper 分布式组件的鼻祖。 一、什么是Zookeeper Zookeeper是一种分布式协调服务,...在分布式系统中,需要有zookeeper作为分布式协调组件,协调分布式系统中的状态 分布式锁 zk在实现分布式锁上,可以做到 -
Zookeeper学习个人总结
2021-10-15 10:54:07NO1:说说zookeeper是什么? Zookeeper一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心,服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到Zookeeper中查找... -
HBase 伪分布式集群环境搭建
2019-04-02 20:22:101. 环境 HBase的版本为 1.4.1 请注意版本差异 ! ...官网版本说明地址 ...-- hbase 中自带的zookeeper数据存放...Hadoop伪分布式集群环境搭建 https://blog.csdn.net/weixin_42195284/article/details/88978897 -
大数据实验报告 (2).zip
2019-06-17 10:24:37大数据实验报告,内含八个实验报告,Hadoop集群伪分布式搭建、Hadoop基本操作、MapReduce程序设计、Zookeeper安装与Hadoop高可用性部署、Hbase数据储存设计、 Sqoop数据迁移实战、Flume数据采集实战、Hive数据分析... -
Hadoop高可用集群,基于Zookeeper集群详细搭建流程!
2020-07-08 03:00:362.HDFS 高可用集群规划,请保证 Hadoop 完全分布式和 ZooKeeper 完全分布式环境已经安装完成,以3台机为例。 3.先在一台机hadoop2上配置文件信息 进入文件夹下的配置文件目录下 cd /opt/soft/hadoop260/etc/hadoop/ ... -
【大数据实验】03:HBase伪分布式部署
2022-04-25 09:10:09OVERVIEWHBase伪分布式部署实验环境1.HBase单机模式安装配置2.HBase伪分布式安装部署3.HBase Shell操作4.HBase Web UI管理(1)Master节点的Web管理(2)RegionServer节点的Web管理 实验环境 硬件:ubuntu 16.04 ... -
大数据分布式集群搭建详细步骤(Spark的安装与配置)
2020-08-25 14:45:03详细步骤:安装scala环境解压Spark的tar包向所有子节点发送 Spark 配置好的安装包测试Spark环境开启Spark集群访问Web界面 安装scala环境 1、解压scala 的 tar 包 首先我们进入到本系统的/opt/soft路径下可以看到我们... -
手把手教你搭建Hadoop生态系统伪分布式集群
2020-06-08 21:33:23这篇博客呢,我会详细介绍怎么搭建Hadoop生态系统,实战课程嘛,搞了三天服务器,搭建完全分布式系统。 一、准备工作 三台服务器的版本信息: 主节点: 从节点1: 从节点2: 1.更新升级软件包 CentOS系统: ... -
Zookeeper学习心得
2021-05-12 17:02:30提起Zookeeper,大家就会想到分布式架构的系统,而分布式系统中都是基于CAP原则来实现的,下面就先介绍一下CAP原则 CAP原则 1.可用性 Availability 可用性是在某个考察时间,系统能够正常运行的概率或时间占有率期望... -
【ZooKeeper】ZooKeeper安装及简单操作
2020-03-28 12:35:25ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、... -
ZooKeeper应用---分布式配置更新
2022-03-21 15:42:11zookeeper API的使用,基于回调和监听的响应式编程 -
Hadoop大数据平台集群部署与开发--------Hbase的部署(单点部署和集群部署)
2018-11-22 22:42:16集群部署的优点:当HMaster主节点出现故障,HMaster备用节点会用Zookeeper获取主HMaster存在的整个Hbase集群状态信息,但是Hbase可以通过Zookeeper随时感知每个HegionServer的状况,以便于控制管理。 1. 集群... -
Java开发环境实验报告,太香了
2021-07-27 16:11:45ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、... -
【实验】Hadoop-2.7.2+zookeeper-3.4.6完全分布式环境搭建(HDFS、YARN HA)转载
2019-03-12 16:48:35Hadoop-2.7.2+Zookeeper-3.4.6完全分布式环境搭建 一.版本 组件名 版本 说明 JRE java version "1.7.0_67"Java™ SE Runtime Environment (build 1.7.0_67-b01)Java ... -
Apache Kafka 集群部署指南
2021-01-13 08:18:16Kafka的生产集群部署 方案背景 假设每天集群需要承载10亿数据。一天24小时,晚上12点到凌晨8点几乎没多少数据。 使用二八法则估计,也就是80%的数据(8亿)会在16个小时涌入,而且8亿的80%的数据(6.4亿)会在这16... -
ELK+zookeeper+kafka+filebeat集群
2022-05-15 18:00:06zookeeper: 为读多写少的场景所设计 并不是存储大规模业务数据 而是用于存储少量的状态和 配置信息,每个节点存储数据不能超过1MB 数据存储基于节点 znode(包含数据子节点 子节点引用 访问权限) Zookeeper ... -
Hbase集群搭建总结
2020-06-03 08:31:05参考:hadoop 分布式集群搭建 二.安装zookeeper 参考:zookeeper集群安装 三.部署hbase 1.解压缩hbase的软件包,使用命令: tar -zxvf hbase-1.3.0-bin.tar.gz 2.进入hbase的配置目录,在hbase-env.sh文件里面... -
zookeeper全面总结
2021-09-04 14:18:30主要⽤用来解决分布式集群中应⽤用系统的一致性问题, 例例如怎样避免同时操作同一数据造成脏读的问题。分布式系统中数据存在一致性的问题!! ZooKeeper 本质上是⼀个分布式的⼩文件存储系统。 提供基于类似于文件... -
搭建hadoop伪分布式+全分布式(基于Centos7)
2021-01-09 16:36:09对于实验环境下Hadoop集群网络需考虑地址规划、连通性。由于实验环境下数据负载较小、可靠性要求不高,链路一般采用单链路连接。IP地址规划在同一网络中,一般设定地址为(192.168.1.0/24)网段。具体IP地址在Centos... -
3.搭建Zookeeper
2021-07-20 07:16:31集群规划2.解压安装3.配置zoo.cfg文件4.将配置好的文件进行文件分发5.进行启动测试 介绍Zookeeper作用: Apache ZooKeeper是一种高可用性服务,用于维护少量协调数据,通知客户端该数据的更改以及监视客户端的故障... -
Hadoop——实验五:HBASE单机部署、伪分布部署
2021-06-16 19:39:10文章目录一. 实验目的二. 实验内容三. 实验步骤及结果分析 1.... 基于ubuntukylin14.04 (6)版本,完成HBASE伪分布式配置部署 2.1 配置hbase-env.sh文件 2.2 配置hbase-site.xml文件 2.3 运行HBase 3. 基于ubuntuky -
分布式NoSQL列存储数据库Hbase(一)Hbase的功能与应用场景、基本设计思想
2021-07-24 12:03:50分布式NoSQL列存储数据库Hbase(一) 知识点01:课程回顾 离线项目为例 数据生成:用户访问咨询数据、意向用户报名信息、考勤信息 数据采集 Flume:实时数据采集:采集文件或者网络端口 Sqoop:离线数据同步:...