Skip to content

Commit

Permalink
reformat indented content
Browse files Browse the repository at this point in the history
  • Loading branch information
yingang committed Dec 8, 2021
1 parent ac6b23f commit 9b3bd96
Show file tree
Hide file tree
Showing 30 changed files with 542 additions and 540 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@

| ISSUE & Pull Requests | USER | Title |
| ----------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| [147](https://github.com/Vonng/ddia/pull/147) | [@ZvanYang](https://github.com/ZvanYang) | ch5: 更正一处不准确的翻译 |
| [145](https://github.com/Vonng/ddia/pull/145) | [@Hookey](https://github.com/Hookey) | 识别了当前简繁转译过程中处理不当的地方,暂通过转换脚本规避 |
| [144](https://github.com/Vonng/ddia/issues/144) | [@secret4233](https://github.com/secret4233) | ch7: 不翻译`next-key locking` |
| [143](https://github.com/Vonng/ddia/issues/143) | [@imcheney](https://github.com/imcheney) | ch3: 更新残留的机翻段落 |
| [142](https://github.com/Vonng/ddia/issues/142) | [@XIJINIAN](https://github.com/XIJINIAN) | 建议去除段首的制表符 |
Expand Down
32 changes: 16 additions & 16 deletions ch1.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@

本书着重讨论三个在大多数软件系统中都很重要的问题:

***可靠性(Reliability)***
* 可靠性(Reliability)

系统在**困境(adversity)**(硬件故障、软件故障、人为错误)中仍可正常工作(正确完成功能,并能达到期望的性能水准)。请参阅“[可靠性](#可靠性)”。
系统在**困境(adversity)**(硬件故障、软件故障、人为错误)中仍可正常工作(正确完成功能,并能达到期望的性能水准)。请参阅“[可靠性](#可靠性)”。

***可伸缩性(Scalability)***
* 可伸缩性(Scalability)

有合理的办法应对系统的增长(数据量、流量、复杂性)。请参阅“[可伸缩性](#可伸缩性)”。
有合理的办法应对系统的增长(数据量、流量、复杂性)。请参阅“[可伸缩性](#可伸缩性)”。

***可维护性(Maintainability)***
* 可维护性(Maintainability)

许多不同的人(工程师、运维)在不同的生命周期,都能高效地在系统上工作(使系统保持现有行为,并适应新的应用场景)。请参阅“[可维护性](#可维护性)”。
许多不同的人(工程师、运维)在不同的生命周期,都能高效地在系统上工作(使系统保持现有行为,并适应新的应用场景)。请参阅“[可维护性](#可维护性)”。

人们经常追求这些词汇,却没有清楚理解它们到底意味着什么。为了工程的严谨性,本章的剩余部分将探讨可靠性、可伸缩性、可维护性的含义。为实现这些目标而使用的各种技术,架构和算法将在后续的章节中研究。

Expand Down Expand Up @@ -152,13 +152,13 @@

为了使这个概念更加具体,我们以推特在2012年11月发布的数据【16】为例。推特的两个主要业务是:

***发布推文***
* 发布推文

用户可以向其粉丝发布新消息(平均 4.6k请求/秒,峰值超过 12k请求/秒)。
用户可以向其粉丝发布新消息(平均 4.6k请求/秒,峰值超过 12k请求/秒)。

***主页时间线***
* 主页时间线

用户可以查阅他们关注的人发布的推文(300k请求/秒)。
用户可以查阅他们关注的人发布的推文(300k请求/秒)。

处理每秒12,000次写入(发推文的速率峰值)还是很简单的。然而推特的伸缩性挑战并不是主要来自推特量,而是来自**扇出(fan-out)**——每个用户关注了很多人,也被很多人关注。

Expand Down Expand Up @@ -279,17 +279,17 @@

但是我们可以,也应该以这样一种方式来设计软件:在设计之初就尽量考虑尽可能减少维护期间的痛苦,从而避免自己的软件系统变成遗留系统。为此,我们将特别关注软件系统的三个设计原则:

***可操作性(Operability)***
* 可操作性(Operability)

便于运维团队保持系统平稳运行。
便于运维团队保持系统平稳运行。

***简单性(Simplicity)***
* 简单性(Simplicity)

从系统中消除尽可能多的**复杂度(complexity)**,使新工程师也能轻松理解系统。(注意这和用户接口的简单性不一样。)
从系统中消除尽可能多的**复杂度(complexity)**,使新工程师也能轻松理解系统。(注意这和用户接口的简单性不一样。)

***可演化性(evolability)***
* 可演化性(evolability)

使工程师在未来能轻松地对系统进行更改,当需求变化时为新应用场景做适配。也称为**可伸缩性(extensibility)****可修改性(modifiability)****可塑性(plasticity)**
使工程师在未来能轻松地对系统进行更改,当需求变化时为新应用场景做适配。也称为**可伸缩性(extensibility)****可修改性(modifiability)****可塑性(plasticity)**

和之前提到的可靠性、可伸缩性一样,实现这些目标也没有简单的解决方案。不过我们会试着想象具有可操作性,简单性和可演化性的系统会是什么样子。

Expand Down
43 changes: 22 additions & 21 deletions ch10.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@

Web和越来越多的基于HTTP/REST的API使交互的请求/响应风格变得如此普遍,以至于很容易将其视为理所当然。但我们应该记住,这不是构建系统的唯一方式,其他方法也有其优点。我们来看看三种不同类型的系统:

***服务(在线系统)***
* 服务(在线系统)

服务等待客户的请求或指令到达。每收到一个,服务会试图尽快处理它,并发回一个响应。响应时间通常是服务性能的主要衡量指标,可用性通常非常重要(如果客户端无法访问服务,用户可能会收到错误消息)。
服务等待客户的请求或指令到达。每收到一个,服务会试图尽快处理它,并发回一个响应。响应时间通常是服务性能的主要衡量指标,可用性通常非常重要(如果客户端无法访问服务,用户可能会收到错误消息)。

***批处理系统(离线系统)***
* 批处理系统(离线系统)

一个批处理系统有大量的输入数据,跑一个**作业(job)** 来处理它,并生成一些输出数据,这往往需要一段时间(从几分钟到几天),所以通常不会有用户等待作业完成。相反,批量作业通常会定期运行(例如,每天一次)。批处理作业的主要性能衡量标准通常是吞吐量(处理特定大小的输入所需的时间)。本章中讨论的就是批处理。
一个批处理系统有大量的输入数据,跑一个**作业(job)** 来处理它,并生成一些输出数据,这往往需要一段时间(从几分钟到几天),所以通常不会有用户等待作业完成。相反,批量作业通常会定期运行(例如,每天一次)。批处理作业的主要性能衡量标准通常是吞吐量(处理特定大小的输入所需的时间)。本章中讨论的就是批处理。

***流处理系统(准实时系统)***
* 流处理系统(准实时系统)

流处理介于在线和离线(批处理)之间,所以有时候被称为**准实时(near-real-time)****准在线(nearline)** 处理。像批处理系统一样,流处理消费输入并产生输出(并不需要响应请求)。但是,流式作业在事件发生后不久就会对事件进行操作,而批处理作业则需等待固定的一组输入数据。这种差异使流处理系统比起批处理系统具有更低的延迟。由于流处理基于批处理,我们将在[第十一章](ch11.md)讨论它。
流处理介于在线和离线(批处理)之间,所以有时候被称为**准实时(near-real-time)****准在线(nearline)** 处理。像批处理系统一样,流处理消费输入并产生输出(并不需要响应请求)。但是,流式作业在事件发生后不久就会对事件进行操作,而批处理作业则需等待固定的一组输入数据。这种差异使流处理系统比起批处理系统具有更低的延迟。由于流处理基于批处理,我们将在[第十一章](ch11.md)讨论它。

正如我们将在本章中看到的那样,批处理是构建可靠、可伸缩和可维护应用程序的重要组成部分。例如,2004年发布的批处理算法Map-Reduce(可能被过分热情地)被称为“造就Google大规模可伸缩性的算法”【2】。随后在各种开源数据系统中得到应用,包括Hadoop,CouchDB和MongoDB。

Expand Down Expand Up @@ -224,12 +224,13 @@ MapReduce是一个编程框架,你可以使用它编写代码来处理HDFS等

要创建MapReduce作业,你需要实现两个回调函数,Mapper和Reducer,其行为如下(请参阅“[MapReduce查询](ch2.md#MapReduce查询)”):

***Mapper***
* Mapper

Mapper会在每条输入记录上调用一次,其工作是从输入记录中提取键值。对于每个输入,它可以生成任意数量的键值对(包括None)。它不会保留从一个输入记录到下一个记录的任何状态,因此每个记录都是独立处理的。
Mapper会在每条输入记录上调用一次,其工作是从输入记录中提取键值。对于每个输入,它可以生成任意数量的键值对(包括None)。它不会保留从一个输入记录到下一个记录的任何状态,因此每个记录都是独立处理的。

***Reducer***
MapReduce框架拉取由Mapper生成的键值对,收集属于同一个键的所有值,并在这组值上迭代调用Reducer。 Reducer可以产生输出记录(例如相同URL的出现次数)。
* Reducer

MapReduce框架拉取由Mapper生成的键值对,收集属于同一个键的所有值,并在这组值上迭代调用Reducer。 Reducer可以产生输出记录(例如相同URL的出现次数)。

在Web服务器日志的例子中,我们在第5步中有第二个`sort`命令,它按请求数对URL进行排序。在MapReduce中,如果你需要第二个排序阶段,则可以通过编写第二个MapReduce作业并将第一个作业的输出用作第二个作业的输入来实现它。这样看来,Mapper的作用是将数据放入一个适合排序的表单中,并且Reducer的作用是处理已排序的数据。

Expand Down Expand Up @@ -686,30 +687,30 @@ Spark,Flink和Tez避免将中间状态写入HDFS,因此它们采取了不同

分布式批处理框架需要解决的两个主要问题是:

***分区***
* 分区

在MapReduce中,Mapper根据输入文件块进行分区。Mapper的输出被重新分区、排序并合并到可配置数量的Reducer分区中。这一过程的目的是把所有的**相关**数据(例如带有相同键的所有记录)都放在同一个地方。
在MapReduce中,Mapper根据输入文件块进行分区。Mapper的输出被重新分区、排序并合并到可配置数量的Reducer分区中。这一过程的目的是把所有的**相关**数据(例如带有相同键的所有记录)都放在同一个地方。

后MapReduce时代的数据流引擎若非必要会尽量避免排序,但它们也采取了大致类似的分区方法。
后MapReduce时代的数据流引擎若非必要会尽量避免排序,但它们也采取了大致类似的分区方法。

***容错***
* 容错

MapReduce经常写入磁盘,这使得从单个失败的任务恢复很轻松,无需重新启动整个作业,但在无故障的情况下减慢了执行速度。数据流引擎更多地将中间状态保存在内存中,更少地物化中间状态,这意味着如果节点发生故障,则需要重算更多的数据。确定性算子减少了需要重算的数据量。
MapReduce经常写入磁盘,这使得从单个失败的任务恢复很轻松,无需重新启动整个作业,但在无故障的情况下减慢了执行速度。数据流引擎更多地将中间状态保存在内存中,更少地物化中间状态,这意味着如果节点发生故障,则需要重算更多的数据。确定性算子减少了需要重算的数据量。


我们讨论了几种MapReduce的连接算法,其中大多数也在MPP数据库和数据流引擎内部使用。它们也很好地演示了分区算法是如何工作的:

***排序合并连接***
* 排序合并连接

每个参与连接的输入都通过一个提取连接键的Mapper。通过分区、排序和合并,具有相同键的所有记录最终都会进入相同的Reducer调用。这个函数能输出连接好的记录。
每个参与连接的输入都通过一个提取连接键的Mapper。通过分区、排序和合并,具有相同键的所有记录最终都会进入相同的Reducer调用。这个函数能输出连接好的记录。

***广播散列连接***
* 广播散列连接

两个连接输入之一很小,所以它并没有分区,而且能被完全加载进一个哈希表中。因此,你可以为连接输入大端的每个分区启动一个Mapper,将输入小端的散列表加载到每个Mapper中,然后扫描大端,一次一条记录,并为每条记录查询散列表。
两个连接输入之一很小,所以它并没有分区,而且能被完全加载进一个哈希表中。因此,你可以为连接输入大端的每个分区启动一个Mapper,将输入小端的散列表加载到每个Mapper中,然后扫描大端,一次一条记录,并为每条记录查询散列表。

***分区散列连接***
* 分区散列连接

如果两个连接输入以相同的方式分区(使用相同的键,相同的散列函数和相同数量的分区),则可以独立地对每个分区应用散列表方法。
如果两个连接输入以相同的方式分区(使用相同的键,相同的散列函数和相同数量的分区),则可以独立地对每个分区应用散列表方法。

分布式批处理引擎有一个刻意限制的编程模型:回调函数(比如Mapper和Reducer)被假定是无状态的,而且除了指定的输出外,必须没有任何外部可见的副作用。这一限制允许框架在其抽象下隐藏一些困难的分布式系统问题:当遇到崩溃和网络问题时,任务可以安全地重试,任何失败任务的输出都被丢弃。如果某个分区的多个任务成功,则其中只有一个能使其输出实际可见。

Expand Down
Loading

0 comments on commit 9b3bd96

Please sign in to comment.