mirror of
https://github.com/DistSysCorp/ddia.git
synced 2026-08-19 07:53:29 +08:00
fix: refactor text format
This commit is contained in:
106
ch01.md
106
ch01.md
@@ -8,7 +8,6 @@
|
||||
|
||||
因此,作为 IT 从业人员,有必要系统性的了解一下现代的、分布式的数据系统。学习本书,能够学习到数据系统的背后的原理、了解其常见的实践、进而将其应用到我们工作的系统设计中。
|
||||
|
||||
|
||||
## 常见的数据系统有哪些
|
||||
|
||||
- 存储数据,以便之后再次使用——**数据库**
|
||||
@@ -49,16 +48,12 @@
|
||||
如何衡量可靠性?
|
||||
|
||||
- **功能上**
|
||||
1. 正常情况下,应用行为满足 API 给出的行为
|
||||
2. 在用户误输入/误操作时,能够正常处理
|
||||
1. 正常情况下,应用行为满足 API 给出的行为
|
||||
2. 在用户误输入/误操作时,能够正常处理
|
||||
- **性能上**
|
||||
|
||||
在给定硬件和数据量下,能够满足承诺的性能指标。
|
||||
|
||||
在给定硬件和数据量下,能够满足承诺的性能指标。
|
||||
- **安全上**
|
||||
|
||||
能够阻止未授权、恶意破坏。
|
||||
|
||||
能够阻止未授权、恶意破坏。
|
||||
|
||||
可用性也是可靠性的一个侧面,云服务通常以多少个 9 来衡量可用性。
|
||||
|
||||
@@ -83,9 +78,7 @@
|
||||
数据系统中常见的需要考虑的硬件指标:
|
||||
|
||||
- **MTTF mean time to failure**
|
||||
|
||||
单块盘 平均故障时间 5 ~10 年,如果你有 1w+ 硬盘,则均匀期望下,每天都有坏盘出现。当然事实是硬盘会一波一波坏。
|
||||
|
||||
单块盘 平均故障时间 5 ~10 年,如果你有 1w+ 硬盘,则均匀期望下,每天都有坏盘出现。当然事实是硬盘会一波一波坏。
|
||||
|
||||
解决办法,增加冗余度:
|
||||
|
||||
@@ -93,9 +86,9 @@
|
||||
|
||||
对于数据:
|
||||
|
||||
**单机**:可以做RAID 冗余。如:EC 编码。
|
||||
**单机**:可以做 RAID 冗余。如:EC 编码。
|
||||
|
||||
**多机**:多副本 or EC 编码。
|
||||
**多机**:多副本 or EC 编码。
|
||||
|
||||
## 软件错误
|
||||
|
||||
@@ -113,21 +106,19 @@
|
||||
系统中最不稳定的是人,因此要在设计层面尽可能消除人对系统影响。依据软件的生命周期,分几个阶段来考虑:
|
||||
|
||||
- **设计编码**
|
||||
1. 尽可能消除所有不必要的假设,提供合理的抽象,仔细设计 API
|
||||
2. 进程间进行隔离,对尤其容易出错的模块使用沙箱机制
|
||||
3. 对服务依赖进行熔断设计
|
||||
1. 尽可能消除所有不必要的假设,提供合理的抽象,仔细设计 API
|
||||
2. 进程间进行隔离,对尤其容易出错的模块使用沙箱机制
|
||||
3. 对服务依赖进行熔断设计
|
||||
- **测试阶段**
|
||||
1. 尽可能引入第三方成员测试,尽量将测试平台自动化
|
||||
2. 单元测试、集成测试、e2e 测试、混沌测试
|
||||
1. 尽可能引入第三方成员测试,尽量将测试平台自动化
|
||||
2. 单元测试、集成测试、e2e 测试、混沌测试
|
||||
- **运行阶段**
|
||||
1. 详细的仪表盘
|
||||
2. 持续自检
|
||||
3. 报警机制
|
||||
4. 问题预案
|
||||
1. 详细的仪表盘
|
||||
2. 持续自检
|
||||
3. 报警机制
|
||||
4. 问题预案
|
||||
- **针对组织**
|
||||
|
||||
科学的培训和管理
|
||||
|
||||
科学的培训和管理
|
||||
|
||||
## 可靠性有多重要?
|
||||
|
||||
@@ -144,14 +135,14 @@
|
||||
应对负载之前,要先找到合适的方法来衡量负载,如**负载参数(load parameters)**:
|
||||
|
||||
- 应用日活月活
|
||||
- 每秒向Web服务器发出的请求
|
||||
- 每秒向 Web 服务器发出的请求
|
||||
- 数据库中的读写比率
|
||||
- 聊天室中同时活跃的用户数量
|
||||
|
||||
书中以 Twitter 2012年11 披露的信息为例进行了说明:
|
||||
书中以 Twitter 2012 年 11 月披露的信息为例进行了说明:
|
||||
|
||||
1. 识别主营业务:发布推文、首页 Feed 流。
|
||||
2. 确定其请求量级:发布推文(平均 4.6k请求/秒,峰值超过 12k请求/秒),查看其他人推文(300k请求/秒)
|
||||
2. 确定其请求量级:发布推文(平均 4.6k 请求/秒,峰值超过 12k 请求/秒),查看其他人推文(300k 请求/秒)
|
||||
|
||||

|
||||
|
||||
@@ -172,29 +163,25 @@
|
||||
|
||||
注意和系统负载区分,系统负载是从用户视角来审视系统,是一种**客观指标**。而系统性能则是描述的系统的一种**实际能力**。比如:
|
||||
|
||||
1. **吞吐量(throughput)**: 每秒可以处理的单位数据量,通常记为 QPS。
|
||||
2. **响应时间(response time)**: 从用户侧观察到的发出请求到收到回复的时间。
|
||||
1. **吞吐量(throughput)**:每秒可以处理的单位数据量,通常记为 QPS。
|
||||
2. **响应时间(response time)**:从用户侧观察到的发出请求到收到回复的时间。
|
||||
3. **延迟(latency)**:日常中,延迟经常和响应时间混用指代响应时间;但严格来说,延迟只是只请求过程中排队等休眠时间,虽然其在响应时间中一般占大头;但只有我们把请求真正处理耗时认为是瞬时,延迟才能等同于响应时间。
|
||||
|
||||
响应时间通常以百分位点来衡量,比如 p95,p99和 p999,它们意味着95%,99%或 99.9% 的请求都能在该阈值内完成。在实际中,通常使用滑动窗口滚动计算最近一段时间的响应时间分布,并通常以折线图或者柱状图进行呈现。
|
||||
响应时间通常以百分位点来衡量,比如 p95,p99 和 p999,它们意味着 95%,99%或 99.9% 的请求都能在该阈值内完成。在实际中,通常使用滑动窗口滚动计算最近一段时间的响应时间分布,并通常以折线图或者柱状图进行呈现。
|
||||
|
||||
## 应对负载
|
||||
|
||||
在有了描述和定义负载、性能的手段之后,终于来到正题,如何应对负载的不断增长,即使系统具有可伸缩性。
|
||||
|
||||
1. **纵向伸缩(scaling up)or 垂直伸缩(vertical scaling)**:换具有更强大性能的机器。e.g. 大型机机器学习训练。
|
||||
2. **横向伸缩(scaling out)or 水平伸缩(horizontal scaling)**:“并联”很多廉价机,分摊负载。 e.g. 马斯克造火箭。
|
||||
1. **纵向伸缩(scaling up)or 垂直伸缩(vertical scaling)**:换具有更强大性能的机器。e.g. 大型机机器学习训练。
|
||||
2. **横向伸缩(scaling out)or 水平伸缩(horizontal scaling)**:“并联”很多廉价机,分摊负载。e.g. 马斯克造火箭。
|
||||
|
||||
负载伸缩的两种方式:
|
||||
|
||||
- **自动**
|
||||
|
||||
如果负载不好预测且多变,则自动较好。坏处在于不易跟踪负载,容易抖动,造成资源浪费。
|
||||
|
||||
如果负载不好预测且多变,则自动较好。坏处在于不易跟踪负载,容易抖动,造成资源浪费。
|
||||
- **手动**
|
||||
|
||||
如果负载容易预测且不长变化,最好手动。设计简单,且不容易出错。
|
||||
|
||||
如果负载容易预测且不长变化,最好手动。设计简单,且不容易出错。
|
||||
|
||||
针对不同应用场景:
|
||||
|
||||
@@ -207,15 +194,11 @@
|
||||
两种服务类型:
|
||||
|
||||
- **无状态服务**
|
||||
|
||||
比较简单,多台机器,外层罩一个 gateway 就行。
|
||||
|
||||
比较简单,多台机器,外层罩一个 gateway 就行。
|
||||
- **有状态服务**
|
||||
|
||||
根据需求场景,如读写负载、存储量级、数据复杂度、响应时间、访问模式,来进行取舍,设计合乎需求的架构。
|
||||
|
||||
根据需求场景,如读写负载、存储量级、数据复杂度、响应时间、访问模式,来进行取舍,设计合乎需求的架构。
|
||||
|
||||
**不可能啥都要,没有万金油架构**! 但同时:万变不离其宗,组成不同架构的原子设计模式是有限的,这也是本书稍后要论述的重点。
|
||||
**不可能啥都要,没有万金油架构**!但同时:万变不离其宗,组成不同架构的原子设计模式是有限的,这也是本书稍后要论述的重点。
|
||||
|
||||
# 可维护性
|
||||
|
||||
@@ -223,18 +206,12 @@
|
||||
|
||||
但大部分人都喜欢挖坑,不喜欢填坑。因此有必要,在刚开就把坑开的足够好。有三个原则:
|
||||
|
||||
- ***可维护性(Operability)***
|
||||
|
||||
便于运维团队无痛接手。
|
||||
|
||||
- ***简洁性(Simplicity)***
|
||||
|
||||
便于新手开发平滑上手:这需要一个合理的抽象,并尽量消除各种复杂度。如,层次化抽象。
|
||||
|
||||
- ***可演化性(Evolvability)***
|
||||
|
||||
便于后面需求快速适配:避免耦合过紧,将代码绑定到某种实现上。也称为**可扩展性(extensibility)**,**可修改性(modifiability)** 或**可塑性(plasticity)**。
|
||||
|
||||
- **_可维护性(Operability)_**
|
||||
便于运维团队无痛接手。
|
||||
- **_简洁性(Simplicity)_**
|
||||
便于新手开发平滑上手:这需要一个合理的抽象,并尽量消除各种复杂度。如,层次化抽象。
|
||||
- **_可演化性(Evolvability)_**
|
||||
便于后面需求快速适配:避免耦合过紧,将代码绑定到某种实现上。也称为**可扩展性(extensibility)**,**可修改性(modifiability)** 或**可塑性(plasticity)**。
|
||||
|
||||
## **可运维性(Operability):人生苦短,关爱运维**
|
||||
|
||||
@@ -269,9 +246,9 @@
|
||||
2. 组件间的强耦合。
|
||||
3. 不一致的术语和[命名](https://www.qtmuniao.com/2021/12/12/how-to-write-code-scrutinize-names/)。
|
||||
4. 为了提升性能的 hack。
|
||||
5. 随处可见的补丁( workaround)。
|
||||
5. 随处可见的补丁(workaround)。
|
||||
|
||||
需求很简单,但不妨碍你实现的很复杂 😉:过多的引入了**额外复杂度**(*accidental* complexity
|
||||
需求很简单,但不妨碍你实现的很复杂 😉:过多的引入了**额外复杂度**(_accidental_ complexity
|
||||
)——非问题本身决定的,而由实现所引入的复杂度。
|
||||
|
||||
通常是问题理解的不够本质,写出了“**流水账**”(没有任何**抽象,abstraction**)式的代码。
|
||||
@@ -307,9 +284,6 @@
|
||||
应对之道:
|
||||
|
||||
- 项目管理上
|
||||
|
||||
敏捷开发
|
||||
|
||||
敏捷开发
|
||||
- 系统设计上
|
||||
|
||||
依赖前两点。合理抽象,合理封装,对修改关闭,对扩展开放。
|
||||
依赖前两点。合理抽象,合理封装,对修改关闭,对扩展开放。
|
||||
|
||||
Reference in New Issue
Block a user