mirror of
https://github.com/Vonng/ddia.git
synced 2024-12-06 15:20:12 +08:00
commit
73003f49a6
@ -13,7 +13,7 @@
|
||||
* [第七章:事务](ch7.md)
|
||||
* [第八章:分布式系统的麻烦](ch8.md)
|
||||
* [第九章:一致性与共识](ch9.md)
|
||||
* [第三部分:派生数据](part-iii.md)
|
||||
* [第三部分:衍生数据](part-iii.md)
|
||||
* [第十章:批处理](ch10.md)
|
||||
* [第十一章:流处理](ch11.md)
|
||||
* [第十二章:数据系统的未来](ch12.md)
|
||||
|
2
ch10.md
2
ch10.md
@ -909,4 +909,4 @@ top5.each{|count, url| puts "#{count} #{url}" } # 5
|
||||
|
||||
| 上一章 | 目录 | 下一章 |
|
||||
| --------------------------------- | ------------------------------- | ------------------------ |
|
||||
| [第三部分:派生数据](part-iii.md) | [设计数据密集型应用](README.md) | [第十章:流处理](ch7.md) |
|
||||
| [第三部分:派生数据](part-iii.md) | [设计数据密集型应用](README.md) | [第十一章:流处理](ch11.md) |
|
25
ch11.md
25
ch11.md
@ -33,22 +33,13 @@
|
||||
|
||||
事件可能被编码为文本字符串或JSON,或者某种二进制编码,如[第4章](ch4.md)所述。这种编码允许你存储一个事件,例如将其附加到一个文件,将其插入关系表,或将其写入文档数据库。它还允许你通过网络将事件发送到另一个节点以进行处理。
|
||||
|
||||
在批处理领域,作业的输入和输出是文件(也许在分布式文件系统上)。什么是类似的流媒体?
|
||||
|
||||
当输入是一个文件(一个字节序列)时,第一个处理步骤通常是将其解析为一系列记录。在流处理的上下文中,记录通常被称为事件,但它本质上是一样的:一个小的,自包含的,不可变的对象,包含某个时间点发生的事情的细节。一个事件通常包含一个时间戳,指示何时根据时钟来发生(参见“[单调钟与时钟](ch8.md#单调钟与时钟)”)。
|
||||
|
||||
例如,发生的事情可能是用户采取的行动,例如查看页面或进行购买。它也可能来源于机器,例如来自温度传感器的周期性测量或者CPU利用率度量。在“[使用Unix工具进行批处理](ch10.md#使用Unix工具进行批处理)”的示例中,Web服务器日志的每一行都是一个事件。
|
||||
|
||||
事件可能被编码为文本字符串或JSON,或者以某种二进制形式编码,如[第4章](ch4.md)所述。这种编码允许你存储一个事件,例如将其追加写入一个文件,将其插入关系型表,或将其写入文档数据库。它还允许你通过网络将事件发送到其他节点以进行处理。
|
||||
|
||||
在批处理中,文件被写入一次,然后可能被多个作业读取。类似地,在流处理术语中,一个事件由**生产者(producer)**(也称为**发布者(publisher)**或**发送者(sender)**)生成一次,然后可能由多个**消费者(consumer)**(**订阅者(subscribers)**或**接收者(recipients)**)进行处理【3】。在文件系统中,文件名标识一组相关记录;在流媒体系统中,相关的事件通常被聚合为一个**主题(topic)**或**流(stream)**。
|
||||
在批处理中,文件被写入一次,然后可能被多个作业读取。类似地,在流处理术语中,一个事件由 **生产者(producer)** (也称为 **发布者(publisher)** 或 **发送者(sender)** )生成一次,然后可能由多个 **消费者(consumer)** ( **订阅者(subscribers)** 或 **接收者(recipients)** )进行处理【3】。在文件系统中,文件名标识一组相关记录;在流式系统中,相关的事件通常被聚合为一个 **主题(topic)** 或 **流(stream)** 。
|
||||
|
||||
原则上讲,文件或数据库就足以连接生产者和消费者:生产者将其生成的每个事件写入数据存储,且每个消费者定期轮询数据存储,检查自上次运行以来新出现的事件。这实际上正是批处理在每天结束时处理当天数据时所做的事情。
|
||||
|
||||
但当我们想要进行低延迟的连续处理时,如果数据存储不是为这种用途专门设计的,那么轮询开销就会很大。轮询的越频繁,能返回新事件的请求比例就越低,而额外开销也就越高。相比之下,最好能在新事件出现时直接通知消费者。
|
||||
|
||||
数据库在传统上对这种通知机制支持的并不好,关系型数据库通常有**触发器(trigger)**,它们可以对变化作出反应(如,插入表中的一行),但它们的功能非常有限,而且在数据库设计中算是一种事后反思【4,5】。相应的是,已经有为传递事件通知这一目开发的专用工具已经被开发出来。
|
||||
|
||||
数据库在传统上对这种通知机制支持的并不好,关系型数据库通常有 **触发器(trigger)** ,它们可以对变化作出反应(如,插入表中的一行),但是它们的功能非常有限,并且在数据库设计中有些后顾之忧【4,5】。相应的是,已经开发了专门的工具来提供事件通知。
|
||||
|
||||
|
||||
### 消息系统
|
||||
@ -262,7 +253,7 @@
|
||||
|
||||
#### 变更数据捕获的实现
|
||||
|
||||
我们可以将日志消费者叫做**衍生数据系统**,正如在第三部分的[介绍](part-iii.md)中所讨论的:存储在搜索索引和数据仓库中的数据,只是**记录系统**数据的额外视图。变更数据捕获是一种机制,可确保对记录系统所做的所有更改都反映在派生数据系统中,以便派生系统具有数据的准确副本。
|
||||
我们可以将日志消费者叫做**衍生数据系统**,正如在第三部分的[介绍](part-iii.md)中所讨论的:存储在搜索索引和数据仓库中的数据,只是**记录系统**数据的额外视图。变更数据捕获是一种机制,可确保对记录系统所做的所有更改都反映在衍生数据系统中,以便衍生系统具有数据的准确副本。
|
||||
|
||||
从本质上说,变更数据捕获使得一个数据库成为领导者(被捕获变化的数据库),并将其他组件变为追随者。基于日志的消息代理非常适合从源数据库传输变更事件,因为它保留了消息的顺序(避免了[图11-2](img/fig11-2.png)的重新排序问题)。
|
||||
|
||||
@ -365,7 +356,7 @@ $$
|
||||
|
||||
如果你持久存储了变更日志,那么重现状态就非常简单。如果你认为事件日志是你的记录系统,而所有的衍生状态都从它派生而来,那么系统中的数据流动就容易理解的多。正如帕特·赫兰(Pat Helland)所说的【52】:
|
||||
|
||||
> 事务日志记录了数据库的所有变更。高速追加下入是更改日志的唯一方法。从这个角度来看,数据库的内容其实是日志中记录最新值的缓存。日志才是真相,数据库是日志子集的缓存,这一缓存子集恰好来自日志中每条记录与索引值的最新值。
|
||||
> 事务日志记录了数据库的所有变更。高速追加是更改日志的唯一方法。从这个角度来看,数据库的内容其实是日志中记录最新值的缓存。日志才是真相,数据库是日志子集的缓存,这一缓存子集恰好来自日志中每条记录与索引值的最新值。
|
||||
|
||||
日志压缩(如“[日志压缩](#日志压缩)”中所述)是连接日志与数据库状态之间的桥梁:它只保留每条记录的最新版本,并丢弃被覆盖的版本。
|
||||
|
||||
@ -512,7 +503,7 @@ $$
|
||||
|
||||
而且,消息延迟还可能导致无法预测消息顺序。例如,假设用户首先发出一个Web请求(由Web服务器A处理),然后发出第二个请求(由服务器B处理)。 A和B发出描述它们所处理请求的事件,但是B的事件在A的事件发生之前到达消息代理。现在,流处理器将首先看到B事件,然后看到A事件,即使它们实际上是以相反的顺序发生的。
|
||||
|
||||
有一个类比也许能帮助理解,“星球大战”电影:第四集于1977年发行,第五集于1980年,第六集于1983年,紧随其后的是1999年的第一集,2002年的第二集,和2005年的三集,以及2015年的第七集【80】[^ii]。如果你按照按照它们上映的顺序观看电影,你处理电影的顺序与它们叙事的顺序就是不一致的。 (集数编号就像事件时间戳,而你观看电影的日期就是处理时间)作为人类,我们能够应对这种不连续性,但是流处理算法需要专门写就,以适应这种时机与顺序的问题。
|
||||
有一个类比也许能帮助理解,“星球大战”电影:第四集于1977年发行,第五集于1980年,第六集于1983年,紧随其后的是1999年的第一集,2002年的第二集,和2005年的三集,以及2015年的第七集【80】[^ii]。如果你按照按照它们上映的顺序观看电影,你处理电影的顺序与它们叙事的顺序就是不一致的。 (集数编号就像事件时间戳,而你观看电影的日期就是处理时间)作为人类,我们能够应对这种不连续性,但是流处理算法需要专门编写,以适应这种时机与顺序的问题。
|
||||
|
||||
[^ii]: 感谢Flink社区的Kostas Kloudas提出这个比喻。
|
||||
|
||||
@ -561,7 +552,7 @@ $$
|
||||
|
||||
***跳动窗口(Hopping Window)***
|
||||
|
||||
跳动窗口也有着固定的长度,但允许窗口重叠以提供一些平滑。例如,一个带有1分钟跳跃步长的5分钟窗口将包含`10:03:00`至`10:07:59`之间的事件,而下一个窗口将覆盖`10:04:00`至`10:08`之间的事件: 59,等等。通过首先计算1分钟的滚动窗口,然后在几个相邻窗口上进行聚合,可以实现这种跳动窗口。
|
||||
跳动窗口也有着固定的长度,但允许窗口重叠以提供一些平滑。例如,一个带有1分钟跳跃步长的5分钟窗口将包含`10:03:00`至`10:07:59`之间的事件,而下一个窗口将覆盖`10:04:00`至`10:08:59`之间的事件,等等。通过首先计算1分钟的滚动窗口,然后在几个相邻窗口上进行聚合,可以实现这种跳动窗口。
|
||||
|
||||
***滑动窗口(Sliding Window)***
|
||||
|
||||
@ -569,7 +560,7 @@ $$
|
||||
|
||||
***会话窗口(Session window)***
|
||||
|
||||
与其他窗口类型不同,会话窗口没有固定的持续时间,而定义为:将同一用户出现时间相近的所有事件分组在一起,而当用户一段时间没有活动时(例如,如果30分钟内没有事件)窗口结束。会话切分是网站分析的常见需求(参阅“[GROUP BY](ch10.md#GROUP BY)”)。
|
||||
与其他窗口类型不同,会话窗口没有固定的持续时间,而定义为:将同一用户出现时间相近的所有事件分组在一起,而当用户一段时间没有活动时(例如,如果30分钟内没有事件)窗口结束。会话切分是网站分析的常见需求(参阅“[GROUP BY](ch10.md#GROUP\ BY)”)。
|
||||
|
||||
### 流式连接
|
||||
|
||||
@ -940,4 +931,4 @@ GROUP BY follows.follower_id
|
||||
|
||||
| 上一章 | 目录 | 下一章 |
|
||||
| ------------------------- | ------------------------------- | ---------------------------------- |
|
||||
| [第十章:批处理](ch10.md) | [设计数据密集型应用](README.md) | [第十二章:数据系统的未来](ch7.md) |
|
||||
| [第十章:批处理](ch10.md) | [设计数据密集型应用](README.md) | [第十二章:数据系统的未来](ch12.md) |
|
6
ch12.md
6
ch12.md
@ -10,9 +10,9 @@
|
||||
|
||||
[TOC]
|
||||
|
||||
到目前为止,本书主要描述的是**实然**问题:现在事情**是**什么样的。在这最后一章中,我们将放眼未来,讨论**应然**的问题:事情**应该**是什么样子的。我将提出一些想法与方法,我相信它们能从根本上改进我们设计与构建应用的方式。
|
||||
到目前为止,本书主要描述的是**现状**。在这最后一章中,我们将放眼**未来**,讨论应该是怎么样的:我将提出一些想法与方法,我相信它们能从根本上改进我们设计与构建应用的方式。
|
||||
|
||||
对未来的看法与推测当然具有很大的主观性。所以在撰写本章时,当提及我个人的观点时会使用第一人称。您完全可以不同意这些观点并提出自己的看法,但我希望本章中的概念,至少能成为富有成效讨论的出发点,并澄清一些经常被混淆的概念。
|
||||
对未来的看法与推测当然具有很大的主观性。所以在撰写本章时,当提及我个人的观点时会使用第一人称。您完全可以不同意这些观点并提出自己的看法,但我希望本章中的概念,至少能成为富有成效的讨论出发点,并澄清一些经常被混淆的概念。
|
||||
|
||||
[第1章](ch1.md)概述了本书的目标:探索如何创建**可靠**,**可扩展**和**可维护**的应用与系统。这一主题贯穿了所有的章节:例如,我们讨论了许多有助于提高可靠性的容错算法,有助于提高可扩展性的分区,以及有助于提高可维护性的演化与抽象机制。在本章中,我们将把所有这些想法结合在一起,并在它们的基础上展望未来。我们的目标是,发现如何设计出比现有应用更好的应用 —— 健壮,正确,可演化,且最终对人类有益。
|
||||
|
||||
@ -850,7 +850,7 @@ COMMIT;
|
||||
|
||||
俗话说,“知识就是力量”。更进一步,“在避免自己被审视的同时审视他人,是权力最重要的形式之一”【105】。这就是极权政府想要监控的原因:这让它们有能力控制全体居民。尽管今天的科技公司并没有公开地寻求政治权力,但是它们积累的数据与知识却给它们带来了很多权力,其中大部分是在公共监督之外偷偷进行的【106】。
|
||||
|
||||
#### 记着工业革命
|
||||
#### 回顾工业革命
|
||||
|
||||
数据是信息时代的决定性特征。互联网,数据存储,处理和软件驱动的自动化正在对全球经济和人类社会产生重大影响。我们的日常生活与社会组织在过去十年中发生了变化,而且在未来的十年中可能会继续发生根本性的变化,所以我们会想到与工业革命对比【87,96】。
|
||||
|
||||
|
2
ch2.md
2
ch2.md
@ -144,7 +144,7 @@ JSON表示比[图2-1](img/fig2-1.png)中的多表模式具有更好的**局部
|
||||
|
||||
[^ii]: 关于关系模型的文献区分了几种不同的规范形式,但这些区别几乎没有实际意义。一个经验法则是,如果重复存储了可以存储在一个地方的值,则模式就不是**规范化(normalized)**的。
|
||||
|
||||
> 数据库管理员和开发人员喜欢争论规范化和非规范化,让我们暂时保留判断吧。在本书的[第三部分](part-iii.md),我们将回到这个话题,探讨系统的方法用以处理缓存,非规范化和派生数据。
|
||||
> 数据库管理员和开发人员喜欢争论规范化和非规范化,让我们暂时保留判断吧。在本书的[第三部分](part-iii.md),我们将回到这个话题,探讨系统的方法用以处理缓存,非规范化和衍生数据。
|
||||
|
||||
不幸的是,对这些数据进行规范化需要多对一的关系(许多人生活在一个特定的地区,许多人在一个特定的行业工作),这与文档模型不太吻合。在关系数据库中,通过ID来引用其他表中的行是正常的,因为连接很容易。在文档数据库中,一对多树结构没有必要用连接,对连接的支持通常很弱[^iii]。
|
||||
|
||||
|
2
ch7.md
2
ch7.md
@ -955,4 +955,4 @@ WHERE room_id = 123 AND
|
||||
|
||||
| 上一章 | 目录 | 下一章 |
|
||||
| ---------------------- | ------------------------------- | ---------------------------------- |
|
||||
| [第六章:分区](ch6.md) | [设计数据密集型应用](README.md) | [第八章:分布式系统的麻烦](ch7.md) |
|
||||
| [第六章:分区](ch6.md) | [设计数据密集型应用](README.md) | [第八章:分布式系统的麻烦](ch8.md) |
|
||||
|
4
ch9.md
4
ch9.md
@ -283,7 +283,7 @@
|
||||
|
||||
> ### CAP定理没有帮助
|
||||
>
|
||||
> CAP有时以这种面目出现:一致性,可用性和分区容忍:三者只能择其二。不幸的是这种说法很有误导性【32】,因为网络分区是一种错误,所以它并不是一个选项:不管你喜不喜欢它都会发生【38】。
|
||||
> CAP有时以这种面目出现:一致性,可用性和分区容错性:三者只能择其二。不幸的是这种说法很有误导性【32】,因为网络分区是一种错误,所以它并不是一个选项:不管你喜不喜欢它都会发生【38】。
|
||||
>
|
||||
> 在网络正常工作的时候,系统可以提供一致性(线性一致性)和整体可用性。发生网络故障时,你必须在线性一致性和整体可用性之间做出选择。因此,一个更好的表达CAP的方法可以是一致的,或者在分区时可用【39】。一个更可靠的网络需要减少这个选择,但是在某些时候选择是不可避免的。
|
||||
>
|
||||
@ -1201,5 +1201,5 @@
|
||||
|
||||
| 上一章 | 目录 | 下一章 |
|
||||
| ---------------------------------- | ------------------------------- | --------------------------------- |
|
||||
| [第八章:分布式系统的麻烦](ch8.md) | [设计数据密集型应用](README.md) | [第三部分:派生数据](part-iii.md) |
|
||||
| [第八章:分布式系统的麻烦](ch8.md) | [设计数据密集型应用](README.md) | [第三部分:衍生数据](part-iii.md) |
|
||||
|
||||
|
@ -88,9 +88,9 @@
|
||||
|
||||
|
||||
|
||||
### 派生数据(derived data)
|
||||
### 衍生数据(derived data)
|
||||
|
||||
一种数据集,根据其他数据通过可重复运行的流程创建。必要时,你可以运行该流程再次创建派生数据。派生数据通常用于提高特定数据的读取速度。常见的派生数据有索引、缓存和物化视图。参见第三部分的介绍。
|
||||
一种数据集,根据其他数据通过可重复运行的流程创建。必要时,你可以运行该流程再次创建衍生数据。衍生数据通常用于提高特定数据的读取速度。常见的衍生数据有索引、缓存和物化视图。参见第三部分的介绍。
|
||||
|
||||
|
||||
|
||||
@ -338,7 +338,7 @@
|
||||
|
||||
### 记录系统(system of record)
|
||||
|
||||
一个保存主要权威版本数据的系统,也被称为真相的来源。首先在这里写入数据变更,其他数据集可以从记录系统派生。 参见第三部分的介绍。
|
||||
一个保存主要权威版本数据的系统,也被称为真相的来源。首先在这里写入数据变更,其他数据集可以从记录系统衍生。 参见第三部分的介绍。
|
||||
|
||||
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
大多数数据库,存储引擎和查询语言,本质上既不是记录系统也不是衍生系统。数据库只是一个工具:如何使用它取决于你自己。**记录系统和衍生数据系统之间的区别不在于工具,而在于应用程序中的使用方式。**
|
||||
|
||||
通过梳理数据的派衍生关系,可以清楚地理解一个令人困惑的系统架构。这将贯穿本书的这一部分。
|
||||
通过梳理数据的衍生关系,可以清楚地理解一个令人困惑的系统架构。这将贯穿本书的这一部分。
|
||||
|
||||
## 章节概述
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user