架构师训练营第六周课程笔记及心得
架构师训练营第六周课程笔记及心得
分布式关系数据库
MySQL复制

在客户端进行操作时,会记录Binlog,客户端会获取命令,在从服务其中,通过Log获取线程来将主服务器中客户端获取到的命令追加到log,然后从服务器通过SQL执行线程,观察log,读新命令
一主多从复制:

生产中一般都是使用多个从服务器,去同步复制主服务的数据;多个从服务器可以用于不同的场景
一主多从复制的优点:
分摊负载
专机专用
便于冷备
高可用
主从复制,一主多从这种模式只能保证读高可用,无法保证写高可用,写高可用,使用主主复制来实现
主主复制:

同样是使用binlog进行两个主服务器之间的数据同步,与主从不同的是,两个主服务器之间都会有同步,相互同步,通过binlog和relaylog来进行两个服务器直接的同步
MySQL主主复制恢复:

主主失效的维护过程:

MySQL复制注意事项:
主主复制不能两个都并发写入:同时向两个主服务器会产生逻辑的问题,可能导致数据冲突
复制只是增加了数据的读并发处理能力,没有增加写并发处理能力和存储能力
更新表结构会导致巨大的同步延迟,一般会让DBA选一个时间手动处理
主从复制,主主复制,都没有提升写的并发能力,只提升了读的并发能力,还需要使用数据分片来提升写的并发处理能力
数据分片:
分片目标
分片特点
分片原理
硬编码实现数据分片:

硬编码的方式对程序的影响比较大,需要在程序中实现代码逻辑;并且不容以管理,集群管理麻烦,所以一般使用映射表外部存储的方式来实现分片
映射表外部存储:

由于不用代码判断数据的分表,在程序伸缩性,代码维护方面会比较好,但是也存在问题
数据分片的挑战:
需要大量的额外代码,处理逻辑因此变得更加复杂
无法执行多分片的联合查询
无法使用数据库的事务
随着数据的增长,如何增加更多的服务器成为了一个挑战
为了解决上述问题,单独将这些功能提取出来做一个数据库中间件
分布式数据库中间件:

Mycat通过将自己伪装成一个数据库接受客户端的数据库请求,在Mycat内部将数据分片,并且由于Mycat链接多个数据库,可以将数据分别存储到分布式数据库中还有很多其他的中间件产品也是为了解决分布式数据库问题
分布式数据库中间件Cobar:

阿里最早推出的一个分布式数据库中间件
Cobar系统组件模型:

Cobar的路由模块决定数据到底读取或存储到哪个或哪几个数据库上
路由配置示例:

之前对2取模获取的数据库中存储的数据,在数据新增节点之后,需要对3或者更高的数量进行取模,这时可能导致和分布式缓存一样的问题,使得添加节点之后之前的数据反而无法被查找到,数据库中若还是找不到数据则客户端就会产生异常,这是不能允许的
实践中如何做分布式数据库集群的伸缩:

数据库的集群伸缩,肯定涉及到数据迁移
如何进行数据迁移:
在进行路由表配置的时候一般不是直接有几个就对几取模,一般会对一个很大的数进行取模,保证伸缩性,同时用数据库别名,通过别名映射不同的数据库来调整修改数据库实际服务器地址。
上述的解决数据库集群扩容方式时,需要一开始的时候就规划好数据库的规模,否则,当数据库需要使用的量超出配置中取模数时,就需要另外考虑办法了
数据库部署方案-单一服务与单一数据库:

数据库部署方式-主从复制实现伸缩:

数据库部署方式-连个web服务及两个数据库(对应用进行拆分-业务分库):

数据库部署方式-综合部署:

CAP原理与NoSQL数据库架构
NoSQL数据库:
关系数据库的替代品,比关系型数据库的伸缩性更好
CAP:C(一致性)、A(可用性)、P(分区耐受性)
C(一致性):每次读取的数据都应该是最近写入的数据或者返回一个错误,而不是过期数据,即数据的一致性
A(可用性):每次请求应该得到一个响应,而不是返回一个错误或者失去响应,但是这个响应可以不是最新最近的数据,即系统整体需要一直正常可用,不会引起调用者异常,但不保证数据的一致性
P(分区耐受性):即使因为网络原因,部分服务器节点之间消息丢失或者延迟了,系统任然可以操作
CAP原理:
选择一致性:系统就直接返回一个错误码,或者干脆超时,即系统不可用
选择可用性:虽然总是可以返回一个数据,但是这个数据不一定是最新的
所以对于CAP原理,准确的描述,应该时在分布式系统必须满足分区耐受性的前提下,可用性和一致性无法同时满足。
CAP原理与数据一致性冲突的场景 :

最终一致性:
一段时间范围之内数据允许可以不一致,但是最后同步发生后,数据是一致的
最终一致性也存在一段时间内数据的不一致,但是数据不一致是在数据库内部的,只要让客户端访问的数据是最新的有效的就可以解决一致性问题了。
最终一致写冲突:
数据库在网络出现问题时遭到修改的场景中,即使只需要保证最终一致性,数据库也需要判断哪个才是最终有效数据,这时就会出现写冲突。
简单的冲突处理策略:
可以根据时间戳,来判断哪个数据是最新的,有效的,再使用这个数据,来保证数据库的最终一致性。

客户端来解决冲突:
一般是客户端逻辑比较强的场景才会使用客户端来保持最终一致性

投票解决冲突(Cassandra):

Cassandra分布式架构:
允许数据库中内部数据不一致,但是客户端获取的数据最终是一致的

Hbase架构:


Hbase数据存储特点
hbase的数据是存储在Log结构的LSM树(Log Structed Merge tree log结构合并数)上的
LSM树是对应的关系数据库的B+,是随机进行读写操作的
但是LSM树是顺序进行写入的,传统的存储在进行log格式的写入(即连续的写入)时效率会更高,利用了这一特性的,就是LSM树,同时Hbase还使用例树结构,最后得到的就是LSM,Log结构合并树
先在内存中进行读写,在超出内存范围时,就会与硬盘中树进行合并,当硬盘中的树也开始变大时,硬盘中的树也会进行进一步的合并,最终合并成一个大树。
ACID与BASE:
ACID(传统的数据库事务特点):
原子性(Atomicity):事务要么全部完成,要么全部取消。如果事务崩溃,状态回到事务之前(回滚)
隔离性(Isolation):如果两个事务同时运行,则两个事务的最终结果不管谁先结束,结果都要相同,主要靠锁实现
持久性(Durability):一旦事务提交,不管发生什么,数据都要保存在数据库中
一致性(Consistency):只有合法的数据,最新的有效的数据才能写入数据库
BASE(NoSQL数据库事务特点):
基本可用(Basically Available):系统在出现不可知的故障时,允许损失部分可用性,如响应时间上的损失或功能上的损失
弱状态(Soft state):也叫软状态,允许数据库中存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点数据副本之间进行数据同步的过程存在延迟
最终一致性(Eventually consistent):数据库中所有的数据副本,在经过一定时间后,最终能够到达一个一致的状态,因此最终一致性的本质是需要系统保证数据能够达到一致,而不需要实时保证系统数据的强一致性
zk与分布式一致性:
分布式系统脑裂:
在一个分布式系统中,不同的服务器获得了弧线给冲突的数据信息,或者执行指令,导致整个集群陷入混乱,数据损坏,被称作分布式系统脑裂
例:主主复制数据库备份,两个主数据库节点同步时间间隔内,出现了数据更新的情况时,会出现数据不一致的情况,同步发生时无法判断以哪个数据为准导致脑裂,所以两个主服务器虽然都可以进行写操作,但是同一时间内只有一台服务器作为主服务器,这是需要一个专用的服务器来做判断和选择,哪个服务器作为主服务器,并且决定哪个服务器为主服务器的服务器本身也需要是高可用的。

解决分布式多台服务器情况下一致性问题:
分布式一致性算法Paxos:
三个角色:
Proposer:接受后端服务器的注册请求,并提交投票
Acceptor:进行投票,通过投票来进行决策,结果票数多的proposer的请求通过,决定之后全都同步结果并像learner发送结果
Learner:接受最后结果,所有客户端都通过learner来获取目前的角色
具体应用中一个服务器同时扮演三个角色
三个阶段:
Prepare阶段:Proposer向Acceptors发出Prepare请求,Acceptors针对收到的Prepare请求进行Promise承诺
Accept阶段:Proposer收到多数Acceptors承诺的Promise后,向Acceptors发出Proposer请求,Acceptors针对收到的Propose请求进行Accept处理
Learner阶段:Proposer在收到多数Acceptors的Accept之后,标志这本次Accept成功,决议形成,将形成的决议发送给所有的Learners

决策方法:
Proposer生成全局唯一且递增的Proposal ID(可使用时间戳加Server ID),向所有Acceptors发送Prepare请求,这里无需携带提案内容,只携带Proposal ID即可。
Acceptors收到Prepare和Propose请求后
不再接受Proposal ID小于等于当前请求的Prepare请求
不再接受Proposal ID小于当前请求的Propose请求
Paxos一致性算法比较复杂,在实现中比较不常用zk中使用的zab协议,核心思路任然是投票决策状态的一致性
Zab协议:

角色:
Leader:只有leader能接受修改操作
Follower:接受读请求,修改操作会被转发至leader
过程:

Zookeeper架构:

Zookeeper的竖装记录结构:

Zookeeper中的API举例
zk的应用场景:

选Master:

集群管理(负载均衡与失效转移):

Zookeeper性能:
读写比和请求处理性能的关系图;写的比例越高,性能越低;服务器越多读的性能越好,写的新能越低

搜索引擎基本架构:
搜索引擎:

网络爬虫:

禁爬协议,一种双方的约束:

文档矩阵与倒排索引:
词对应的文档有哪些,像是根据tag来排序文档,例:


带词频的倒排索引:

带词频与位置的倒排索引:

Lucene架构:
利用搜索引擎来优化数据访问时可以用到的一个开源搜索引擎架构

Lucene倒排索引:

Lucene索引文件准实时更新:
依赖索引来进行搜索,索引的实时性很重要,直接关系到是否能快速的查到结果,更新一个索引时,就需要全量创建一个索引来替换原来的索引,这种方式数据量大,实时效率很低,并且由于创建一次索引成本高,性能也差
Lucene中引入了段的概念,将一个索引文件拆分为多个子文件,每个子文件叫做段,每个段都是一个独立的可被搜索的数据集,索引的修改针对段进行操作。
新增:当有新的数据需要创建索引时,原来的段不变,选择新建一个段来存储新增的数据。
删除:当需要删除数据时,在索引文件新增一个.del的文件,专门用来存储被删除的数据ID。当查询时,被删除的数据还是可以被查到,只是在进行文档链表合并时,才把已经删除的数据过滤掉。被删除的数据在进行段合并时才会被真正移除
更新:更新操作其实就是删除和新增的组合操作,先在.del文件中记录旧数据,再在新段中添加一条更新后的数据。
段合并机制:段的数量时不是一味增长的,段的数量过多也会影响查询的效率,为了控制索引里段的数量,必须定期进行段合并操作。
Lucene优缺点:
优点:Lucene是一个强大的搜索引擎产品
缺点:Lucene不支持分布式集群,只支持单台服务器,那就没有高可用
ES架构一个包装过的Lucene,把单机的lucene,进行了分布式改造:
索引分片,实现分布式
索引备份,实现高可用
API更简单,更高级
ES分片预分配与集群扩容:
索引被创建时就需要指定好分片数量,分片指定之后,ES服务器自动为我们调整分片所在服务器节点
分片数量和集群数量无关,分片数量一开始指定后,不会随着节点的增加减少而改变
案例分析:Doris
版权声明: 本文为 InfoQ 作者【Airs】的原创文章。
原文链接:【http://xie.infoq.cn/article/87b002773f6729cd5a969aacd】。未经作者许可,禁止转载。
评论