mirror of
https://github.com/Vonng/ddia.git
synced 2024-12-06 15:20:12 +08:00
fix punctuation marks
This commit is contained in:
parent
072814f29e
commit
bbc7bb8d5a
@ -17,7 +17,7 @@
|
||||
>
|
||||
> —— Vonng
|
||||
|
||||
现今,尤其是在互联网领域,大多数应用都属于数据密集型应用。本书从底层数据结构到顶层架构设计,将数据系统设计中的精髓娓娓道来。其中的宝贵经验无论是对架构师,DBA、还是后端工程师、甚至产品经理都会有帮助。
|
||||
现今,尤其是在互联网领域,大多数应用都属于数据密集型应用。本书从底层数据结构到顶层架构设计,将数据系统设计中的精髓娓娓道来。其中的宝贵经验无论是对架构师、DBA、还是后端工程师、甚至产品经理都会有帮助。
|
||||
|
||||
这是一本理论结合实践的书,书中很多问题,译者在实际场景中都曾遇到过,读来让人击节扼腕。如果能早点读到这本书,该少走多少弯路啊!
|
||||
|
||||
@ -138,9 +138,9 @@
|
||||
0. 全文校订 by [@yingang](https://github.com/yingang)
|
||||
1. [序言初翻修正](https://github.com/Vonng/ddia/commit/afb5edab55c62ed23474149f229677e3b42dfc2c) by [@seagullbird](https://github.com/Vonng/ddia/commits?author=seagullbird)
|
||||
2. [第一章语法标点校正](https://github.com/Vonng/ddia/commit/973b12cd8f8fcdf4852f1eb1649ddd9d187e3644) by [@nevertiree](https://github.com/Vonng/ddia/commits?author=nevertiree)
|
||||
3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 与[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by @[MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex)
|
||||
3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 与[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by [@MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex)
|
||||
4. [第一部分](part-i.md)前言,[ch2](ch2.md)校正 by [@jiajiadebug](https://github.com/Vonng/ddia/commits?author=jiajiadebug)
|
||||
5. [词汇表](glossary.md)、[后记](colophon.md)关于野猪的部分 by @[Chowss](https://github.com/Vonng/ddia/commits?author=Chowss)
|
||||
5. [词汇表](glossary.md)、[后记](colophon.md)关于野猪的部分 by [@Chowss](https://github.com/Vonng/ddia/commits?author=Chowss)
|
||||
6. [繁體中文](https://github.com/Vonng/ddia/pulls)版本与转换脚本 by [@afunTW](https://github.com/afunTW)
|
||||
7. 感谢所有作出贡献,提出意见的朋友们:
|
||||
|
||||
|
22
ch2.md
22
ch2.md
@ -226,7 +226,7 @@ CODASYL中的查询是通过利用遍历记录列和跟随访问路径表在数
|
||||
|
||||
#### 哪种数据模型更有助于简化应用代码?
|
||||
|
||||
如果应用程序中的数据具有类似文档的结构(即,一对多关系树,通常一次性加载整个树),那么使用文档模型可能是一个好主意。将类似文档的结构分解成多个表(如[图2-1](img/fig2-1.png)中的`positions`,`education`和`contact_info`)的关系技术可能导致繁琐的模式和不必要的复杂的应用程序代码。
|
||||
如果应用程序中的数据具有类似文档的结构(即,一对多关系树,通常一次性加载整个树),那么使用文档模型可能是一个好主意。将类似文档的结构分解成多个表(如[图2-1](img/fig2-1.png)中的`positions`、`education`和`contact_info`)的关系技术可能导致繁琐的模式和不必要的复杂的应用程序代码。
|
||||
|
||||
文档模型有一定的局限性:例如,不能直接引用文档中的嵌套的项目,而是需要说“用户251的位置列表中的第二项”(很像层次模型中的访问路径)。但是,只要文件嵌套不太深,这通常不是问题。
|
||||
|
||||
@ -286,7 +286,7 @@ UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
|
||||
|
||||
自2000年代中期以来,大多数关系数据库系统(MySQL除外)都已支持XML。这包括对XML文档进行本地修改的功能,以及在XML文档中进行索引和查询的功能。这允许应用程序使用那种与文档数据库应当使用的非常类似的数据模型。
|
||||
|
||||
从9.3版本开始的PostgreSQL 【8】,从5.7版本开始的MySQL以及从版本10.5开始的IBM DB2 [30]也对JSON文档提供了类似的支持级别。鉴于用在Web APIs的JSON流行趋势,其他关系数据库很可能会跟随他们的脚步并添加JSON支持。
|
||||
从9.3版本开始的PostgreSQL 【8】,从5.7版本开始的MySQL以及从版本10.5开始的IBM DB2【30】也对JSON文档提供了类似的支持级别。鉴于用在Web APIs的JSON流行趋势,其他关系数据库很可能会跟随他们的脚步并添加JSON支持。
|
||||
|
||||
在文档数据库中,RethinkDB在其查询语言中支持类似关系的连接,一些MongoDB驱动程序可以自动解析数据库引用(有效地执行客户端连接,尽管这可能比在数据库中执行的连接慢,需要额外的网络往返,并且优化更少)。
|
||||
|
||||
@ -541,18 +541,18 @@ db.observations.aggregate([
|
||||
|
||||
### 属性图
|
||||
|
||||
在属性图模型中,每个**顶点(vertex)** 包括:
|
||||
在属性图模型中,每个顶点(vertex)包括:
|
||||
|
||||
* 唯一的标识符
|
||||
* 一组 **出边(outgoing edges)**
|
||||
* 一组 **入边(ingoing edges)**
|
||||
* 一组出边(outgoing edges)
|
||||
* 一组入边(ingoing edges)
|
||||
* 一组属性(键值对)
|
||||
|
||||
每条 **边(edge)** 包括:
|
||||
每条边(edge)包括:
|
||||
|
||||
* 唯一标识符
|
||||
* **边的起点/尾部顶点(tail vertex)**
|
||||
* **边的终点/头部顶点(head vertex)**
|
||||
* 边的起点(**尾部顶点**,即tail vertex)
|
||||
* 边的终点(**头部顶点**,即head vertex)
|
||||
* 描述两个顶点之间关系类型的标签
|
||||
* 一组属性(键值对)
|
||||
|
||||
@ -640,11 +640,11 @@ RETURN person.name
|
||||
|
||||
答案是肯定的,但有些困难。在关系数据库中,你通常会事先知道在查询中需要哪些连接。在图查询中,你可能需要在找到待查找的顶点之前,遍历可变数量的边。也就是说,连接的数量事先并不确定。
|
||||
|
||||
在我们的例子中,这发生在Cypher查询中的`() -[:WITHIN*0..]-> ()`规则中。一个人的`LIVES_IN`边可以指向任何类型的位置:街道、城市、地区、地区、国家等。城市可以在一个地区,在一个州内的一个地区,在一个国家内的一个州等等。`LIVES_IN`边可以直接指向正在查找的位置,或者一个在位置层次结构中隔了数层的位置。
|
||||
在我们的例子中,这发生在Cypher查询中的`() -[:WITHIN*0..]-> ()`规则中。一个人的`LIVES_IN`边可以指向任何类型的位置:街道、城市、地区、地区、国家等。一个城市可以在(WITHIN)一个地区内,一个地区可以在(WITHIN)在一个州内,一个州可以在(WITHIN)一个国家内,等等。`LIVES_IN`边可以直接指向正在查找的位置,或者一个在位置层次结构中隔了数层的位置。
|
||||
|
||||
在Cypher中,用`WITHIN * 0`非常简洁地表述了上述事实:“沿着`WITHIN`边,零次或多次”。它很像正则表达式中的`*`运算符。
|
||||
在Cypher中,用`WITHIN*0..`非常简洁地表述了上述事实:“沿着`WITHIN`边,零次或多次”。它很像正则表达式中的`*`运算符。
|
||||
|
||||
自SQL:1999,查询可变长度遍历路径的思想可以使用称为**递归公用表表达式**(`WITH RECURSIVE`语法)的东西来表示。[例2-5]()显示了同样的查询 - 查找从美国移民到欧洲的人的姓名 - 在SQL使用这种技术(PostgreSQL,IBM DB2,Oracle和SQL Server均支持)来表述。但是,与Cypher相比,其语法非常笨拙。
|
||||
自SQL:1999,查询可变长度遍历路径的思想可以使用称为**递归公用表表达式**(`WITH RECURSIVE`语法)的东西来表示。[例2-5]()显示了同样的查询 - 查找从美国移民到欧洲的人的姓名 - 在SQL使用这种技术(PostgreSQL、IBM DB2、Oracle和SQL Server均支持)来表述。但是,与Cypher相比,其语法非常笨拙。
|
||||
|
||||
**例2-5 与示例2-4同样的查询,在SQL中使用递归公用表表达式表示**
|
||||
|
||||
|
14
ch4.md
14
ch4.md
@ -70,7 +70,7 @@
|
||||
|
||||
因此,除非临时使用,采用语言内置编码通常是一个坏主意。
|
||||
|
||||
### JSON,XML和二进制变体
|
||||
### JSON、XML和二进制变体
|
||||
|
||||
当我们谈到可以被多种编程语言读写的标准编码时,JSON和XML是最显眼的角逐者。它们广为人知,广受支持,也“广受憎恶”。 XML经常收到批评:过于冗长与且过份复杂【9】。 JSON的流行则主要源于(通过成为JavaScript的一个子集)Web浏览器的内置支持,以及相对于XML的简单性。 CSV是另一种流行的与语言无关的格式,尽管其功能相对较弱。
|
||||
|
||||
@ -148,7 +148,7 @@ Thrift和Protocol Buffers每一个都带有一个代码生成工具,它采用
|
||||
|
||||
**图4-2 使用Thrift二进制协议编码的记录**
|
||||
|
||||
[^iii]: 实际上,Thrift有三种二进制协议:BinaryProtocol、CompactProtocol和DenseProtocol,尽管DenseProtocol只支持C ++实现,所以不算作跨语言[18]。 除此之外,它还有两种不同的基于JSON的编码格式【19】。 真逗!
|
||||
[^iii]: 实际上,Thrift有三种二进制协议:BinaryProtocol、CompactProtocol和DenseProtocol,尽管DenseProtocol只支持C ++实现,所以不算作跨语言【18】。 除此之外,它还有两种不同的基于JSON的编码格式【19】。 真逗!
|
||||
|
||||
与[图4-1](Img/fig4-1.png)类似,每个字段都有一个类型注释(用于指示它是一个字符串,整数,列表等),还可以根据需要指定长度(字符串的长度,列表中的项目数) 。出现在数据中的字符串`(“Martin”, “daydreaming”, “hacking”)`也被编码为ASCII(或者说,UTF-8),与之前类似。
|
||||
|
||||
@ -395,7 +395,7 @@ Web浏览器不是唯一的客户端类型。例如,在移动设备或桌面
|
||||
|
||||
[^vi]: 即使在每个阵营内也有很多争论。 例如,**HATEOAS(超媒体作为应用程序状态的引擎)** 就经常引发讨论【35】。
|
||||
|
||||
REST不是一个协议,而是一个基于HTTP原则的设计哲学【34,35】。它强调简单的数据格式,使用URL来标识资源,并使用HTTP功能进行缓存控制,身份验证和内容类型协商。与SOAP相比,REST已经越来越受欢迎,至少在跨组织服务集成的背景下【36】,并经常与微服务相关[31]。根据REST原则设计的API称为RESTful。
|
||||
REST不是一个协议,而是一个基于HTTP原则的设计哲学【34,35】。它强调简单的数据格式,使用URL来标识资源,并使用HTTP功能进行缓存控制,身份验证和内容类型协商。与SOAP相比,REST已经越来越受欢迎,至少在跨组织服务集成的背景下【36】,并经常与微服务相关【31】。根据REST原则设计的API称为RESTful。
|
||||
|
||||
相比之下,SOAP是用于制作网络API请求的基于XML的协议[^vii]。虽然它最常用于HTTP,但其目的是独立于HTTP,并避免使用大多数HTTP功能。相反,它带有庞大而复杂的多种相关标准(Web服务框架,称为`WS-*`),它们增加了各种功能【37】。
|
||||
|
||||
@ -421,7 +421,7 @@ Web服务仅仅是通过网络进行API请求的一系列技术的最新版本
|
||||
* 每次调用本地功能时,通常需要大致相同的时间来执行。网络请求比函数调用要慢得多,而且其延迟也是非常可变的:好的时候它可能会在不到一毫秒的时间内完成,但是当网络拥塞或者远程服务超载时,可能需要几秒钟的时间完成一样的东西。
|
||||
* 调用本地函数时,可以高效地将引用(指针)传递给本地内存中的对象。当你发出一个网络请求时,所有这些参数都需要被编码成可以通过网络发送的一系列字节。如果参数是像数字或字符串这样的基本类型倒是没关系,但是对于较大的对象很快就会变成问题。
|
||||
|
||||
- 客户端和服务可以用不同的编程语言实现,所以RPC框架必须将数据类型从一种语言翻译成另一种语言。这可能会捅出大篓子,因为不是所有的语言都具有相同的类型 —— 例如回想一下JavaScript的数字大于$2^{53}$的问题(请参阅“[JSON,XML和二进制变体](#JSON,XML和二进制变体)”)。用单一语言编写的单个进程中不存在此问题。
|
||||
- 客户端和服务可以用不同的编程语言实现,所以RPC框架必须将数据类型从一种语言翻译成另一种语言。这可能会捅出大篓子,因为不是所有的语言都具有相同的类型 —— 例如回想一下JavaScript的数字大于$2^{53}$的问题(请参阅“[JSON、XML和二进制变体](#JSON、XML和二进制变体)”)。用单一语言编写的单个进程中不存在此问题。
|
||||
|
||||
所有这些因素意味着尝试使远程服务看起来像编程语言中的本地对象一样毫无意义,因为这是一个根本不同的事情。 REST的部分吸引力在于,它并不试图隐藏它是一个网络协议的事实(尽管这似乎并没有阻止人们在REST之上构建RPC库)。
|
||||
|
||||
@ -469,7 +469,7 @@ RPC方案的前后向兼容性属性从它使用的编码方式中继承:
|
||||
|
||||
#### 消息代理
|
||||
|
||||
过去,**消息代理(Message Broker)** 主要是TIBCO,IBM WebSphere和webMethods等公司的商业软件的秀场。最近像RabbitMQ,ActiveMQ,HornetQ,NATS和Apache Kafka这样的开源实现已经流行起来。我们将在[第十一章](ch11.md)中对它们进行更详细的比较。
|
||||
过去,**消息代理(Message Broker)** 主要是TIBCO、IBM WebSphere和webMethods等公司的商业软件的秀场。最近像RabbitMQ、ActiveMQ、HornetQ、NATS和Apache Kafka这样的开源实现已经流行起来。我们将在[第十一章](ch11.md)中对它们进行更详细的比较。
|
||||
|
||||
详细的交付语义因实现和配置而异,但通常情况下,消息代理的使用方式如下:一个进程将消息发送到指定的队列或主题,代理确保将消息传递给那个队列或主题的一个或多个消费者或订阅者。在同一主题上可以有许多生产者和许多消费者。
|
||||
|
||||
@ -507,8 +507,8 @@ Actor模型是单个进程中并发的编程模型。逻辑被封装在actor中
|
||||
我们讨论了几种数据编码格式及其兼容性属性:
|
||||
|
||||
* 编程语言特定的编码仅限于单一编程语言,并且往往无法提供前向和后向兼容性。
|
||||
* JSON,XML和CSV等文本格式非常普遍,其兼容性取决于你如何使用它们。他们有可选的模式语言,这有时是有用的,有时是一个障碍。这些格式对于数据类型有些模糊,所以你必须小心数字和二进制字符串。
|
||||
* 像Thrift,Protocol Buffers和Avro这样的二进制模式驱动格式允许使用清晰定义的前向和后向兼容性语义进行紧凑,高效的编码。这些模式可以用于静态类型语言的文档和代码生成。但是,他们有一个缺点,就是在数据可读之前需要对数据进行解码。
|
||||
* JSON、XML和CSV等文本格式非常普遍,其兼容性取决于你如何使用它们。他们有可选的模式语言,这有时是有用的,有时是一个障碍。这些格式对于数据类型有些模糊,所以你必须小心数字和二进制字符串。
|
||||
* 像Thrift、Protocol Buffers和Avro这样的二进制模式驱动格式允许使用清晰定义的前向和后向兼容性语义进行紧凑,高效的编码。这些模式可以用于静态类型语言的文档和代码生成。但是,他们有一个缺点,就是在数据可读之前需要对数据进行解码。
|
||||
|
||||
我们还讨论了数据流的几种模式,说明了数据编码重要性的不同场景:
|
||||
|
||||
|
2
ch5.md
2
ch5.md
@ -545,7 +545,7 @@ PostgreSQL和Oracle等使用这种复制方法【16】。主要缺点是日志
|
||||
但是,即使在$w + r> n$的情况下,也可能存在返回陈旧值的边缘情况。这取决于实现,但可能的情况包括:
|
||||
|
||||
* 如果使用宽松的法定人数(见“[宽松的法定人数与提示移交](#宽松的法定人数与提示移交)”),w个写入和r个读取落在完全不同的节点上,因此r节点和w之间不再保证有重叠节点【46】。
|
||||
* 如果两个写入同时发生,不清楚哪一个先发生。在这种情况下,唯一安全的解决方案是合并并发写入(请参阅“[处理写入冲突](#处理写入冲突)”)。如果根据时间戳(最后写入胜利)挑选出一个胜者,则由于时钟偏差[35],写入可能会丢失。我们将在“[检测并发写入](#检测并发写入)”继续讨论此话题。
|
||||
* 如果两个写入同时发生,不清楚哪一个先发生。在这种情况下,唯一安全的解决方案是合并并发写入(请参阅“[处理写入冲突](#处理写入冲突)”)。如果根据时间戳(最后写入胜利)挑选出一个胜者,则由于时钟偏差【35】,写入可能会丢失。我们将在“[检测并发写入](#检测并发写入)”继续讨论此话题。
|
||||
* 如果写操作与读操作同时发生,写操作可能仅反映在某些副本上。在这种情况下,不确定读取是返回旧值还是新值。
|
||||
* 如果写操作在某些副本上成功,而在其他节点上失败(例如,因为某些节点上的磁盘已满),在小于w个副本上写入成功。所以整体判定写入失败,但整体写入失败并没有在写入成功的副本上回滚。这意味着如果一个写入虽然报告失败,后续的读取仍然可能会读取这次失败写入的值【47】。
|
||||
* 如果携带新值的节点失败,需要读取其他带有旧值的副本。并且其数据从带有旧值的副本中恢复,则存储新值的副本数可能会低于w,从而打破法定人数条件。
|
||||
|
4
ch7.md
4
ch7.md
@ -226,7 +226,7 @@ SELECT COUNT(*)FROM emails WHERE recipient_id = 2 AND unread_flag = true
|
||||
|
||||
比起盲目地依赖工具,我们应该对存在的并发问题的种类,以及如何防止这些问题有深入的理解。然后就可以使用我们所掌握的工具来构建可靠和正确的应用程序。
|
||||
|
||||
在本节中,我们将看几个在实践中使用的弱(**非串行的**,即nonserializable)隔离级别,并详细讨论哪种竞争条件可能发生也可能不发生,以便你可以决定什么级别适合你的应用程序。一旦我们完成了这个工作,我们将详细讨论可串行化(请参阅“[可串行化](#可串行化)”)。我们讨论的隔离级别将是非正式的,通过示例来进行。如果你需要严格的定义和分析它们的属性,你可以在学术文献中找到它们[28,29,30]。
|
||||
在本节中,我们将看几个在实践中使用的弱(**非串行的**,即nonserializable)隔离级别,并详细讨论哪种竞争条件可能发生也可能不发生,以便你可以决定什么级别适合你的应用程序。一旦我们完成了这个工作,我们将详细讨论可串行化(请参阅“[可串行化](#可串行化)”)。我们讨论的隔离级别将是非正式的,通过示例来进行。如果你需要严格的定义和分析它们的属性,你可以在学术文献中找到它们【28,29,30】。
|
||||
|
||||
### 读已提交
|
||||
|
||||
@ -281,7 +281,7 @@ SELECT COUNT(*)FROM emails WHERE recipient_id = 2 AND unread_flag = true
|
||||
|
||||
出于这个原因,大多数数据库[^vi]使用[图7-4](img/fig7-4.png)的方式防止脏读:对于写入的每个对象,数据库都会记住旧的已提交值,和由当前持有写入锁的事务设置的新值。当事务正在进行时,任何其他读取对象的事务都会拿到旧值。 只有当新值提交后,事务才会切换到读取新值。
|
||||
|
||||
[^vi]: 在撰写本文时,唯一在读已提交隔离级别使用读锁的主流数据库是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server [23,36]。
|
||||
[^vi]: 在撰写本文时,唯一在读已提交隔离级别使用读锁的主流数据库是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server 【23,36】。
|
||||
|
||||
### 快照隔离和可重复读
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 术语表 【DRAFT】
|
||||
# 术语表
|
||||
|
||||
> 请注意,本术语表中的定义简短而简单,旨在传达核心思想,而不是术语的完整细微之处。 有关更多详细信息,请参阅正文中的参考资料。
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
>
|
||||
> —— Vonng
|
||||
|
||||
現今,尤其是在網際網路領域,大多數應用都屬於資料密集型應用。本書從底層資料結構到頂層架構設計,將資料系統設計中的精髓娓娓道來。其中的寶貴經驗無論是對架構師,DBA、還是後端工程師、甚至產品經理都會有幫助。
|
||||
現今,尤其是在網際網路領域,大多數應用都屬於資料密集型應用。本書從底層資料結構到頂層架構設計,將資料系統設計中的精髓娓娓道來。其中的寶貴經驗無論是對架構師、DBA、還是後端工程師、甚至產品經理都會有幫助。
|
||||
|
||||
這是一本理論結合實踐的書,書中很多問題,譯者在實際場景中都曾遇到過,讀來讓人擊節扼腕。如果能早點讀到這本書,該少走多少彎路啊!
|
||||
|
||||
@ -138,9 +138,9 @@
|
||||
0. 全文校訂 by [@yingang](https://github.com/yingang)
|
||||
1. [序言初翻修正](https://github.com/Vonng/ddia/commit/afb5edab55c62ed23474149f229677e3b42dfc2c) by [@seagullbird](https://github.com/Vonng/ddia/commits?author=seagullbird)
|
||||
2. [第一章語法標點校正](https://github.com/Vonng/ddia/commit/973b12cd8f8fcdf4852f1eb1649ddd9d187e3644) by [@nevertiree](https://github.com/Vonng/ddia/commits?author=nevertiree)
|
||||
3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 與[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by @[MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex)
|
||||
3. [第六章部分校正](https://github.com/Vonng/ddia/commit/d4eb0852c0ec1e93c8aacc496c80b915bb1e6d48) 與[第十章的初翻](https://github.com/Vonng/ddia/commit/9de8dbd1bfe6fbb03b3bf6c1a1aa2291aed2490e) by [@MuAlex](https://github.com/Vonng/ddia/commits?author=MuAlex)
|
||||
4. [第一部分](part-i.md)前言,[ch2](ch2.md)校正 by [@jiajiadebug](https://github.com/Vonng/ddia/commits?author=jiajiadebug)
|
||||
5. [詞彙表](glossary.md)、[後記](colophon.md)關於野豬的部分 by @[Chowss](https://github.com/Vonng/ddia/commits?author=Chowss)
|
||||
5. [詞彙表](glossary.md)、[後記](colophon.md)關於野豬的部分 by [@Chowss](https://github.com/Vonng/ddia/commits?author=Chowss)
|
||||
6. [繁體中文](https://github.com/Vonng/ddia/pulls)版本與轉換指令碼 by [@afunTW](https://github.com/afunTW)
|
||||
7. 感謝所有作出貢獻,提出意見的朋友們:
|
||||
|
||||
|
22
zh-tw/ch2.md
22
zh-tw/ch2.md
@ -226,7 +226,7 @@ CODASYL中的查詢是透過利用遍歷記錄列和跟隨訪問路徑表在資
|
||||
|
||||
#### 哪種資料模型更有助於簡化應用程式碼?
|
||||
|
||||
如果應用程式中的資料具有類似文件的結構(即,一對多關係樹,通常一次性載入整個樹),那麼使用文件模型可能是一個好主意。將類似文件的結構分解成多個表(如[圖2-1](../img/fig2-1.png)中的`positions`,`education`和`contact_info`)的關係技術可能導致繁瑣的模式和不必要的複雜的應用程式程式碼。
|
||||
如果應用程式中的資料具有類似文件的結構(即,一對多關係樹,通常一次性載入整個樹),那麼使用文件模型可能是一個好主意。將類似文件的結構分解成多個表(如[圖2-1](../img/fig2-1.png)中的`positions`、`education`和`contact_info`)的關係技術可能導致繁瑣的模式和不必要的複雜的應用程式程式碼。
|
||||
|
||||
文件模型有一定的侷限性:例如,不能直接引用文件中的巢狀的專案,而是需要說“使用者251的位置列表中的第二項”(很像層次模型中的訪問路徑)。但是,只要檔案巢狀不太深,這通常不是問題。
|
||||
|
||||
@ -286,7 +286,7 @@ UPDATE users SET first_name = substring_index(name, ' ', 1); -- MySQL
|
||||
|
||||
自2000年代中期以來,大多數關係資料庫系統(MySQL除外)都已支援XML。這包括對XML文件進行本地修改的功能,以及在XML文件中進行索引和查詢的功能。這允許應用程式使用那種與文件資料庫應當使用的非常類似的資料模型。
|
||||
|
||||
從9.3版本開始的PostgreSQL 【8】,從5.7版本開始的MySQL以及從版本10.5開始的IBM DB2 [30]也對JSON文件提供了類似的支援級別。鑑於用在Web APIs的JSON流行趨勢,其他關係資料庫很可能會跟隨他們的腳步並新增JSON支援。
|
||||
從9.3版本開始的PostgreSQL 【8】,從5.7版本開始的MySQL以及從版本10.5開始的IBM DB2【30】也對JSON文件提供了類似的支援級別。鑑於用在Web APIs的JSON流行趨勢,其他關係資料庫很可能會跟隨他們的腳步並新增JSON支援。
|
||||
|
||||
在文件資料庫中,RethinkDB在其查詢語言中支援類似關係的連線,一些MongoDB驅動程式可以自動解析資料庫引用(有效地執行客戶端連線,儘管這可能比在資料庫中執行的連線慢,需要額外的網路往返,並且最佳化更少)。
|
||||
|
||||
@ -541,18 +541,18 @@ db.observations.aggregate([
|
||||
|
||||
### 屬性圖
|
||||
|
||||
在屬性圖模型中,每個**頂點(vertex)** 包括:
|
||||
在屬性圖模型中,每個頂點(vertex)包括:
|
||||
|
||||
* 唯一的識別符號
|
||||
* 一組 **出邊(outgoing edges)**
|
||||
* 一組 **入邊(ingoing edges)**
|
||||
* 一組出邊(outgoing edges)
|
||||
* 一組入邊(ingoing edges)
|
||||
* 一組屬性(鍵值對)
|
||||
|
||||
每條 **邊(edge)** 包括:
|
||||
每條邊(edge)包括:
|
||||
|
||||
* 唯一識別符號
|
||||
* **邊的起點/尾部頂點(tail vertex)**
|
||||
* **邊的終點/頭部頂點(head vertex)**
|
||||
* 邊的起點(**尾部頂點**,即tail vertex)
|
||||
* 邊的終點(**頭部頂點**,即head vertex)
|
||||
* 描述兩個頂點之間關係型別的標籤
|
||||
* 一組屬性(鍵值對)
|
||||
|
||||
@ -640,11 +640,11 @@ RETURN person.name
|
||||
|
||||
答案是肯定的,但有些困難。在關係資料庫中,你通常會事先知道在查詢中需要哪些連線。在圖查詢中,你可能需要在找到待查詢的頂點之前,遍歷可變數量的邊。也就是說,連線的數量事先並不確定。
|
||||
|
||||
在我們的例子中,這發生在Cypher查詢中的`() -[:WITHIN*0..]-> ()`規則中。一個人的`LIVES_IN`邊可以指向任何型別的位置:街道、城市、地區、地區、國家等。城市可以在一個地區,在一個州內的一個地區,在一個國家內的一個州等等。`LIVES_IN`邊可以直接指向正在查詢的位置,或者一個在位置層次結構中隔了數層的位置。
|
||||
在我們的例子中,這發生在Cypher查詢中的`() -[:WITHIN*0..]-> ()`規則中。一個人的`LIVES_IN`邊可以指向任何型別的位置:街道、城市、地區、地區、國家等。一個城市可以在(WITHIN)一個地區內,一個地區可以在(WITHIN)在一個州內,一個州可以在(WITHIN)一個國家內,等等。`LIVES_IN`邊可以直接指向正在查詢的位置,或者一個在位置層次結構中隔了數層的位置。
|
||||
|
||||
在Cypher中,用`WITHIN * 0`非常簡潔地表述了上述事實:“沿著`WITHIN`邊,零次或多次”。它很像正則表示式中的`*`運算子。
|
||||
在Cypher中,用`WITHIN*0..`非常簡潔地表述了上述事實:“沿著`WITHIN`邊,零次或多次”。它很像正則表示式中的`*`運算子。
|
||||
|
||||
自SQL:1999,查詢可變長度遍歷路徑的思想可以使用稱為**遞迴公用表表達式**(`WITH RECURSIVE`語法)的東西來表示。[例2-5]()顯示了同樣的查詢 - 查詢從美國移民到歐洲的人的姓名 - 在SQL使用這種技術(PostgreSQL,IBM DB2,Oracle和SQL Server均支援)來表述。但是,與Cypher相比,其語法非常笨拙。
|
||||
自SQL:1999,查詢可變長度遍歷路徑的思想可以使用稱為**遞迴公用表表達式**(`WITH RECURSIVE`語法)的東西來表示。[例2-5]()顯示了同樣的查詢 - 查詢從美國移民到歐洲的人的姓名 - 在SQL使用這種技術(PostgreSQL、IBM DB2、Oracle和SQL Server均支援)來表述。但是,與Cypher相比,其語法非常笨拙。
|
||||
|
||||
**例2-5 與示例2-4同樣的查詢,在SQL中使用遞迴公用表表達式表示**
|
||||
|
||||
|
14
zh-tw/ch4.md
14
zh-tw/ch4.md
@ -70,7 +70,7 @@
|
||||
|
||||
因此,除非臨時使用,採用語言內建編碼通常是一個壞主意。
|
||||
|
||||
### JSON,XML和二進位制變體
|
||||
### JSON、XML和二進位制變體
|
||||
|
||||
當我們談到可以被多種程式語言讀寫的標準編碼時,JSON和XML是最顯眼的角逐者。它們廣為人知,廣受支援,也“廣受憎惡”。 XML經常收到批評:過於冗長與且過份複雜【9】。 JSON的流行則主要源於(透過成為JavaScript的一個子集)Web瀏覽器的內建支援,以及相對於XML的簡單性。 CSV是另一種流行的與語言無關的格式,儘管其功能相對較弱。
|
||||
|
||||
@ -148,7 +148,7 @@ Thrift和Protocol Buffers每一個都帶有一個程式碼生成工具,它採
|
||||
|
||||
**圖4-2 使用Thrift二進位制協議編碼的記錄**
|
||||
|
||||
[^iii]: 實際上,Thrift有三種二進位制協議:BinaryProtocol、CompactProtocol和DenseProtocol,儘管DenseProtocol只支援C ++實現,所以不算作跨語言[18]。 除此之外,它還有兩種不同的基於JSON的編碼格式【19】。 真逗!
|
||||
[^iii]: 實際上,Thrift有三種二進位制協議:BinaryProtocol、CompactProtocol和DenseProtocol,儘管DenseProtocol只支援C ++實現,所以不算作跨語言【18】。 除此之外,它還有兩種不同的基於JSON的編碼格式【19】。 真逗!
|
||||
|
||||
與[圖4-1](Img/fig4-1.png)類似,每個欄位都有一個型別註釋(用於指示它是一個字串,整數,列表等),還可以根據需要指定長度(字串的長度,列表中的專案數) 。出現在資料中的字串`(“Martin”, “daydreaming”, “hacking”)`也被編碼為ASCII(或者說,UTF-8),與之前類似。
|
||||
|
||||
@ -395,7 +395,7 @@ Web瀏覽器不是唯一的客戶端型別。例如,在移動裝置或桌面
|
||||
|
||||
[^vi]: 即使在每個陣營內也有很多爭論。 例如,**HATEOAS(超媒體作為應用程式狀態的引擎)** 就經常引發討論【35】。
|
||||
|
||||
REST不是一個協議,而是一個基於HTTP原則的設計哲學【34,35】。它強調簡單的資料格式,使用URL來標識資源,並使用HTTP功能進行快取控制,身份驗證和內容型別協商。與SOAP相比,REST已經越來越受歡迎,至少在跨組織服務整合的背景下【36】,並經常與微服務相關[31]。根據REST原則設計的API稱為RESTful。
|
||||
REST不是一個協議,而是一個基於HTTP原則的設計哲學【34,35】。它強調簡單的資料格式,使用URL來標識資源,並使用HTTP功能進行快取控制,身份驗證和內容型別協商。與SOAP相比,REST已經越來越受歡迎,至少在跨組織服務整合的背景下【36】,並經常與微服務相關【31】。根據REST原則設計的API稱為RESTful。
|
||||
|
||||
相比之下,SOAP是用於製作網路API請求的基於XML的協議[^vii]。雖然它最常用於HTTP,但其目的是獨立於HTTP,並避免使用大多數HTTP功能。相反,它帶有龐大而複雜的多種相關標準(Web服務框架,稱為`WS-*`),它們增加了各種功能【37】。
|
||||
|
||||
@ -421,7 +421,7 @@ Web服務僅僅是透過網路進行API請求的一系列技術的最新版本
|
||||
* 每次呼叫本地功能時,通常需要大致相同的時間來執行。網路請求比函式呼叫要慢得多,而且其延遲也是非常可變的:好的時候它可能會在不到一毫秒的時間內完成,但是當網路擁塞或者遠端服務超載時,可能需要幾秒鐘的時間完成一樣的東西。
|
||||
* 呼叫本地函式時,可以高效地將引用(指標)傳遞給本地記憶體中的物件。當你發出一個網路請求時,所有這些引數都需要被編碼成可以透過網路傳送的一系列位元組。如果引數是像數字或字串這樣的基本型別倒是沒關係,但是對於較大的物件很快就會變成問題。
|
||||
|
||||
- 客戶端和服務可以用不同的程式語言實現,所以RPC框架必須將資料型別從一種語言翻譯成另一種語言。這可能會捅出大簍子,因為不是所有的語言都具有相同的型別 —— 例如回想一下JavaScript的數字大於$2^{53}$的問題(請參閱“[JSON,XML和二進位制變體](#JSON,XML和二進位制變體)”)。用單一語言編寫的單個程序中不存在此問題。
|
||||
- 客戶端和服務可以用不同的程式語言實現,所以RPC框架必須將資料型別從一種語言翻譯成另一種語言。這可能會捅出大簍子,因為不是所有的語言都具有相同的型別 —— 例如回想一下JavaScript的數字大於$2^{53}$的問題(請參閱“[JSON、XML和二進位制變體](#JSON、XML和二進位制變體)”)。用單一語言編寫的單個程序中不存在此問題。
|
||||
|
||||
所有這些因素意味著嘗試使遠端服務看起來像程式語言中的本地物件一樣毫無意義,因為這是一個根本不同的事情。 REST的部分吸引力在於,它並不試圖隱藏它是一個網路協議的事實(儘管這似乎並沒有阻止人們在REST之上構建RPC庫)。
|
||||
|
||||
@ -469,7 +469,7 @@ RPC方案的前後向相容性屬性從它使用的編碼方式中繼承:
|
||||
|
||||
#### 訊息代理
|
||||
|
||||
過去,**訊息代理(Message Broker)** 主要是TIBCO,IBM WebSphere和webMethods等公司的商業軟體的秀場。最近像RabbitMQ,ActiveMQ,HornetQ,NATS和Apache Kafka這樣的開源實現已經流行起來。我們將在[第十一章](ch11.md)中對它們進行更詳細的比較。
|
||||
過去,**訊息代理(Message Broker)** 主要是TIBCO、IBM WebSphere和webMethods等公司的商業軟體的秀場。最近像RabbitMQ、ActiveMQ、HornetQ、NATS和Apache Kafka這樣的開源實現已經流行起來。我們將在[第十一章](ch11.md)中對它們進行更詳細的比較。
|
||||
|
||||
詳細的交付語義因實現和配置而異,但通常情況下,訊息代理的使用方式如下:一個程序將訊息傳送到指定的佇列或主題,代理確保將訊息傳遞給那個佇列或主題的一個或多個消費者或訂閱者。在同一主題上可以有許多生產者和許多消費者。
|
||||
|
||||
@ -507,8 +507,8 @@ Actor模型是單個程序中併發的程式設計模型。邏輯被封裝在act
|
||||
我們討論了幾種資料編碼格式及其相容性屬性:
|
||||
|
||||
* 程式語言特定的編碼僅限於單一程式語言,並且往往無法提供前向和後向相容性。
|
||||
* JSON,XML和CSV等文字格式非常普遍,其相容性取決於你如何使用它們。他們有可選的模式語言,這有時是有用的,有時是一個障礙。這些格式對於資料型別有些模糊,所以你必須小心數字和二進位制字串。
|
||||
* 像Thrift,Protocol Buffers和Avro這樣的二進位制模式驅動格式允許使用清晰定義的前向和後向相容性語義進行緊湊,高效的編碼。這些模式可以用於靜態型別語言的文件和程式碼生成。但是,他們有一個缺點,就是在資料可讀之前需要對資料進行解碼。
|
||||
* JSON、XML和CSV等文字格式非常普遍,其相容性取決於你如何使用它們。他們有可選的模式語言,這有時是有用的,有時是一個障礙。這些格式對於資料型別有些模糊,所以你必須小心數字和二進位制字串。
|
||||
* 像Thrift、Protocol Buffers和Avro這樣的二進位制模式驅動格式允許使用清晰定義的前向和後向相容性語義進行緊湊,高效的編碼。這些模式可以用於靜態型別語言的文件和程式碼生成。但是,他們有一個缺點,就是在資料可讀之前需要對資料進行解碼。
|
||||
|
||||
我們還討論了資料流的幾種模式,說明了資料編碼重要性的不同場景:
|
||||
|
||||
|
@ -545,7 +545,7 @@ PostgreSQL和Oracle等使用這種複製方法【16】。主要缺點是日誌
|
||||
但是,即使在$w + r> n$的情況下,也可能存在返回陳舊值的邊緣情況。這取決於實現,但可能的情況包括:
|
||||
|
||||
* 如果使用寬鬆的法定人數(見“[寬鬆的法定人數與提示移交](#寬鬆的法定人數與提示移交)”),w個寫入和r個讀取落在完全不同的節點上,因此r節點和w之間不再保證有重疊節點【46】。
|
||||
* 如果兩個寫入同時發生,不清楚哪一個先發生。在這種情況下,唯一安全的解決方案是合併併發寫入(請參閱“[處理寫入衝突](#處理寫入衝突)”)。如果根據時間戳(最後寫入勝利)挑選出一個勝者,則由於時鐘偏差[35],寫入可能會丟失。我們將在“[檢測併發寫入](#檢測併發寫入)”繼續討論此話題。
|
||||
* 如果兩個寫入同時發生,不清楚哪一個先發生。在這種情況下,唯一安全的解決方案是合併併發寫入(請參閱“[處理寫入衝突](#處理寫入衝突)”)。如果根據時間戳(最後寫入勝利)挑選出一個勝者,則由於時鐘偏差【35】,寫入可能會丟失。我們將在“[檢測併發寫入](#檢測併發寫入)”繼續討論此話題。
|
||||
* 如果寫操作與讀操作同時發生,寫操作可能僅反映在某些副本上。在這種情況下,不確定讀取是返回舊值還是新值。
|
||||
* 如果寫操作在某些副本上成功,而在其他節點上失敗(例如,因為某些節點上的磁碟已滿),在小於w個副本上寫入成功。所以整體判定寫入失敗,但整體寫入失敗並沒有在寫入成功的副本上回滾。這意味著如果一個寫入雖然報告失敗,後續的讀取仍然可能會讀取這次失敗寫入的值【47】。
|
||||
* 如果攜帶新值的節點失敗,需要讀取其他帶有舊值的副本。並且其資料從帶有舊值的副本中恢復,則儲存新值的副本數可能會低於w,從而打破法定人數條件。
|
||||
|
@ -226,7 +226,7 @@ SELECT COUNT(*)FROM emails WHERE recipient_id = 2 AND unread_flag = true
|
||||
|
||||
比起盲目地依賴工具,我們應該對存在的併發問題的種類,以及如何防止這些問題有深入的理解。然後就可以使用我們所掌握的工具來構建可靠和正確的應用程式。
|
||||
|
||||
在本節中,我們將看幾個在實踐中使用的弱(**非序列的**,即nonserializable)隔離級別,並詳細討論哪種競爭條件可能發生也可能不發生,以便你可以決定什麼級別適合你的應用程式。一旦我們完成了這個工作,我們將詳細討論可序列化(請參閱“[可序列化](#可序列化)”)。我們討論的隔離級別將是非正式的,透過示例來進行。如果你需要嚴格的定義和分析它們的屬性,你可以在學術文獻中找到它們[28,29,30]。
|
||||
在本節中,我們將看幾個在實踐中使用的弱(**非序列的**,即nonserializable)隔離級別,並詳細討論哪種競爭條件可能發生也可能不發生,以便你可以決定什麼級別適合你的應用程式。一旦我們完成了這個工作,我們將詳細討論可序列化(請參閱“[可序列化](#可序列化)”)。我們討論的隔離級別將是非正式的,透過示例來進行。如果你需要嚴格的定義和分析它們的屬性,你可以在學術文獻中找到它們【28,29,30】。
|
||||
|
||||
### 讀已提交
|
||||
|
||||
@ -281,7 +281,7 @@ SELECT COUNT(*)FROM emails WHERE recipient_id = 2 AND unread_flag = true
|
||||
|
||||
出於這個原因,大多數資料庫[^vi]使用[圖7-4](../img/fig7-4.png)的方式防止髒讀:對於寫入的每個物件,資料庫都會記住舊的已提交值,和由當前持有寫入鎖的事務設定的新值。當事務正在進行時,任何其他讀取物件的事務都會拿到舊值。 只有當新值提交後,事務才會切換到讀取新值。
|
||||
|
||||
[^vi]: 在撰寫本文時,唯一在讀已提交隔離級別使用讀鎖的主流資料庫是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server [23,36]。
|
||||
[^vi]: 在撰寫本文時,唯一在讀已提交隔離級別使用讀鎖的主流資料庫是使用`read_committed_snapshot = off`配置的IBM DB2和Microsoft SQL Server 【23,36】。
|
||||
|
||||
### 快照隔離和可重複讀
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# 術語表 【DRAFT】
|
||||
# 術語表
|
||||
|
||||
> 請注意,本術語表中的定義簡短而簡單,旨在傳達核心思想,而不是術語的完整細微之處。 有關更多詳細資訊,請參閱正文中的參考資料。
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user