文章字数:3504,阅读全文大约需要14分钟
分布式特点
- 分布性,硬件或软件组件分布在不同网络机器上,彼此间仅仅通过消息传递进行通信和协调的系统
- 对等性,服务冗余,微服务有多个副本,彼此直接完全一样
- 并发性,
- 缺乏全局时钟,每个节点都有自己的本地时间(使用共同的时间服务器解决)
- 故障随时发生
分布式系统问题
- 通讯异常, 节点间网络异常,会导致脑裂。(多个master)
- 网络分区
- 三态,正确、错误、超时三种状态。
- 节点故障
CAP
C 一致性,数据在多个副本中一致(强一致性只能将数据放在一个节点上)
A 可用, 请求总能得到返回
P 分区容错性(冗余数据),除非整个网络故障,分布式系统在任何网络或节点故障时,仍然能满足一致性(最终一致)和可用的服务
AC,放弃P|数据放在一个节点上,充分保证了一致性和系统可用性,放弃拓展性(P)。放弃分区一致性就不是分布式了
PC,放弃A|当节点故障或网络故障时,受到影响的服务需要等一定时间,等待时间内无法提供服务。一般不会这么做
AP,放弃C|无法保证实时一致,承诺最终一致。
BASE
即使无法做到强一致性,但分布式系统可以根据业务特点,采用适当方式达到最终一致性
Basically Avaliable
基本可用,当分布式系统出现不可预见故障时,允许损失部分可用性,保障系统基本可用。例如双十一高峰,部分用户会出现页面卡顿或降级处理(换成功能没这么强的服务·)。Soft state
软状态,允许系统中的数据存在中间状态,即系统的不同节点数据副本间数据同步存在延时,并认为延时不影响系统可用性。例如买票的正在抢票Eventually consistent
最终一致,所有数据经过一段时间的数据同步,最终达到一个一致状态。
分布式一致性算法
算法 | 说明 |
---|---|
2p | 两段提交,数据库分布式事务常用。算法简单,容易出现阻塞。某些情况下不一致 |
3p | 对于2p的改进,三段提交,完善了阻塞以及可用性。2p,3p都属于强一致性算法。 |
paxos算法 | 两个阶段,少数服从多数。并不需要所有参与者都同一某一协议 |
zab | 借鉴paxos思路,zookeeper解决分布式一致性的算法 |
zookeeper
高性能,高可用,严格顺序访问控制能力的分布式协调服务。是hadoop和Hbase重要组件
- 简单数据结构,共享的树形结构,类似文件系统,存储与内存
- 可构建集群,避免单点故障,3-5台机器就可用组成集群,超过半数正常工作就能对外提供服务
- 顺序访问,每个写请求,zk会分配一个全局唯一的递增编号,利用这个特性可用实现高级协调服务
- 高性能,基于内存操作,服务于非事务请求,适用于读操作为主的业务请求。3台kz集群能达到13w QPS
使用场景
- 发布订阅
- 负载均衡(客户端负载均衡)
- 命名服务,注册中心
- Master选举
- 集群管理,检测集群节点是否健康
- 配置管理,配置中心
- 分布式队列
- 分布式锁
Zookeeper
序号 | 参数名 | 说明 |
---|---|---|
7 | snapCount |
设置多少次事务日志输出后,触发一次快照(snapshot),此时ZK会生产一个snapshot.* 文件,同时创建一个新的事务日志文件log.* ,默认100000,真实实现会增加一定的随机数,避免所有服务器同一时间快照影响性能 |
节点
create /aaa val
创建节点aaa
并赋予值val
。节点必须有值,否则不能创建zk
视图结构和标准unix
文件系统类似,从/
根节点出发。节点成为
ZNode
,每个节点可存储数据,也可以挂载子节点。因此可以成为树节点类型(不同类型节点名也不能重复)
- 持久节点,和客户端连接,断开后数据还在(
ZNode
) - 临时节点,和客户端断开后,数据不在
- 顺序节点,临时节点和持久节点都能创建顺序节点,每次创建节点名都会自动递增(名字+自动生成的序列)
节点状态属性
序号 | 属性 | 数据结构 | 描述 |
---|---|---|---|
1 | czxid |
long |
节点被创建的Zxid 值 |
2 | mzxid |
long |
节点被修改的Zxid 值 |
3 | paxid |
long |
节点最后一次被修改时的事务ID |
4 | ctime |
long |
节点被创建的时间 |
5 | mtime |
long |
节点最后一次被修改时间 |
6 | dataVersoin |
long |
节点被修改的版本号(每次修改+1)(CAS 保证分布式数据原子性) |
7 | cversion |
long |
节点所拥有子节点被修改的版本号 |
8 | aversion |
long |
节点的ACL 被修改的版本号 |
9 | emphemeralOwner |
long |
如果此阶段为临时节点,这个值就是节点拥有者会话ID,否则0 |
10 | dataLength |
long |
节点数据域长度 |
umChildren |
long |
节点拥有的子节点个数 |
ACL
getAcl /xxx
查看xxx的权限1
2'world',anyone
:cdrwascheme
授权机制,id
用户id给谁授权,permissions
权限,只读、读写、管理等。- create(c)
- delete(d)
- read(r)
- write(w)
- admin(a) 是否能给子节点设置权限
机制有
world
,下面只有一个id
,叫anyone
,world:anyone
代表任何人,ZK
中对搜有人有权限的节点就是属于world:anyone
的auth
, 它不需要id
, 只需要通过authentication
的user
都有权限。ZK
支持通过kerberos
来进行authencation
,也支持username/password
形式的authentication
(明文)digest
, 通过对应的id为username:BASE64(SHA1(password))
, 它需要先通过username:password
形式的authentication
(密文)ip
, 它对应的id
为客户机的IP
地址,设置的时候可以设置一个ip
段,比如ip:192.168.1.0/16
,表示匹配16
个bit
的IP
段
常用ACL
命令
getAcl
获取指定节点的ACL
信息setAcl
设置指定节点的ACL
信息1
2
3addauth digest username:pwd # 添加用户(会话级别的,退出需要重新操作)
setAcl /xxx/zzz auth:username:pwd:crwa #给用户添加 auth机制的crwa权限
setAcl /xxx/zzz digest:username:xxxxmd5:crwa #digest机制的权限添加,密文生产在zookeeper自带的java类 DigestAuthenticationProvider里
addauth
注册绘画授权信息注册超级管理员用户可以解决没有权限不能删除的问题
使用
zkCli.sh -server ip
连接ZooKeeper
服务,连接成功后系统会输出相关环境及配置- 基本操作
- 显示根目录下、文件:
ls /
查看当前ZooKeeper
包含的内容 - 显示根目录下、文件:
ls2 /
查看当前节点数据并能看到更新次数等数据 - 创建文件,并设置初始内容。
create /zk "val"
创建一个新的znode
节点zk
,以及初始化内容-e 临时节点
(客户端端口就删除)-s 顺序节点
(名字自增) - 获取内容
get /zk
确认znode
是否包含我们所创建的字符串 - 修改
set /zk "val2"
修改节点内容 - 删除
delete /zk
将指定znode
删除,如果有子节点,删除失败 - 递归删除
rmr /zk
删除节点及子节点 - 退出
quit
- 显示根目录下、文件:
四字命令
zk
支持使用某些特点四字的命令交互获取服务当前状态,可通过telnet
或nc
提交命令
echo stat|nc ip port
查看那个节点被选择作为follower
或者leader
- 使用
echo ruok|nc ip port
测试是否启动了该server
若回复imok
表示已经启动 echo dump|nc ip port
列出未经处理的会话和临时节点echo kill |nc ip port
关闭serverecho conf | nc ip port
输出相关服务配置的详细信息echo cons | nc ip port
列出所有连接到服务器的客户端完全的连接/会话的详细信息echo envi|nc ip port
输出关于服务环境的详细信息echo reqs|nc ip port
列出未经处理的请求echo wchs|nc ip port
列出服务器watch
的详细信息echo wchc|nc ip port
通过session
列出服务器的watch
详细信息,输出的是一个与watch
相关会话的列表echo wchp|nc ip port
通过路径列出服务器的watch
的详细信息,输出的是与session
相关的路径
可视化
事务日志可视化
LogFormatter
1
java -cp ../../zookeeper-3.4.5.jar;../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.logFormatter log.xxx
数据快照可视化
SnapshotFormatter
1
java -cp ../../zookeeper-3.4.5.jar;../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.xxx
一致性原理
2pc
2pc 两段提交,强一致性算法。常用于分布式数据库中。
- 术语
undo
记录原始数据,用于回滚。redo
正常提交数据
流程
- 第一阶段,所有资源数据库都写入
undo
和redo
到事务日志- 第二阶段,所有资源都返回ok,则全部执行commit,否则rollback
- 第一阶段,所有资源数据库都写入
缺点
- 同步阻塞,所有都成功才能成功。
- 单点故障,一个返回失败,都失败
- 数据不一致,网络延迟导致一个资源commit了,另一个没有commit
- 容错机制不完善,一个失败都失败
- 同步阻塞,所有都成功才能成功。
3pc
先询问资源是否可以访问再进行2pc相同步骤
不一样的是第三阶段协调者如果网络超时或异常,参与者也会commit
优点
1. 改善同步阻塞(不会因为某些访问超时占用时间)
2. 解决单点故障
paxos算法
少数服从多数,角色轮换避免单点故障
第一阶段,提议者订一个K值,然后访问所有资源(prepare请求),多数回应ok就进行下一阶段,否则k+1再重新请求
第二阶段, 提交数据,绝大部分返回ok则整体成功,否则重新进行第一阶段
问题
- 主导者故障(单点故障)
- 最终一致性
协议要求
- 资源端必须接受第一个prepare
- 第一个prepare的数据必须要接受
多提议者情况下(解决单点故障)
若干提议者发起prepare,若多数资源同意则进入下一阶段。若同意没超过半数,则k增加再进行prepare。资源会同意更高K的prepare。当提议者认为自己的支持者超过半数就会进行第二阶段,
提交accept,如果资源在次期间遇到更高k的prepare,则会拒绝当前accept,等待最高k发起的提议者的accept。accept接受超过半数则成功,否则k增加,重新prepare。成功后全体接受成功的accept。
ZK使用
Zookeeper原生客户端
1 | <dependency> |
1 | private final static String CONNECT = "192.168.1.1:8088,xxxx";// 多个用逗号隔开 |
问题
- 会话连接是异步的
- watch需要重复注册,一次watch只能监听一个
- 缺少session重连机制
- 复杂,缺少很多功能,例如级联新增
ZkClient
1 | <dependency> |
1 | private final static String CONNECT_HOST = "192.168.1.1:8000"; |
Curator
1 | <dependency> |
1 | private final static String CONNECT_HOST="192.168.1.1:8000"; |
集群
特点
- 顺序一致性,命令执行顺序一致
- 原子性,集群中所有机器都成功,否则失败
- 单一视图,连接集群任意一个机器数据一致
- 可靠性,一个更新被操作之前,数据不变
- 实时性,一个节点更改,其他节点很短时间内同步
- 角色轮换,避免故障
角色
leader
任务调度,事务处理(增,删,改)follower
非事务请求,读。参与投票observer
观察者,读,不参与投票。(3.30以上提供,增加效率)
配置集群
zoo.cfg
1 | server.0=192.168.1.2:2333:2444 # 选举端口:通讯端口 |
ZAB协议
类似paxos
,zk
自己实现的协议