2018/1/22
1.大数据的概念:
指的是所涉及的数据量规模巨大到无法通过人工,在合理的时间内达到截取,管理,处理,并整理成人类所能解读的形式的信息的数据集合,几乎无法使用大多的数据管理系统进行管理
大数据的特点:volume(体量大),,variety(类型多),value(价值),velocity(速度快
2.数据仓库的概念:是一个面向主题的(Subject Oriented)、集成的(Integrate)、相对稳定的(Non-Volatile)、反映历史变化(Time Variant)的数据集合,用于支持管理决策。
3.分析(ETL)和挖掘的区别:数据分析输出的是统计结果,比如总计,平均值等,数据挖掘输出的是模型或规则
4.hadoop:对大量数据进行分布式处理的软件框架,由Apache开发的分布式基本框架,可以利用集群来进行高速运算和存储
2018/1/23
1.CAP和BASE
分布式领域CAP理论,
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容忍性) 可靠性
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。
关系数据库的ACID模型拥有 高一致性 + 可用性很难进行分区:
Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。
Durability. 一旦事务完成,就不能返回。
跨数据库两段提交事务:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的,JavaEE中的JTA事务可以支持2PC。因为2PC是反模式,尽量不要使用2PC,使用BASE来回避。
Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)
Soft state软状态 状态可以有一段时间不同步,异步。
Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。
BASE思想的主要实现有
1.按功能划分数据库 2.sharding碎片
BASE思想主要强调基本的可用性,如果你需要High 可用性,也就是纯粹的高性能,那么就要以一致性或容忍性为牺牲,BASE思想的方案在性能上还是有潜力可挖的。
现在NOSQL运动丰富了拓展了BASE思想,可按照具体情况定制特别方案,比如忽视一致性,获得高可用性等等,NOSQL应该有下面两个流派:
1. Key-Value存储,如Amaze Dynamo等,可根据CAP三原则灵活选择不同倾向的数据库产品。
2. 领域模型 + 分布式缓存 + 存储 (Qi4j和NoSql运动),可根据CAP三原则结合自己项目定制灵活的分布式方案,难度高。
这两者共同点:都是关系数据库SQL以外的可选方案,逻辑随着数据分布,任何模型都可以自己持久化,将数据处理和数据存储分离,将读和写分离,存储可以是异步或同步,取决于对一致性的要求程度。
不同点:NOSQL之类的Key-Value存储产品是和关系数据库头碰头的产品BOX,可以适合非Java如PHPRUBY等领域,是一种可以拿来就用的产品,而领域模型 + 分布式缓存 + 存储是一种复杂的架构解决方案,不是产品,但这种方式更灵活,更应该是架构师必须掌握的。
2.数据分割
数据分割是指把逻辑上是统一整体的数据分割成较小的、可以独立管理的物理单元进行存储,以便于重构、重组和恢复,以提高创建索引和顺序扫描的效率。数据分割使数据仓库的开发人员和使用者具有更大的灵活性,具有容易重构、自由索引、顺序扫描、容易重组、容易恢复和容易监控等优点
,分类方法有水平分割和垂直分割,
数据分割的层次:分割的层次一般分为系统层和应用层。系统层的分割由数据库管理系统和操作系统完成;应用层的分割由应用系统完成,在应用层上的分割更有意义3.副本策略---primary---secondary协议,paxos协议----通过面试
副本控制协议指按特定的协议流程控制副本数据的读写行为,使得副本满足一定的可用性和一致性要求的分布式协议。副本控制协议可以分为两大类“中心化(centralized)副本控制协议”和“去中心化(decentralized)副本控制协议”。中心化副本控制协议的基本思路:由一个中心节点协调副本数据的更新、维护副本之间的一致性。所有副本相关的控制交由中心节点完成,并发控制由中心节点完成,从而简化一个分布式并发控制问题为一个单机并发控制问题。而所谓并发控制,即多个节点同时需要修改副本数据时,需要解决“WW”,"RW"等并发冲突。其结构如图1所示。
Fig. 1中心化副本控制
Primary-secondary协议
该协议是中心化副本控制协议中常常用到的,该协议将副本分为两大类:其中有且仅有一个副本作为primary副本,除primary意外的副本都作为secondary副本。维护primary副本的节点作为中心节点,中心节点负责维护数据的更新、并发控制、协同副本的一致性。
(1)数据更新基本流程
1.数据更新都由primary节点协调完成
2.外部节点将更新操作发给primary节点
3.primary节点进行并发控制即确定并发更新操作的先后顺序
4.primary节点将更新操作发送给secondary节点
5.primary根据secondary节点的完成情况决定更新是否成功并将结果返回外部节点
(2)数据读取方式
与数据更新流程类似,读取方式也与一致性高度相关。使用primary-secondary比较困难的是实现强一致性。实现强一致性一般有如下几个思路:
1.始终只读primary副本的数据
2.由primary控制节点secondary节点的可用性。
3.基于Quorum机制
(3)Primary副本的确定和切换
primary副本的确定通常由原信息管理,由专门的元数据服务器维护,执行更新操作时,首先查询元数据服务器获取副本的primary信息,从而进一步执行数据更新流程。
primary副本的切换通常可以使用lease机制来完成。
(4)数据同步
数据同步是因为primary副本可能会存在于secondary副本不一致的问题。通常有如下三种形式:
1.由于网络分化等异常,secondary上的数据落后于primary上的数据。—— redo primary副本上的操作日志。
2.在某些协议下,secondary上的数据有可能是脏数据,需要被丢弃。—— undo日志的方法删除脏数据
3.secondary是一个新增加的副本,完全没有数据,需要从其他副本上拷贝数据。—— 使用primary副本的snapshot(快照)功能
Paxos算法是莱斯利·兰伯特(LeslieLamport)1990年提出的一种基于消息传递的一致性算法。
Paxos算法解决的问题是一个分布式系统如何就某个值(决议)达成一致。在工程实践意义上来说,就是可以通过Paxos实现多副本一致性,分布式锁,名字管理,序列号分配等。比如,在一个分布式数据库系统中,如果各节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能得到一个一致的状态。为保证每个节点执行相同的命令序列,需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。本文首先会讲原始的Paxos算法(Basic Paxos),主要描述二阶段提交过程,然后会着重讲Paxos算法的变种(Multi Paxos),它是对Basic Paxos的优化,而且更适合工程实践,最后我会通过Q&A的方式,给出我在学习Paxos算法中的疑问,以及我对这些疑问的理解。
概念与术语
Proposer:提议发起者,处理客户端请求,将客户端的请求发送到集群中,以便决定这个值是否可以被批准。
Acceptor:提议批准者,负责处理接收到的提议,他们的回复就是一次投票,会存储一些状态来决定是否接收一个值。
replica:节点或者副本,分布式系统中的一个server,一般是一台单独的物理机或者虚拟机,同时承担paxos中的提议者和接收者角色。
ProposalId:每个提议都有一个编号,编号高的提议优先级高。
Paxos Instance:Paxos中用来在多个节点之间对同一个值达成一致的过程,比如同一个日志序列号:logIndex,不同的logIndex属于不同的Paxos Instance。
acceptedProposal:在一个Paxos Instance内,已经接收过的提议
acceptedValue:在一个Paxos Instance内,已经接收过的提议对应的值。
minProposal:在一个Paxos Instance内,当前接收的最小提议值,会不断更新
Basic-Paxos算法
基于Paxos协议构建的系统,只需要系统中超过半数的节点在线且相互通信正常即可正常对外提供服务。它的核心实现Paxos Instance主要包括两个阶段:准备阶段(prepare phase)和提议阶段(accept phase)。如下图所示:
1.获取一个ProposalId,为了保证ProposalId递增,可以采用时间戳+serverId方式生成;
2.提议者向所有节点广播prepare(n)请求;
3.接收者比较n和minProposal,如果n>minProposal,表示有更新的提议,minProposal=n;否则将(acceptedProposal,acceptedValue)返回;
4.提议者接收到过半数请求后,如果发现有acceptedValue返回,表示有更新的提议,保存acceptedValue到本地,然后跳转1,生成一个更高的提议;
5.到这里表示在当前paxos instance内,没有优先级更高的提议,可以进入第二阶段,广播accept(n,value)到所有节点;
6.接收者比较n和minProposal,如果n>=minProposal,则acceptedProposal=minProposal=n,acceptedValue=value,本地持久化后,返回;
否则,返回minProposal
7.提议者接收到过半数请求后,如果发现有返回值>n,表示有更新的提议,跳转1;否则value达成一致。
从上述流程可知,并发情况下,可能会出现第4步或者第7步频繁重试的情况,导致性能低下,更严重者可能导致永远都无法达成一致的情况,就是所谓的“活锁”,如下图所示
1.S1作为提议者,发起prepare(3.1),并在S1,S2和S3达成多数派;
2.随后S5作为提议者 ,发起了prepare(3.5),并在S3,S4和S5达成多数派;
3.S1发起accept(3.1,value1),由于S3上提议 3.5>3.1,导致accept请求无法达成多数派,S1尝试重新生成提议
4.S1发起prepare(4.1),并在S1,S2和S3达成多数派
5.S5发起accpet(3.5,value5),由于S3上提议4.1>3.5,导致accept请求无法达成多数派,S5尝试重新生成提议
6.S5发起prepare(5.5),并在S3,S4和S5达成多数派,导致后续的S1发起的accept(4.1,value1)失败
......
prepare阶段的作用
从Basic-Paxos的描述可知,需要通过两阶段来最终确定一个值,由于轮回多,导致性能低下,至少两次网络RTT。那么prepare阶段能否省去?如下图所示:
1.S1首先发起accept(1,red),并在S1,S2和S3达成多数派,red在S1,S2,S3上持久化
2.随后S5发起accept(5,blue),对于S3而言,由于接收到更新的提议,会将acceptedValue值改为blue
3.那么S3,S4和S5达成多数派,blue在S3,S4和S5持久化
4.最后的结果是,S1和S2的值是red,而S3,S4和S5的值是blue,没有达成一致。
所以两阶段必不可少,Prepare阶段的作用是阻塞旧的提议,并且返回已经接收到的acceptedProposal。同时也可以看到的是,假设只有S1提议,则不会出现问题,这就是我们下面要讲的Multi-Paxos。
Multi-paxos算法
Paxos是对一个值达成一致,Multi-Paxos是连续多个paxos instance来对多个值达成一致,这里最核心的原因是multi-paxos协议中有一个Leader。Leader是系统中唯一的Proposal,在lease租约周期内所有提案都有相同的ProposalId,可以跳过prepare阶段,议案只有accept过程,一个ProposalId可以对应多个Value,所以称为Multi-Paxos。
选举
首先我们需要有一个leader,其实选主的实质也是一次Paxos算法的过程,只不过这次Paxos确定的“谁是leader”这个值。由于任何一个节点都可以发起提议,在并发情况下,可能会出现多主的情况,比如A,B先后当选为leader。为了避免频繁选主,当选leader的节点要马上树立自己的leader权威(让其它节点知道它是leader),写一条特殊日志(start-working日志)确认其身份。根据多数派原则,只有一个leader的startworking日志可以达成多数派。leader确认身份后,可以通过了lease机制(租约)维持自己的leader身份,使得其它proposal不再发起提案,这样就进入了leader任期,由于没有并发冲突,因此可以跳过prepare阶段,直接进入accept阶段。通过分析可知,选出leader后,leader任期内的所有日志都只需要一个网络RTT(Round Trip Time)即可达成一致。
新主恢复流程
由于Paxos中并没有限制,任何节点都可以参与选主并最终成为leader,这就无法保证新选出的leader包含了所有日志,可能存在空洞,因此在真正提供服务前,还存在一个获取所有已提交日志的恢复过程。新主向所有成员查询最大logId的请求,收到多数派响应后,选择最大的logId作为日志恢复结束点,这里多数派的意义在于恢复结束点包含了所有达成一致的日志,当然也可能包含了没有达成多数派的日志。拿到logId后,从头开始对每个logId逐条进行paxos协议,因为在新主获得所有日志之前,系统是无法提供服务的。为了优化,引入了confirm机制,就是将已经达成一致的logId告诉其它acceptor,acceptor写一条confirm日志到日志文件中。那么新主在重启后,扫描本地日志,对于已经拥有confirm日志的log,就不会重新发起paxos了。同样的,在响应客户端请求时,对于没有confirm日志的log,需要重新发起一轮paxos。由于没有严格要求confirm日志的位置,可以批量发送。为了确保重启时,不需要对太多已提价的log进行paxos,需要将confirm日志与最新提交的logId保持一定的距离。
性能优化
Basic-Paxos一次日志确认,需要至少2次磁盘写操作(prepare,promise)和2次网络RTT(prepare,promise)。Multi-Paxos利用一阶段提交(省去Prepare阶段),将一次日志确认缩短为一个RTT和一次磁盘写;通过confirm机制,可以缩短新主的恢复时间。为了提高性能,我们还可以实现一批日志作为一个组提交,要么成功一批,要么都不成功,这点类似于group-commit,通过RT换取吞吐量。
安全性(异常处理)
1.Leader异常
Leader在任期内,需要定期给各个节点发送心跳,已告知它还活着(正常工作),如果一个节点在超时时间内仍然没有收到心跳,它会尝试发起选主流程。Leader异常了,则所有的节点先后都会出现超时,进入选主流程,选出新的主,然后新主进入恢复流程,最后再对外提供服务。我们通常所说的异常包括以下三类:
(1).进程crash(OS crash)
Leader进程crash和Os crash类似,只要重启时间大于心跳超时时间都会导致节点认为leader挂了,触发重新选主流程。
(2).节点网络异常(节点所在网络分区)
Leader网络异常同样会导致其它节点收不到心跳,但有可能leader是活着的,只不过发生了网络抖动,因此心跳超时不能设置的太短,否则容易因为网络抖动造成频繁选主。另外一种情况是,节点所在的IDC发生了分区,则同一个IDC的节点相互还可以通信,如果IDC中节点能构成多数派,则正常对外服务,如果不能,比如总共4个节点,两个IDC,发生分区后会发现任何一个IDC都无法达成多数派,导致无法选出主的问题。因此一般Paxos节点数都是奇数个,而且在部署节点时,IDC节点的分布也要考虑。
(3).磁盘故障
前面两种异常,磁盘都是OK的,即已接收到的日志以及对应confirm日志都在。如果磁盘故障了,节点再加入就类似于一个新节点,上面没有任何日志和Proposal信息。这种情况会导致一个问题就是,这个节点可能会promise一个比已经promise过的最大proposalID更小的proposal,这就违背了Paxos原则。因此重启后,节点不能参与Paxos Instance,它需要先追上Leader,当观察到一次完整的paxos instance时该节点结束不能promise/ack状态。
2.Follower异常(宕机,磁盘损坏等)
对于Follower异常,则处理要简单的多,因为follower本身不对外提供服务(日志可能不全),对于leader而言,只要能达成多数派,就可以对外提供服务。follower重启后,没有promise能力,直到追上leader为止。
Q&A
1.Paxos协议数据同步方式相对于基于传统1主N备的同步方式有啥区别?
一般情况下,传统数据库的高可用都是基于主备来实现,1主1备2个副本,主库crash后,通过HA工具来进行切换,提升备库为主库。在强一致场景下,复制可以开启强同步,Oracle和Mysql都是类似的复制模式。但是如果备库网络抖动,或者crash,都会导致日志同步失败,服务不可用。为此,可以引入1主N备的多副本形式,我们对比都是3副本的情况,一个是基于传统的1主2备,另一种基于paxos的1主2备。传统的1主两备,进行日志同步时,只要有一个副本接收到日志并就持久化成功,就可以返回,在一定程度上解决了网络抖动和备库crash问题。但如果主库出问题后,还是要借助于HA工具来进行切换,那么HA切换工具的可用性如何来保证又成为一个问题。基于Paxos的多副本同步其实是在1主N备的基础上引入了一致性协议,这样整个系统的可用性完全有3个副本控制,不需要额外的HA工具。而实际上,很多系统为了保证多节点HA工具获取主备信息的一致性,采用了zookeeper等第三方接口来实现分布式锁,其实本质也是基于Paxos来实现的。
我这里以MySQL的主备复制一套体系为例来具体说明传统的主备保持强一致性的一些问题。整个系统中主要包含以下几种角色:Master,Slave,Zookeeper-Service(zk),HA-Console(HA),Zookeeper-Agent(Agent)
Master,Slave:分别表示主节点和备节点,主节点提供读写服务,备节点可以提供读服务,或者完全用于容灾。
Zookeeper-Service(zk):分布式一致性服务,负责管理Master/Slave节点的存活信息和切换信息。zk基于zab协议,zab协议是一种一致性协议,与paxos,raft协议类似,它主要有两种模式,包括恢复模式(选主)和广播模式(同步)。一般zk包含N个节点(zk-node),只要有超过半数的zk-node存活且相互连通,则zk可以对外提供一致性服务。
HA-Console:切换工具,负责具体的切换流程
Zookeeper-Agent(Agent):Master/Slave实例上的监听进程,与监听的实例保持心跳,维护Master/Slave的状态,每个实例有一个对应的Agent。大概工作流程如下:
(1).Master/Slave正常启动并搭建好了复制关系,对应的Agent会调用zk接口去注册alive节点信息,假设分别为A和B。
(2).如果此时Master Crash,则实例对应的Agent发现心跳失败,如果重试几次后仍然失败,则将调用zk接口注销掉A节点信息。
(3).HA工具通过zk接口比较两次的节点信息,发现少了A节点,表示A可能不存在了,需要切换,尝试连接A,如果仍然不通,注册A的dead节点,并开始切换流程。
(4).HA工具读取配置信息,找到对应的Slave节点B,(更改读写比配置信息,设置B提供写),打开写。
(5).应用程序通过拉取最新的配置信息,得知新主B,新的写入会写入B。
前面几部基本介绍了MySQL借助zk实现高可用的流程,由于zk-node可以多地部署,HA无状态,因此可以很容易实现同城或者是异地的高可用系统,并且动态可扩展,一个HA节点可以同时管理多个Master/Slave的切换。那么能保证一致性吗?前面提到的Agent除了做监听,还有一个作用是尽可能保持主备一致,并且不丢数据。
(6).假设此时A节点重启,Agent检测到,通过zk接口发现A节点在dead目录下,表示被切换过,需要kill上面的所有连接,并回滚crash时A比B多的binlog,为了尽可能的少丢数据,然后再开启binlog后,将这部分数据重做。这里要注意rollback和replay都在old-Master上面进行,rollback时需要关闭binlog,而replay需要开启binlog,保证这部分数据能流向new-Master。
(7).从第6步来看,可以一定程度上保证主备一致性,但是进行rollback和replay时,实际上是往new-Slave上写数据,这一定程度上造成了双写,如果此时new—Master也在写同一条记录,可能会导致写覆盖等问题。
(8).如果开启半同步呢?old-Master crash时,仍然可能比old-Slave多一个group的binlog,所以仍然需要借助于rollback和replay,依然避免不了双写,所以也不能做到严格意义上的强一致。
2.分布式事务与Paxos协议的关系?
在数据库领域,提到分布式系统,就会提到分布式事务。Paxos协议与分布式事务并不是同一层面的东西。分布式事务的作用是保证跨节点事务的原子性,涉及事务的节点要么都提交(执行成功),要么都不提交(回滚)。分布式事务的一致性通常通过2PC来保证(Two-Phase Commit, 2PC),这里面涉及到一个协调者和若干个参与者。第一阶段,协调者询问参与者事务是否可以执行,参与者回复同意(本地执行成功),回复取消(本地执行失败)。第二阶段,协调者根据第一阶段的投票结果进行决策,当且仅当所有的参与者同意提交事务时才能提交,否则回滚。2PC的最大问题是,协调者是单点(需要有一个备用节点),另外协议是阻塞协议,任何一个参与者故障,都需要等待(可以通过加入超时机制)。Paxos协议用于解决多个副本之间的一致性问题。比如日志同步,保证各个节点的日志一致性,或者选主(主故障情况下),保证投票达成一致,选主的唯一性。简而言之,2PC用于保证多个数据分片上事务的原子性,Paxos协议用于保证同一个数据分片在多个副本的一致性,所以两者可以是互补的关系,绝不是替代关系。对于2PC协调者单点问题,可以利用Paxos协议解决,当协调者出问题时,选一个新的协调者继续提供服务。工程实践中,Google Spanner,Google Chubby就是利用Paxos来实现多副本日志同步。
3.如何将Paxos应用于传统的数据库复制协议中?
复制协议相当于是对Paxos的定制应用,通过对一系列日志进行投票确认达成多数派,就相当于日志已经在多数派持久化成功。副本通过应用已经持久化的日志,实现与Master节点同步。由于数据库ACID特性,本质是由一个一致的状态到另外一个一致的状态,每次事务操作都是对应数据库状态的变更,并生成一条日志。由于client操作有先后顺序,因此需要保证日志的先后的顺序,在任何副本中,不仅仅要保证所有日志都持久化了,而且要保证顺序。对于每条日志,通过一个logID标示,logID严格递增(标示顺序),由leader对每个日志进行投票达成多数派,如果中途发生了leader切换,对于新leader中logID的“空洞”,需要重新投票,确认日志的有效性。
4.Multi-Paxos的非leader节点可以提供服务吗?
Multi-Paxos协议中只有leader确保包含了所有已经已经持久化的日志,当然本地已经持久化的日志不一定达成了多数派,因此对于没有confirm的日志,需要再进行一次投票,然后将最新的结果返回给client。而非leader节点不一定有所有最新的数据,需要通过leader确认,所以一般工程实现中,所有的读写服务都由leader提供。
5.客户端请求过程中失败了,如何处理?
client向leader发起一次请求,leader在返回前crash了。对于client而言,这次操作可能成功也可能失败。因此client需要检查操作的结果,确定是否要重新操作。如果leader在本地持久化后,并没有达成多数派时就crash,新leader首先会从各个副本获取最大的logID作为恢复结束点,对于它本地没有confirm的日志进行Paxos确认,如果此时达成多数派,则应用成功,如果没有则不应用。client进行检查时,会知道它的操作是否成功。当然具体工程实践中,这里面涉及到client超时时间,以及选主的时间和日志恢复时间。
分布式领域CAP理论,Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容忍性) 可靠性
定理:任何分布式系统只可同时满足二点,没法三者兼顾。
忠告:架构师不要将精力浪费在如何设计能满足三者的完美分布式系统,而是应该进行取舍。
关系数据库的ACID模型拥有 高一致性 + 可用性很难进行分区:
Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。
Durability. 一旦事务完成,就不能返回。
跨数据库两段提交事务:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸缩模式的,JavaEE中的JTA事务可以支持2PC。因为2PC是反模式,尽量不要使用2PC,使用BASE来回避