前言
关系数据库的ACID
- Atomicity原子性: 一个事务中所有操作都必须全部完成,要么全部不完成;
- Consistency一致性: 在事务开始或结束时,数据库应该在一致状态;
- Isolation隔离层: 事务间不影响;
- Durability持久性: 事务一旦完成必须持久化,不能返回。
SOA
面向服务的体系结构,将应用程序的不同功能单元(服务)分布在网络计算机上,并通过定义好的接口(协议)进行网络通讯。
CPA理论
- Consistency 一致性:
分布式数据视图必须一致 - Availability 可用性:
有限时间内必返回明确响应。正常的响应结果能够明确反映请求的处理结果 - Partition tolerance 分区容错性:
分布式系统在遇到任何网络分区故障仍能保证对外提供满足一致性和可用性的服务,除非整个网络环境都发生故障。
CA | 放弃分区容错性,加强一致性和可用性,其实就是传统的单机数据库的选择 |
AP | 放弃强一致性,追求分区容错性和可用性,这是很多分布式系统设计时的选择,例如很多NoSQL系统就是如此 |
CP | 放弃可用性,追求一致性和分区容错性,基本不会选择,网络问题会直接让整个系统不可用 |
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
BASE理论
- Basically Available 基本可用:
当异常时,保证主要功能不挂,或者响应稍微延时些; - Soft state 软状态:
可存在中间状态,不影响系统的整体可用性,即允许系统在不同节点的数据副本之间的数据同步存在延时; - Eventually consistent 最终一致性:
弱一致性,保证最终一致而不是实时一致
tip: 基于上述理论,如何做好HA(高可用集群),分布式系统间的信息同步,容灾?
Zookeeper
高性能分布式应用功能单元服务协调服务,分布式数据一致性解决方案。 主要用途: 统一命名服务、分布式锁、状态同步服务、集群管理、 分布式应用配置管理等。
特性
- 最终一致性: 无论连接在zookeeper集群中的哪个服务器,返回的视图都是一致的;
- 顺序性: 消息的传递保证FIFIO,且在每一台服务器上的顺序都是一样的;
- 原子性: 更新只能全部服务都成功或者失败,没有中间状态;
- 可靠传输: 消息被一台服务器接受,则肯定能被所有服务器接受;
- 实时性: 在一定时间内能获取服务端返回数据;
- 慢的或者失效的客户端不干预快的客户端的请求,使得每个客户端能有效等待。
存储结构
存储类似于文件目录格式的树型结构Znode,但存储在内存中。每个节点下保存stat对象(节点状态信息)。
Stat
用于保证分布式数据的原子性操作,表示对数据节点数据内容的变更次数,强调的是变更次数,因此就算数值没有发生变化,version的值也会递增。 Zookeeper的版本作用就是类似于乐观锁机制,用于实现乐观锁机制的“写入校验”。
- czxid:创建节点的事务的zxid
- mzxid: 最后修改时的zxid
- ctime:以距离时间原点(epoch)的毫秒数表示的znode创建时间
- mtime:以距离时间原点(epoch)的毫秒数表示的znode最近修改时间
- pzxid: 子节点列表最后一次被修改的事务ID, 只有子节点列表变更了才会更新pzxid,子节点内容变更不影响。
- cversion: znode子节点列表变更版本
- dataVersion: znode数据的修改版本
- aclVersion: znode的ACL修改版本
- ephemeralOwner: 若znode为临时节点,则指示节点所有者的会话ID;否则为零。
- dataLength: znode数据长度。
- numChildren: znode子节点个数。
znode类型
- 持久节点: 通常用来保存应用的持久化数据。 可用delete和rmr来删除。
- 临时节点: 不允许有子节点。除了客户端主动删除该节点时消失外,客户端会话失效会自动被清除掉,因此常用来检测会话的有效性。
- 有序节点: 创建时,一个会自动递增的序号会加到路径之后,
eg: 客户端创建一个有序znode并指定路径为/tasks/task,则第一个创建的节点是/tasks/task-0000000001,该节点消亡后再创建这样的节点会产生/tasks/task-0000000002,以此类推。有序znode提供了创建具有唯一命名的znode的方式。
常用命令
- create [-s] [-e] path data [acl]
-s或-e分别指定节点特性,顺序或临时节点,默认持久节点;acl用来进行权限控制 - delete path [version]
当有子节点时不能删除 - rmr path
递归删除节点 - set path data [version]
- getAcl / setAcl
- connect host:port
权限
- CREATE(c): 创建权限,可以在在当前node下创建child node;
- DELETE(d): 删除权限,可以删除当前的node;
- READ(r): 读权限,可以获取当前node的数据,可以list当前node所有的child nodes;
- WRITE(w): 写权限,可以向当前node写数据;
- ADMIN(a): 管理权限,可以设置当前node的permission;
ACL
- world
默认方式, world:anyone 都能访问 ;
- auth
代表已经认证通过的用户; - digest
用户名和密码进行认证. 对应为username:BASE64(SHA1(password)); - ip
客户机的IP地址
- 增加一个认证用户: addauth digest 用户名:密码明文
- 设置权限:
- setAcl /path digest:用户名:密码密文:权限
setAcl /path auth:用户名:密码明文:权限 <测试没发现怎么使用>
缺陷:ACL 并无递归机制,任何一个 znode 创建后,都需要单独设置 ACL,无法继承父节点的 ACL设置。
SuperDigest
修改 zkServer.sh <zkServer.cmd> 加入 super 权限后, 重启使用 super:super 进行认证:
-Dzookeeper.DigestAuthenticationProvider.superDigest=super:gG7s8t3oDEtIqF6DM9LlI/R+9Ss=
Zookeeper quota
支持节点个数( znode )和空间大小(字节数)。
- -n : 表示设置 节点个数的限制,包括 自己本身。
这里表示 /test 这个 path 下的 znode count 个数限制为 5 ; - -b : 表示设置 znode 数据的字节大小限制. 包括 自己本身。
看 zookeeper 的日志,发现有 Quota exceeded 的日志, zookeeper 的 Quota机制是比较温和的,即使超限了,只是在日志中报告一下,并不会限制 Client 的行为, Client 可以继续操作 znode 。在实际项目中, Client 可以查看 /zookeeper/quota 目录下的数据来确定是否超出 quota 限制,由此来做一些告警
限制
ZK单个node节点默认的最大数据量上限是1M
大于1M时拋异常:Unable to read additional data from server sessionid 0x15dd29d55b00004, likely server has closed socket, closing socket connection and attempting reconnect,
但是可以修改zkServer.sh启动脚本来调整这个阀值;