架构师训练营第 0 期第六周学习总结

用户头像
Albert
关注
发布于: 2020 年 07 月 15 日

本周的主要内容



1、关系型数据库分片

1-1、为什么要做分片(问题)?

一般做数据库分片有两个原因:

  • 单个数据库服务器数据量过大,单表的数据量太大;

  • 单个数据库读写访问的IO已经达到上限;

单个数据库服务器达到物理极限,无法再通过升级硬件方式解决上面两个问题,这时候需要做数据分片;



1-2、数据分片的挑战

  • 需要大量额外代码,处理逻辑变复杂;

  • 无法执行多分片联合查询;

  • 无法使用数据库事务;

  • 随着数据量再增加,数据库服务器如何扩容;



1-3、数据分片的实现方法

1-3-1、硬编码实现

优点:实现较为简单

缺点:分片实现逻辑与代码耦合



1-3-2、使用映射表

优点:较为灵活,可以按多个方式进行分片,ID和库的Mapping算法可以随意更改;

缺点:1、查询次数增加(先查映射表再查数据表);2、实现复杂;3、映射表单点问题;



1-3-3、数据库中间件

常用的数据库中间件:MyCAT 和 Apache ShardingSphere

优点:对于应用程序比较透明;路由选择比侵入业务逻辑;不需要额外代码维护;



1、MyCAT的架构





2、Apache ShardingSphere

Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款相互独立,却又能够混合部署配合使用的产品组成。 它们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。

Apache ShardingSphere 定位为关系型数据库中间件,旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。



2-1、Sharding JDBC架构

定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。



  • 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。

  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。

  • 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。





2-2、Sharding Proxy架构

定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前先提供MySQL/PostgreSQL版本,它可以使用任何兼容MySQL/PostgreSQL协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat等)操作数据,对DBA更加友好。



  • 向应用程序完全透明,可直接当做MySQL/PostgreSQL使用。

  • 适用于任何兼容MySQL/PostgreSQL协议的的客户端。





2-3、Sharding-JDBC和Sharding-Proxy比较



1-3-4、数据库集群伸缩解决方案

基本实现算法:余数Hash

具体操作:

1、一个数据库服务器上有多个实例;

2、当单个实例需要扩容时,只需要将对应Schema直接迁移到新的SQL上;

3、数据库迁移完成,再修改代码中的数据路由规则,数据库连接指向新的数据库;



1-4、数据库部署架构演化过程

1-4-1、单一服务与单一数据库

系统刚开始,访问和请求压力较小,业务逻辑也比较简单,此时只需要单个数据库就好;



1-4-2、读写分离

当数据库读写IO较大时,可以使用读写分离,主机负责写请求,丛机负责读请求;



1-4-3、业务服务数据库分离

当业务越来越复杂,在一个系统开发部署难度增大,代码变多时,这时就需要对业务进行拆分,数据库压力增大,也对业务数据拆分;



1-4-4、数据库分片

当一个业务的数据库读写压力达到瓶颈,此时就要对单个业务的数据库进行分片处理;



1-4-5、综合部署

对于访问量较大的业务,数据库需要进行数据库分片;

对于访问数据量较小,或者数据量较小的业务,只需要进行主从复制(读写分离);



2、CAP原理以及NoSQL如何实现CAP

因为内容比较多,参考我的另一篇文章:https://xie.infoq.cn/article/78aef90c0e9b320b7bfa7940b



3、分布式一致性算法Paxos

Paxos是一个提高分布式系统容错性的一致性算法,解决【数据一致性】问题。

3-1、Paxos中的角色

  • Proposer:提出提案(Proposal),一个Proposal可以理解成一个由提案编号和提案值组成的键值对[Key,Value],其中Key就是提案编号,Value就是提案值;

  • Acceptor:负责批准提案,如果一个提案得到一半以上Accceptor的批准,那么这个提案就被批准,可以理解在分布式数据存储系统中,假如更新一个数据获得分布式集群中一半以上的节点同意,那么这个值就可以达到分布式一致性;

  • Learner:负责提案获取;当一个提案被批准后,Acceptor负责将批准的提案发送给Learner;就像一个数据在分布式集群中被同意更新,需要通知节点更新。





3-2、Paxos算法过程

  1. 第一阶段:Prepare阶段。Proposer向Acceptors发出【Prepare请求】,Acceptors针对收到的【Prepare请求】进行Promise承诺。

  2. 第二阶段:Accept阶段。Proposer收到多数Acceptors承诺的Promise后,向Acceptors发出「Propose请求」,Acceptors针对收到的「Propose请求」进行Accept处理。

  3. 第三阶段:Learn阶段。Proposer在收到多数Acceptors的Accept之后,标志着本次Accept成功,决议形成,将形成的决议发送给所有Learners。





3-3、Paxos算法消息的描述

Prepare: Proposer生成全局唯一且递增的Proposal ID (可使用时间戳加Server ID),向所有Acceptors发送Prepare请求,这里无需携带提案内容,只携带Proposal ID即可。

Promise: Acceptors收到Prepare请求后,做出“两个承诺,一个应答”

两个承诺:

  1. 不再接受Proposal ID小于等于(<=)当前请求的Prepare请求。

  2. 不再接受Proposal ID小于(< )当前请求的Propose请求。

一个应答:

不违背以前作出的承诺下,回复已经Accept过的提案中Proposal ID最大的那个提案的Value和Proposal ID,没有则返回空值。



Propose: Proposer 收到多数Acceptors的Promise应答后,从应答中选择Proposal ID最大的提案的Value,作为本次要发起的提案。如果所有应答的提案Value均为空值,则可以自己随意决定提案Value。然后携带当前Proposal ID,向所有Acceptors发送Propose请求。

Accept: Acceptor收到Propose请求后,在不违背自己之前作出的承诺下,接受并持久化当前Proposal ID和提案Value。

Learn: Proposer收到多数Acceptors的Accept后,决议形成,将形成的决议发送给所有Learners。



4、Zookeeper

Zookeeper是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby的开源实现。Zookeeper的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以简单易用的接口提供给用户使用。



4-1、Zookeeper如何保证分布式一致性?

  • 顺序一致性:从同一个客户端发起的事务请求,最终将会严格地按照其发起顺序被应用到Zookeeper;

  • 原子性:所有事务请求的处理结果在整个集群所有机器上的应用一致,要么整个集群所有机器都成功应用某一个事务,要么都没应用,一定不会出现部分机器应用,而另外一部分没有应用的情况;

  • 单一视图:无论客户端连接的是哪个Zookeeper服务器,其看到的服务端数据模型都是一致的;

  • 可靠性:一旦服务成功地应用一个事务,并完成对客户端的响应,那么该事务所引起的服务端状态变更将会被一致保留下来,除非有另一个事务又对其进行变更;

  • 实时性:Zookeeper保证在一定的时间段内,客户端最终一定能够从服务端上读取到最新的数据状态。



4-2、Zookeeper的ZAB协议

Zookeeper并没有采用Paxos算法,而是使用一种称为Zookeeper Atomic Broadcast(ZAB,Zookeeper原子消息广播协议)作为其数据一致性的核心算法。

ZAB协议是为分布式协调服务Zookeeper专门设计的支持【崩溃恢复】的原子广播协议。

在Zookeeper中,主要依赖ZAB协议来实现分布式数据一致性,基于该协议,Zookeeper实现一种【主备模式】的系统架构来保持集群中各副本之间数据的一致性。



4-2-1、ZAB协议描述

ZAB协议的核心是定义对那些会改变Zookeeper服务器数据状态的事务请求的处理方式,即:

所有的事务请求必须由一个【全局唯一】的服务器协调处理,这个服务器被称为【Leader】服务器,而其它服务器称为【Follower】服务器。

Leader服务器负责将一个客户端事务请求转换成一个事务Proposal(提议),并将该 Proposal 分发给集群中所有的 Follower 服务器。

之后Leader服务器需要等待所有 Follower 服务器反馈,当【超过半数】的 Follower 服务器进行正确反馈后,Leader 就会再次向所有 Follower 服务器 分发 Commit 消息,要求将 Proposal 进行提交。



集群有两种方式收到客户端的请求:

1、Leader服务器直接接收到客户端的事务请求,生成提案进行一轮广播协议;

2、集群中的Follower服务器收到客户端请求,会将这个请求先发给Leader服务器处理;



4-2-2、ZAB协议模式



4-2-2-1、消息广播

  1. 发出提案:一个客户端请求发送到Leader服务器,Leader服务器生产对应的Proposal,并将其发送给集群中的Follower服务器;

  2. 提交提案:Leader收到集群中【超过一半】的Follower服务器反馈的ACK请求后,发送Commit请求将第一步发出的Proposal事务提交;



4-3、Zookeeper集群



4-4、Zookeeper的Leader选举过程

节点的状态

Looking 正在参与竞选状态,会参与投票 Leading 选举结束,主节点的状态 Following 选举结束,从节点的状态 一开始所有节点都是Looking状态,进行选举,选举出主节点后, 主节点的状态是leading,其他节点状态是following,主节点挂了之后,需要进行新一轮的选举,所有节点又变成looking。



所有节点都有两个属性,SID:节点ID,zoo.cfg中配置的myid,ZXID:节点当前的最大事务ID 选举的目的就是选目前所有节点中拥有最大ZXID的节点作为Leader,如果拥有的ZXID相同,就选取SID最大的节点作为Leader。



全新的集群leader选举

启动时,当集群没有leader时,每个机器会将票投给SID最大的机器(越晚加入的机器SID越大) 有leader时会将票投给leader。 假设有五个节点,一开始A启动时之会将票投给自己,B启动时之后将票投给B,A也投给B,C启动时,A,B,C都投个C C得票超过半数,C成为leader,之后加入的D,E也只会投给C。



非全新的集群leader选举

基本原则是

1.选epoch值大的,epoch值小的投票结果会被忽略掉。 2.epoch值相同时,把票投给ZXID大的节点。 3.ZXID相同时,把票投给SID(server id)大的节点。 得票超过半数的节点会成为leader。 通常是数据越新的节点越有可能成为主节点。



投票阶段

1.初始化选票

将逻辑时钟+1,初始化选票, 每个节点都会投给自己,然后选票发给其他节点



2.处理选票信息

从其他节点B收到投票信息后,进行处理 2.1 如果本节点的逻辑时钟小于接受这条投票的逻辑时钟, 说明本节点之前错过了上一轮的投票,将当前存储的选票信息清空, 2.2 如果本节点的逻辑时钟大于接受的这条投票的逻辑时钟,那么忽略掉这条投票信息。 2.3 本节点的逻辑时钟等于接受的这条投票的逻辑时钟,那么进行处理,与本节点当前投票的结果进行比较 先比较ZXID(数据ID,越大代表数据越新),ZXID越大的应该当leader,ZXID相同比较SID,SID越大的当leader。 2.4如果比较的结果跟当前节点的投票结果不一致,那么需要更改选票,将更改后的选票结果发送给其他节点。 2.5将其他节点B的投票结果记录下来



3.统计选票

对当前收到的所有投票信息进行统计,看是否有节点获得半数以上的选票,有的话就将它设置为leader,然后终止投票,否则继续投票,继续步骤2。



4.发现阶段

所有follower会向leader发送epoch和ZXID(最大事务ID),然后leader选取最大的事务ID作为当前最新的ID



5.同步阶段

通知其他follower节点进行同步,将数据更新到最大的事务ID。



原子广播阶段

这时正式向客户端提供服务,leader接受客户端的写请求后,会将请求通过队列发送个每个节点,每个节点收到消息后将记录写到磁盘, 并且返回ACK给leader,当半数以上的从节点返回ACK后,leader才commit这条更新。



4-5、Zookeeper的应用

Zookeeper的应用场景包括:

  • 配置中心

  • 负载均衡

  • 命名服务

  • 分布式协调/通知

  • 集群管理

  • Master选举

  • 分布式锁

  • 分布式队列



5、本周总结

本周主要的收获:

1、了解数据库分片的目的,实现原理和解决方案;

2、掌握了CAP原理,并且了解Cassandra(AP)和HBase(CP)在CAP中进行取舍的;

3、了解分布式海量存储框架Doris的设计背景、目标和实现;

4、掌握分布式一致性算法Paxos的算法原理;

5、掌握Zookeeper这个开源的分布式协调服务的原理和在实践中的应用场景;

发布于: 2020 年 07 月 15 日 阅读数: 18
用户头像

Albert

关注

还未添加个人签名 2018.08.31 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第 0 期第六周学习总结