分布式

分布式系统:一组独立的计算单元通过网络进行通信并透明地对外提供服务

为什么要分布式

分布式系统解决了什么问题

  1. 单机性能瓶颈导致的成本问题 小型机器不够用 大型机器又很贵
  2. 用户量以及数据量增大不得不使用分布式
  3. 业务高可用的要求

技术栈

关键技术:服务治理、架构管理、DevOps、自动化运维、资源调度管理、监控、流量控制

分布式系统的麻烦

系统的某些部分可能会以某种不可预知的方式被破坏。这被称为部分失效(partial failure)。这种失效重点在于由于分布式系统通过网络来进行协作,所以是不确定性的

分布式系统的故障处理原则:

网络不可靠

分布式系统大都通过节点之间发送消息来协作。但网络是不可靠的,有时消息发没发到,接没接到,这些都是不确定的。处理这个问题的通常方法是超时(Timeout):在一段时间之后放弃等待,并且认为响应不会到达,人为原因是造成网络中断的主要原因

为了检测分布式系统节点的故障,一些机制可以知道节点是否关闭了,比如TCP协议中发送FIN或者RST,通过探测整个网络拓扑结构来发现网络是否故障。但这些仍无法百分百确保能接收到节点关闭的消息,所以可以通过重试,无论是TCP层的重试,还是应用层的重试,来进行等待,超时则声明节点死亡。

既然超时是唯一的解决方案,那超时应该超多久?这个时间应该是动态调整的,由于网络是通过动态分配流量来提升资源利用率,所以只能通过实验方式选择超时:测量延长的网络往返时间和多台机器的分布,以确定超时时间

不同于电话网这种事先为每个用户预留一定资源的网络,以太网这种网络更像一种抢占性的网络,所以电话网这种网络更有可能达到可预测的延时时间目标。

节点失效模型:

时钟不可靠

计算机中的石英钟不够精确:它会漂移(drifts)(运行速度快于或慢于预期)

由于时钟的不准确性,时钟应该是要有一个可信区间:[不早于, 不晚于] 如果没有重叠就能使用这个区间判断两个时钟的先后顺序

为了解决时钟漂移带来的不同节点时间不一致的问题,可以使用:

逻辑时钟(logic clock):类似于事务版本号

另外一个需要注意额是进程暂停问题,无论是JVM的STW或者操作系统的进程重新调度,可能都会造成进程被冻结一段时间,然后会来重新执行,此时如果没有对时间做特殊处理,可能就会出现问题。分布式系统中的节点,必须假定其执行可能在任意时刻暂停相当长的时间

STW导致冲突

为了解决这个问题,可以引入版本号,当资源持有者发现请求者的版本号不是最新的时候就可以拒绝请求

为了达到响应时间的保证,一些实时系统可能会通过降低吞吐量的方式来提升实时性。

定时假设,三种系统模型是常用的:

一致性与共识

线性化

在一个线性化的系统中,只要一个客户端成功完成写操作,所有客户端从数据库中读取数据必须能够看到刚刚写入的值

使用线性化的场景:

线性化背后的基本思想很简单:使系统看起来好像只有一个数据副本。

可实现线性化的复制方式:

网络分区迫使我们在线性化与可用性之间进行选择

顺序保证

为了知道因果关系,需要知道请求的先后顺序,为了知道请求先后顺序,需要知道读取或者写入数据的版本

为了产生这个版本,使用时间戳是不可靠的,在单个节点内可以使用逻辑时间戳

Lamport时间戳,很像雪花算法

全序关系广播