分布式理论课后思考 | 青训营笔记

87 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 八 天

分布式系统有哪些优势和挑战?

分布式系统优势:

  • 可用性,分布式系统不会因为一个或者少数几个节点故障而整体崩溃。分布式系统又很好的容错性。
  • 可拓展性,分布式系统可以提高水平拓展,来应对不断增长的爱不需求。
  • 资源共享,分布式系统允许设备、数据库、文件等资源共享。
  • 加快计算速度,分布式系统可以将特定的计算任务划分为若干个并行子任务,同时将子任务分发给不同节点,从而加速计算速度。

分布式系统挑战:

  • 数据一致性,考虑到分布式系统的机器集群数量庞大,机器的故障成为了必然的事件:宕机、重启、关机,数据可能丢失、陈旧、位反转等等可能性也骤然上升。因此,如何保证分布式系统的数据一致性也成为了一项挑战!
  • 网络和通信故障,网络的不可靠,消息可能产生丢失、延迟、超发等问题,加上网络链路上的非法监听篡改,也给分布式系统的网络安全和通信可靠带来了挑战!
  • 集群治理,分布式系统的成千上万台机器组成的集群,如何去管理,如何去运维,如何去部署呢?

两将军问题为什么理论上永远达不成共识?

假设将军A派遣使者顺利穿越敌军领土,到达将军B处;

将军B派遣使者回复将军A

  • 使者被俘 ---> 没有达成共识
  • 使者穿越敌军领土 ---> 将军A达成共识,将军B仍然未达成共识 -> 没有达成共识

将军A派遣使者回复将军B

  • 使者被俘 ---> 没有达成共识
  • 使者穿越敌军领土 ---> 将军B达成共识,将军A无法确认使者到达与否故没有达成共识 -> 没有达成共识

这时将军B再回复将军A?事实上,不难发现因为信道的不可靠,两位将军都无法确认使者是否到达对面将军处。

这使得两位将军在经过无数遍的重复也无法达成共识。

为什么TCP采用三次握手?而不是两次和四次?

从两将军问题中,我们不难看出如果信道在最理想的情况下两位将军只要进行三次通信就可以达成共识。

前两次通信让将军A达成共识,第三次让将军B也达成了共识。

也正因此,想保证TCP的可靠传输也必须建立可靠连接,也就是至少需要三次握手才能建立共识。采用三次握手是最优的工程解,当到第四次握手是我们可看到其作用是非常微弱的,并没有明显的效益。

为什么在4将军问题中,增加1轮协商就可以对抗拜占庭故障?

image-20230203105249497.png

假设叛徒是将军1,在将军C发起进攻消息后,三个将军都接到了进攻信号,为了确保消息的准确性三位将军进行一轮协商:

123
1进攻撤退撤退
2进攻进攻进攻
3进攻进攻进攻

可以看到,协商后将军1三票进攻、将军2、3两票进攻,最终达成进攻协议。

假设将军C是叛徒,其向将军3发出撤退信号,向其他将军发出进攻信号,为了确保消息的准确性三位将军进行一轮协商:

123
1进攻进攻进攻
2进攻进攻进攻
3撤退撤退撤退

可以看到,一轮协商后三位将军都是两票进攻,达成一致进攻。

什么是最终一致性?什么是线性一致性?

最终一致性:节点间的数据最终都会一致,但是不保证之间过程数据的一致性

线性一致性:系统中的所有进程看到的操作顺序都与全局时钟下的顺序一致,即所有操作都是可见的,有序的。

CAP理论中,请举例说明可用性和一致性的矛盾?

矛盾:要保证多个节点数据的一致性,则需要在一个节点写入数据时,对其他

节点进行加锁,直到数据同步完成才能释放锁。

矛盾点:在单个节点写入时,对其他节点加锁的操作,直到数据同步才能释放锁。显然无法保证系统的可用性。

反之亦然。

数据库里的一致性和分布式系统中的一致性有什么区别?

数据库的一致性是借助于数据库自带的事务进行控制的。数据库事务是具有ACID特性的,MySQL 中事务的实现借助于MVCC 版本控制实现。

分布式系统的一致性是借助于一些中间件(例如Redis、Zookeeper、seata等等)而非依赖于节点本身。一般的分布式事务实现思路:两阶段提交、三阶段提交和MVCC机制。

两阶段提交中,什么场景需要数据库管理员介入?

image-20230203165349023.png 协调节点宕机,节点也宕机的情况下,需要数据库管理员接入。原因:节点的事务状态是未知的,为例确保数据库的一致性需要接入检查。

三阶段提交缓和两阶段提交的哪两个问题?

三阶段提交解决了以下两个问题:

  • 单点故障问题
  • 阻塞问题

三阶段提交会预先进行canCommit,这阶段需要判断数据能否提交以及节点的状态,可以避免节点故障的问题。

同时三阶段提交引入了超时机制,在等待超时后会继续事务的提交。减少了阻塞问题。

什么场景适合乐观锁?什么场景适合悲观锁?

乐观锁:

  • 适合读多写少,并发小的场景
  • 每次获取数据时,不通过加锁的方式获取数据,仅在对数据修改时进行CAS操作

悲观锁:

  • 适合数据一致性需求强的场景
  • 每次获取数据时,会对数据加锁,在完成数据的修改时才会释放锁

在共识协议中,为什么说允许数据被覆盖会带来数据一致性问题?

在并发读写场景下,产生数据一致性问题:

假设某时刻来了两个并发更新,如下表:

副本1副本2副本3
初始值(v)v1=1v1=1v1=1
第一次写v2=2v2=2v1=1
第二次写v3=3v2=2v2=2

这时又来了两个并发读线程,

副本1副本2副本3结论
读1v3=3v2=2v=3
读2v2=2v2=2v=2

可以看到,由于允许数据覆盖两次读操作,得出来的结果完全不一致。