跳至主要內容

《深入浅出分布式技术原理》笔记

钝悟...大约 13 分钟笔记分布式分布式理论分布式理论

《深入浅出分布式技术原理》笔记

开篇词 掌握好学习路径,分布式系统原来如此简单

导读:以前因后果为脉络,串起网状知识体系

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

  • 首先,分布式系统解决了单机性能瓶颈导致的成本问题。——水平扩展
  • 然后,解决了用户量和数据量爆炸性地增大导致的成本问题。——水平扩展
  • 接着,满足了业务高可用的要求。——解决单点问题,鸡蛋不要都放在一个篮子里
  • 最后,分布式系统解决了大规模软件系统的迭代效率和成本的问题。——分而治之,化繁为简

如何思考和处理分布式系统引入的新问题

  • 怎么找到服务——服务注册和发现
  • 怎么找到实例——路由、负载均衡
  • 怎么管理配置——配置中心
  • 怎么进行协同——分布式锁
  • 怎么确保请求只执行一次——重试+幂等
  • 怎么避免雪崩——限流、熔断、降级、快速失败、弹性扩容
  • 怎么监控告警和故障恢复——分布式链路追踪

分布式存储如何内部协调

  • 首先,理解 ACID、CAP、BASE
  • 然后,确定分片策略,常见方案有 Hash、Region 分片
  • 接着,确定复制方案,常见方案有:
    • 中心化方案:主从复制、一致性协议,比如 Raft 和 Paxos 等
    • 去中心化方案: Quorum 和 Vector Clock
  • 最后,如何处理分布式事务
    • 分布式 ID
    • 2PC、3PC 等分布式事务方案

新的挑战:分布式系统是银弹吗?我看未必!

  • 故障处理
  • 网络不可靠——超时处理
  • 时间不可靠——NTP、逻辑时钟
  • 共识协同——共识性算法

CAP 理论:分布式场景下我们真的只能三选二吗?

在一个分布式系统中,当发生网络分区时,那么强一致性和可用性只能二选一

注册发现: AP 系统和 CP 系统哪个更合适?

服务注册的关键:

  • 统一的中介存储:调用方在唯一的地方获得被调用服务的所有实例的信息。
  • 状态更新与通知:服务实例的信息能够及时更新并且通知到服务调用方。

注册中心的特性要求:

  • 可用性要求非常高:因为服务注册发现是整个分布式系统的基石,如果它出现问题,整个分布式系统将不可用。
  • 性能要求中等:只要设计得当,整体的性能要求还是可控的,不过需要注意的是性能要求会随分布式系统的实例数量变多而提高。
  • 数据容量要求低:因为主要是存储实例的 IP 和 Port 等元数据,单个实例存储的数据量非常小。
  • API 友好程度:是否能很好支持服务注册发现场景的“发布/订阅”模式,将被调用服务实例的 IP 和 Port 信息同步给调用方。

注册中心选择 AP 还是 CP:

因为服务发现是整个分布式系统的基石,所以可用性是最关键的设计目标。

负载均衡:从状态的角度重新思考负载均衡

负载均衡策略:

  • 轮询
  • 随机
  • 加权轮询/随机
  • 最少连接/请求
  • 最少响应时间
  • Hash
  • 一致性 Hash
  • 虚拟一致性 Hash

配置中心:如何确保配置的强一致性呢?

配置中心的关键挑战:

  • 统一的配置存储:一个带版本管理的存储系统,按服务的维度,存储和管理整个分布式系统的配置信息,这样可以很方便地对服务的配置信息,进行搜索、查询和修改。
  • 配置信息的同步:所有的实例,本地都不存储配置信息,实例能够从配置中心获得服务的配置信息,在配置修改后,能够及时将最新的配置,同步给服务的每一个实例。

配置中心特性要求:

  • 可用性要求非常高
  • 性能要求中等
  • 数据容量要求低
  • API 友好程度

分布式锁:所有的分布式锁都是错误的?

重试幂等:让程序 Exactly-once 很难吗?

在分布式系统中,程序不能保证 Exactly-once:响应超时的情况下,请求方无法判断接收方是否处理过这个请求。过程中有可能出现网络丢包问题或服务端故障。

幂等设计要点:

  • 使用唯一性 ID 来标记请求,通过 ID 进行去重
  • 保存状态快照+回滚模式——代价太高,一般不会用

雪崩(一):熔断,让故障自适应地恢复

在服务调用链中,服务调用时由于某一个服务故障,导致级联服务故障,并逐步扩散引起大范围服务故障的现象,称为雪崩效应。

在熔断机制的模式下,服务调用方需要为每一个调用对象,可以是服务、实例和接口,维护一个状态机,在这个状态机中有三种状态。

首先,是闭合状态( Closed )。在这种状态下,我们需要一个计数器来记录调用失败的次数和总的请求次数,如果在一个时间窗口内,请求的特定错误码的比例达到预设的阈值,就切换到断开状态。

其次,是断开状态( Open )。在该状态下,发起请求时会立即返回错误,也可以返回一个降级的结果,我们会在后面的课程“降级”中再详细讨论。在断开状态下,会启动一个超时计时器,当计时器超时后,状态切换到半打开状态。

最后,是半打开状态( Half-Open )。在该状态下,允许应用程序将一定数量的请求发往被调用服务,如果这些调用正常,那么就可以认为被调用服务已经恢复正常,此时熔断器切换到闭合状态,同时需要重置计数。如果这部分仍有调用失败的情况,我们就认为被调用方仍然没有恢复,熔断器会切换到断开状态,然后重置计数器。所以半打开状态能够有效防止正在恢复中的服务,被突然出现的大量请求再次打垮的情况。

雪崩(二):限流,抛弃超过设计容量的请求

常见限流算法

  • 固定窗口限流
  • 滑动窗口限流
  • 漏桶限流
  • 令牌桶限流

雪崩(三):降级,无奈的丢车保帅之举

降级机制能从全局角度对资源进行调配,通过牺牲非核心服务来保障核心服务的稳定性

如何实现降级:

  • 手动降级
  • 自动降级:当系统的某些指标或接口调用出现错误时,直接启动降级逻辑

雪崩(四):扩容,没有用钱解决不了的问题

如何实现动态扩容

通过可观测性系统监控核心指标

过载判断 - 一旦核心指标达到阈值,触发扩容

自动扩容 - 利用 K8S 进行容器化扩容

可观测性(一):如何监控一个复杂的分布式系统?

搭建一个可观测性平台,主要通过对日志( Logs )、链路( Traces )与指标( Metrics )这三类数据进行采集、计算和展示。

  • 日志信息( Logs ) - 代表:ELK
  • 追踪链路( Traces ) - 代表:Jaeger、Zipkin、SkyWalking
  • 指标信息( Metrics ) - 代表:Prometheus + Grafana

四个黄金指标:延迟、流量、错误和饱和度

可观测性(二):如何设计一个高效的告警系统?

告警系统的评价指标:

  • 信噪比:指有效告警通知数和无效告警通知数的比例,信噪比越高越好,是用来评估“多报”问题的。
  • 覆盖率:指被告警系统通知的故障占全部线上故障的比例,同样,覆盖率也是越高越好,是用来评估“漏报”问题的。
  • 转交率:指被转交的告警通知数占全部告警通知数的比例,转交率越低越好,是用来评估“对比人”问题的。

故障(一):预案管理竟然能让被动故障自动恢复?

故障评价标准:

  • 平均出现故障的频率:指平均多少时间出现一次故障,这个频率越低越好。
  • 平均故障恢复的时间:指出现故障后,系统在多长时间恢复到正常状态,这个时间越短越好,并且,我认为这是一个更关键的指标。

被动故障的来源:

  • DNS 解析问题:用户本地网络的 DNS 服务不能将我们的域名正确解析到 IP 地址。

  • 网络连通性问题:用户已经解析到正确的 IP 地址,但是从用户网络到我们服务器的 IP 地址之间的网络慢或者不通。

  • 系统内部的硬件设施故障:比如机器突然宕机,内部网线中断等。

  • 系统依赖的各种第三方服务:比如 CDN 服务、短信网关、语音识别等第三方服务故障。

故障(二):变更管理,解决主动故障的高效思维方式

主动故障的来源:

  • 程序发布变更:指服务器、App 和 Web 等发布了新版本的程序和服务。
  • 实例数目变更:指服务器新增实例和下线实例。
  • 配置发布变更:指发布了新版本的配置。
  • 运营策略变更:指举办了导致用户流量增长的运营活动,比如购买了新的推广广告等。

分片(一):如何选择最适合的水平分片方式?

分片(二):垂直分片和混合分片的 trade-off

复制(一):主从复制从副本的数据可以读吗?

复制的三种方案:

  • 主从复制:整个系统中只有一个主副本,其他的都为从副本。
  • 多主复制:系统中存在多个主副本,客户端将写请求发送给其中的一个主副本,该主副本负责将数据变更发送到其他所有的主副本。
  • 无主复制:系统中不存在主副本,每一个副本都能接受客户端的写请求,接受写请求的副本不会将数据变更同步到其他的副本。

Mysql、PostgreSql、Redis、MongoDB、Kafka 都支持主从复制。

主从复制的关键在于采用同步复制还是异步复制。

复制(二):多主复制的多主副本同时修改了怎么办?

为什么需要多主复制——为了提供更好的容灾能力,需要多机房、多数据中心来进行冗余,这就需要多主复制或无主复制。

如何实现多主复制

  • 首先,每一个主从复制单元内部是一个常规的主从复制模式,这里的主副本、从副本之间的复制可以是同步的,也可以是异步的。
  • 其次,多个主从复制单元之间,每一个主副本都会将自己的修改复制到其他的主副本,主副本之间的复制可以是同步的,也可以是异步的。

问题:

同步会导致整个模式退化为主从复制的形式。

异步模式的多主复制会存在数据一致性的问题。

如何解决冲突

写入冲突是由于多个主副本同时接受写入,并且主副本之间异步复制导致的。

注:文中并未给出完整的解决方案。

复制(三):最早的数据复制方式竟然是无主复制?

无主复制由于写入不依赖主节点,所以在主节点故障时,不会出现不可用的情况。但是,也是由于写入不依赖主节点,可能导致副本之间的写入顺序不相同,会影响数据的一致性。

在实现无主复制时,有两个关键问题:数据读写和数据修复。数据读写是通过仲裁条件 w + r > n 来保证的,如果满足 w + r > n ,那么读副本和写副本之间就一定有交集,即一定能读取到最新的写入。而数据修复是通过读修复和反熵过程实现的,这两个方法在数据的持久性和一致性方面存在一定的问题,如果对数据有强一致性的要求,就要谨慎采用无主复制。

然后,我们了解了 Sloppy Quorum ,它相比于传统的 Quorum ,为了系统的可用性而牺牲了数据的一致性,这里我们可以进一步得出,无主复制是一个可用性优先的复制模型

事务(一):一致性,事务的集大成者

事务是一个或多个操作的组合操作,它需要保证这组操作要么都执行,要么都不执行。

事务(二):原子性,对应用层提供的完美抽象

简单介绍了 2PC

事务(三):隔离性,正确与性能之间权衡的艺术

简单介绍了事务隔离级别

事务(四):持久性,吃一碗粉就付一碗粉的钱

简单介绍了 Redo Log + WAL

一致性与共识(一):数据一致性都有哪些级别?

按照一致性强度由高到低,有以下模型:

线性一致性——现在可以实现的一致性级别最强的是线性一致性,它是指所有进程看到的事件历史一致有序,并符合时间先后顺序, 单个进程遵守 program order,并且有 total order。

顺序一致性——它是指所有进程看到的事件历史一致有序,但不需要符合时间先后顺序, 单个进程遵守 program order,也有 total order。

因果一致性——它是指所有进程看到的因果事件历史一致有序,单个进程遵守 program order,不对没有因果关系的并发排序。

最终一致性——它是指所有进程互相看到的写无序,但最终一致。不对跨进程的消息排序。

一致性与共识(二):它们是鸡生蛋还是蛋生鸡?

一致性与共识(三):共识与事务之间道不明的关系

分布式计算技术的发展史:从单进程服务到 Service Mesh

分布式存储技术的发展史:从 ACID 到 NewSQL

春节加餐 技术债如房贷,是否借贷怎样取舍?

春节加餐 深入聊一聊计算机系统的时间

春节加餐 系统性思维,高效学习和工作的利器

结束语 在分布式技术的大潮流中自由冲浪吧!

参考资料

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.7