“学好分布式架构”节目做到第四期了,👏👏👏
想要解锁更多新姿势?请访问我的博客
分布式概念(前戏)
了解一个技术,先要掌握它的理论,然后循序渐进。所以,理论来了~
什么是分布式呢?简单说,分布式系统背后是由一系列的计算机组成的,但用户感知不到背后的逻辑,就像访问单个计算机一样
最基本的特点
分布性
服务器的位置可能在不一个位置
并发性
程序运行过程中,并发性操作是很常见的。比如同一个分布式系统中的多个节点,同时访问一个共享资源。数据库、分布式存储
无序性
进程之间的消息通信,会出现顺序不一致问题
分布式环境下面临的问题
分布式的特点决定了它一定会有相应的问题
网络通信
分布式系统的信息通过网络来传输的,而网络本身的不可靠性,因此会涉及到一些网络通信问题
网络分区(脑裂)
什么是脑裂呢?
在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出了故障。两个节点上的HA软件像“裂脑人”一样,争抢“共享资源”、争起“应用服务”,就会发生严重后果——或者共享资源被瓜分、2边“服务”都起不来了;或者2边“服务”都起来了,但同时读写“共享存储”,导致数据损坏(常见如数据库轮询着的联机日志出错)。
而当网络发生异常导致分布式系统中部分节点之间的网络延时不断增大,就会产生脑裂现象,即组成分布式架构的所有节点,只有部分节点能够正常通信
三态
在正常的单机环境下,一个程序调用一个接口,正常情况下只有2个状态,成功态和失败态。 但是在分布式环境下,就又多了一种状态,叫做超时态,指的就是在分布式网路通信时,因为网络故障,我的消息一直没有收到返回或者是我的消息没有发送出去。
分布式事务
分布式也会有事物问题,即ACID(原子性、一致性、隔离性、持久性)。譬如,如果两台分布式架构的服务器有这相同的功能,当用户操作的时候,你要保存这两台服务器的同时发生同时成功,这就属于事物问题。
1.原子性(Atomicity)
一个原子事务要么完整执行,要么干脆不执行。这意味着,工作单元中的每项任务都必须正确执行。如果有任一任务执行失败,则整个工作单元或事务就会被终止。即此前对数据所作的任何修改都将被撤销。如果所有任务都被成功执行,事务就会被提交,即对数据所作的修改将会是永久性的。
2.一致性(Consistency)
一致性代表了底层数据存储的完整性。它必须由事务系统和应用开发人员共同来保证。事务系统通过保证事务的原子性,隔离性和持久性来满足这一要求; 应用开发人员则需要保证数据库有适当的约束(主键,引用完整性等),并且工作单元中所实现的业务逻辑不会导致数据的不一致(即,数据预期所表达的现实业务情况不相一致)。例如,在一次转账过程中,从某一账户中扣除的金额必须与另一账户中存入的金额相等。
3.隔离性(Isolation)
隔离性意味着事务必须在不干扰其他进程或事务的前提下独立执行。换言之,在事务或工作单元执行完毕之前,其所访问的数据不能受系统其他部分的影响。
4.持久性(Durability)
持久性表示在某个事务的执行过程中,对数据所作的所有改动都必须在事务成功结束前保存至某种物理存储设备。这样可以保证,所作的修改在任何系统瘫痪时不至于丢失。
中心化和去中心化
数据库备份一般使用冷备或者热备
热备:一般用于保证服务正常不间断运行,用两台机器作为服务机器,一台用于实际数据库操作应用,另外一台实时的从前者中获取数据以保持数据一致.如果当前的机器熄火,备份的机器立马取代当前的机器继续提供服务
冷备:.冷备份指在数据库关闭后,进行备份,适用于所有模式的数据库
分布式架构里面,很多的架构思想采用的是去中心化。即在一个分布有众多节点的系统中,每个节点都具有高度自治的特征。节点之间彼此可以自由连接,形成新的连接单元。任何一个节点都可能成为阶段性的中心,但不具备强制性的中心控制功能。节点与节点之间的影响,会通过网络而形成非线性因果关系。这种开放式、扁平化、平等性的系统现象或结构,我们称之为去中心化
最典型的是: zookeeper / etcd
经典的CAP
C一致性 (Consistency): 所有节点上的数据,时刻保持一致
A可用性(Availability):每个请求都能够收到一个响应,无论响应成功或者失败
P分区容错 (Partition-tolerance):表示系统出现脑裂以后,可能导致某些server与集群中的其他机器失去联系
无论如何,都只能保证CP或者 AP。CAP理论仅适用于原子读写的Nosql场景,不适用于数据库系统
BASE理论
基于CAP理论,CAP理论并不适用于数据库事务(因为更新一些错误的数据而导致数据出现紊乱,无论什么样的数据库高可用方案都是徒劳) ,虽然XA事务可以保证数据库在分布式系统下的ACID特性,但是会带来性能方面的影响;
eBay尝试了一种完全不同的套路,放宽了对事务ACID的要求。提出了BASE理论:
Basically available : 数据库采用分片模式, 把100W的用户数据分布在5个实例上。如果破坏了其中一个实例,仍然可以保证
80%的用户可用
soft-state: 在基于client-server模式的系统中,server端是否有状态,决定了系统是否具备良好的水平扩展、负载均衡、故障恢复等特性。
Server端承诺会维护client端状态数据,这个状态仅仅维持一小段时间, 这段时间以后,server端就会丢弃这个状态,恢复正常状态
Eventually consistent:数据的最终一致性
是
Zookeeper(正片)
zookeeper是一个开源的分布式数据存储系统,提供分布式数据一致性的解决方案。是由雅虎创建的,基于google chubby。
zookeeper是什么
分布式数据一致性的解决方案
zookeeper能做什么
数据的发布/订阅(配置中心:disconf) 、 负载均衡(dubbo利用了zookeeper机制实现负载均衡) 、命名服务、
master选举(kafka、hadoop、hbase)、分布式队列、分布式锁
zookeeper特性
顺序一致性
从同一个客户端发起的事务请求,最终会严格按照顺序被应用到zookeeper中
原子性
所有的事务请求的处理结果在整个集群中的所有机器上的应用情况是一致的,也就是说,要么整个集群中的所有机器都成功应用了某一事务、要么全都不应用
可靠性
一旦服务器成功应用了某一个事务数据,并且对客户端做了响应,那么这个数据在整个集群中一定是同步并且保留下来的
实时性
一旦一个事务被成功应用,客户端就能够立即从服务器端读取到事务变更后的最新数据状态;(zookeeper仅仅保证在一定时间内,近实时)
zookeeper集群环境
zookeeper集群, 包含三种角色: leader / follower /observer
observer
observer 是一种特殊的zookeeper节点。可以帮助解决zookeeper的扩展性(如果大量客户端访问我们zookeeper集群,需要增加zookeeper集群机器数量。从而增加zookeeper集群的性能。 导致zookeeper写性能下降, zookeeper的数据变更需要半数以上服务器投票通过。造成网络消耗增加投票成本)
observer不参与投票。 只接收投票结果。不和follower联系。
不属于zookeeper的关键部位。
安装zookeeper
可以虚拟机中操作,系统centos7,zookeeper去官方网下稳定版。安装后:
第一步: 修改配置文件zoo.cfg
server.id=host:port:port
id的取值范围: 1~255; 用id来标识该机器在集群中的机器序号;
2888是表示follower节点与leader节点交换信息的端口号,要定义成和系统没有冲突的端口号;
3181 表示leader选举的端口,如果leader节点挂掉了, 需要一个端口来重新选举
栗子:
server.1=192.168.11.129:2888:3181
server.2=192.168.11.131:2888:3181
server.3=192.168.11.135:2888:3181
如果需要增加observer节点,zoo.cfg中,增加 ;peerType=observer
server.1=192.168.11.129:2888:3181
server.2=192.168.11.135:2888:3181
server.3=192.168.111.136:2888:3181:observer
第二步:创建myid
在每一个服务器的dataDir目录下创建一个myid的文件,文件就一行数据,数据内容是每台机器对应的server ID的数字
第三步:启动zookeeper
关掉防火墙
看到生成zeekeeper.out
这样的一个日志,可以使用tail
命令查看
Zookeeper中的一些概念
Zookeeper配置解析
tickTime=2000
zookeeper中最小的时间单位长度 (ms)
initLimit=10
follower节点启动后与leader节点完成数据同步的时间
syncLimit
=5 leader节点和follower节点进行心跳检测的最大延时时间
dataDir
=/tmp/zookeeper 表示zookeeper服务器存储快照文件的目录
dataLogDir
表示配置 zookeeper事务日志的存储路径,默认指定在dataDir目录下
clientPort
表示客户端和服务端建立连接的端口号: 2181
数据模型
zookeeper
的数据模型和文件系统类似,每一个节点称为:znode
. 是zookeeper中的最小数据单元。每一个znode
上都可以保存数据和挂载子节点。 从而构成一个层次化的属性结构
节点特性
持久化节点 : 节点创建后会一直存在zookeeper
服务器上,直到主动删除
持久化有序节点 :每个节点都会为它的一级子节点维护一个顺序
临时节点 : 临时节点的生命周期和客户端的会话保持一致。当客户端会话失效,该节点自动清理
临时有序节点 : 在临时节点上多勒一个顺序性特性
会话
客户端和zookeeper
会建立一个连接,这就是一个会话。
会话有什么过程呢?
Watcher(监听)
zookeeper
提供了分布式数据发布/订阅,zookeeper
允许客户端向服务器注册一个watcher
监听。当服务器端的节点触发指定事件的时候,会触发watcher
。服务端会向客户端发送一个事件通知 watcher
的通知是一次性,一旦触发一次通知后,该watcher
就失效
ACL
zookeeper
提供控制节点访问权限的功能,用于有效的保证zookeeper
中数据的安全性。避免误操作而导致系统出现重大事故。
提供了:CREATE /READ/WRITE/DELETE/ADMIN
Zookeeper命令操作(增删改查)
create [-s] -e path data acl
-s 表示节点是否有序
-e 表示是否为临时节点
(默认情况下,是持久化节点)
1 | create /zoo #创建zoo节点 |
get path [watch]
获得指定 path的信息
3.set path data [version]
修改节点 path对应的data
version
表示乐观锁,及数据库中有一个version字段去控制数据行的版本号
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。而乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本( Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
4.delete path [version]
删除节点
节点状态stat信息
cversion
= 0 子(child)节点的版本号
aclVersion
= 0 表示acl的版本号,修改节点权限
dataVersion
= 1 表示的是当前节点数据的版本号
czxid
节点被创建时的事务ID
mzxid
节点最后一次被更新的事务ID
pzxid
当前节点下的子节点最后一次被修改时的事务ID
ctime
= 创建时间
mtime
= 修改时间
ephemeralOwner
= 0x0 创建临时节点的时候,会有一个sessionId 。 该值存储的就是这个sessionid 。0X0代表无
dataLength
= 3 数据值长度
numChildren
= 0 子节点数
在Java中使用zookeeper
引入依赖
1 | <dependency> |
困了,睡觉。明天再码字。未完待续。。。。。
参考
感谢
结束
此片完了~ 想要了解更多精彩新姿势?
请访问我的个人博客 本篇为原创内容,已在个人博客率先发表,随后CSDN,segmentfault,掘金,简书,开源中国同步发出。如有雷同,缘分呢兄弟。赶快加个好友,咱们两个想个号码, 买个彩票,先挣他个几百万😝