fix parentheses

This commit is contained in:
Gang Yin 2023-03-13 09:19:49 +08:00
parent 2e5d96f919
commit bc42b0550c
8 changed files with 11 additions and 11 deletions

2
ch4.md
View File

@ -78,7 +78,7 @@ JSONXML 和 CSV 属于文本格式,因此具有人类可读性(尽管它
* **数字numbers** 编码有很多模糊之处。在 XML 和 CSV 中,无法区分数字和碰巧由数字组成的字符串(除了引用外部模式)。 JSON 虽然区分字符串与数字,但并不区分整数和浮点数,并且不能指定精度。
这在处理大数字时是个问题。例如大于 $2^{53}$ 的整数无法使用 IEEE 754 双精度浮点数精确表示,因此在使用浮点数(例如 JavaScript的语言进行分析时这些数字会变得不准确。 Twitter 有一个关于大于 $2^{53}$ 的数字的例子,它使用 64 位整数来标识每条推文。 Twitter API 返回的 JSON 包含了两个推特 ID一个是 JSON 数字,另一个是十进制字符串,以解决 JavaScript 程序中无法正确解析数字的问题【10】。
* JSON 和 XML 对 Unicode 字符串(即人类可读的文本)有很好的支持,但是它们不支持二进制数据(即不带 **字符编码 (character encoding)** 的字节序列)。二进制串是很有用的功能,人们通过使用 Base64 将二进制数据编码为文本来绕过此限制。其特有的模式标识着这个值应当被解释为 Base64 编码的二进制数据。这种方案虽然管用,但比较 Hacky并且会增加三分之一的数据大小。
* JSON 和 XML 对 Unicode 字符串(即人类可读的文本)有很好的支持,但是它们不支持二进制数据(即不带 **字符编码character encoding** 的字节序列)。二进制串是很有用的功能,人们通过使用 Base64 将二进制数据编码为文本来绕过此限制。其特有的模式标识着这个值应当被解释为 Base64 编码的二进制数据。这种方案虽然管用,但比较 Hacky并且会增加三分之一的数据大小。
* XML 【11】和 JSON 【12】都有可选的模式支持。这些模式语言相当强大所以学习和实现起来都相当复杂。 XML 模式的使用相当普遍,但许多基于 JSON 的工具才不会去折腾模式。对数据的正确解读(例如区分数值与二进制串)取决于模式中的信息,因此不使用 XML/JSON 模式的应用程序可能需要对相应的编码 / 解码逻辑进行硬编码。
* CSV 没有任何模式,因此每行和每列的含义完全由应用程序自行定义。如果应用程序变更添加了新的行或列,那么这种变更必须通过手工处理。 CSV 也是一个相当模糊的格式如果一个值包含逗号或换行符会发生什么。尽管其转义规则已经被正式指定【13】但并不是所有的解析器都正确的实现了标准。

2
ch5.md
View File

@ -114,7 +114,7 @@
* 如果数据库需要和其他外部存储相协调,那么丢弃写入内容是极其危险的操作。例如在 GitHub 【13】的一场事故中一个过时的 MySQL 从库被提升为主库。数据库使用自增 ID 作为主键,因为新主库的计数器落后于老主库的计数器,所以新主库重新分配了一些已经被老主库分配掉的 ID 作为主键。这些主键也在 Redis 中使用,主键重用使得 MySQL 和 Redis 中的数据产生不一致,最后导致一些私有数据泄漏到错误的用户手中。
* 发生某些故障时(见 [第八章](ch8.md))可能会出现两个节点都以为自己是主库的情况。这种情况称为 **脑裂 (split brain)**,非常危险:如果两个主库都可以接受写操作,却没有冲突解决机制(请参阅 “[多主复制](#多主复制)”),那么数据就可能丢失或损坏。一些系统采取了安全防范措施:当检测到两个主库节点同时存在时会关闭其中一个节点 [^ii]但设计粗糙的机制可能最后会导致两个节点都被关闭【14】。
* 发生某些故障时(见 [第八章](ch8.md))可能会出现两个节点都以为自己是主库的情况。这种情况称为 **脑裂split brain**,非常危险:如果两个主库都可以接受写操作,却没有冲突解决机制(请参阅 “[多主复制](#多主复制)”),那么数据就可能丢失或损坏。一些系统采取了安全防范措施:当检测到两个主库节点同时存在时会关闭其中一个节点 [^ii]但设计粗糙的机制可能最后会导致两个节点都被关闭【14】。
[^ii]: 这种机制称为 **屏障fencing**,或者更充满感情的术语是:**爆彼之头Shoot The Other Node In The Head, STONITH**。我们将在 “[领导者和锁](ch8.md#领导者和锁)” 中对屏障进行详细讨论。

2
ch6.md
View File

@ -17,7 +17,7 @@
> #### 术语澄清
>
> 上文中的 **分区 (partition)**,在 MongoDBElasticsearch 和 Solr Cloud 中被称为 **分片 (shard)**,在 HBase 中称之为 **区域 (Region)**Bigtable 中则是 **表块tablet**Cassandra 和 Riak 中是 **虚节点vnode)**Couchbase 中叫做 **虚桶 (vBucket)**。但是 **分区 (partitioning)** 是最约定俗成的叫法。
> 上文中的 **分区partition**,在 MongoDBElasticsearch 和 Solr Cloud 中被称为 **分片shard**,在 HBase 中称之为 **区域Region**Bigtable 中则是 **表块tablet**Cassandra 和 Riak 中是 **虚节点vnode**Couchbase 中叫做 **虚桶vBucket**。但是 **分区partitioning** 是最约定俗成的叫法。
>
通常情况下,每条数据(每条记录,每行或每个文档)属于且仅属于一个分区。有很多方法可以实现这一点,本章将进行深入讨论。实际上,每个分区都是自己的小型数据库,尽管数据库可能支持同时进行多个分区的操作。

View File

@ -65,7 +65,7 @@
**图 II-1 一个数据库切分为两个分区,每个分区都有两个副本**
理解了这些概念,就可以开始讨论在分布式系统中需要做出的困难抉择。[第七章](ch7.md) 将讨论 **事务 (Transaction)**,这对于了解数据系统中可能出现的各种问题,以及我们可以做些什么很有帮助。[第八章](ch8.md) 和 [第九章](ch9.md) 将讨论分布式系统的根本局限性。
理解了这些概念,就可以开始讨论在分布式系统中需要做出的困难抉择。[第七章](ch7.md) 将讨论 **事务Transaction**,这对于了解数据系统中可能出现的各种问题,以及我们可以做些什么很有帮助。[第八章](ch8.md) 和 [第九章](ch9.md) 将讨论分布式系统的根本局限性。
在本书的 [第三部分](part-iii.md) 中,将讨论如何将多个(可能是分布式的)数据存储集成为一个更大的系统,以满足复杂的应用需求。 但首先,我们来聊聊分布式的数据。

View File

@ -78,7 +78,7 @@ JSONXML 和 CSV 屬於文字格式,因此具有人類可讀性(儘管它
* **數字numbers** 編碼有很多模糊之處。在 XML 和 CSV 中,無法區分數字和碰巧由數字組成的字串(除了引用外部模式)。 JSON 雖然區分字串與數字,但並不區分整數和浮點數,並且不能指定精度。
這在處理大數字時是個問題。例如大於 $2^{53}$ 的整數無法使用 IEEE 754 雙精度浮點數精確表示,因此在使用浮點數(例如 JavaScript的語言進行分析時這些數字會變得不準確。 Twitter 有一個關於大於 $2^{53}$ 的數字的例子,它使用 64 位整數來標識每條推文。 Twitter API 返回的 JSON 包含了兩個推特 ID一個是 JSON 數字,另一個是十進位制字串,以解決 JavaScript 程式中無法正確解析數字的問題【10】。
* JSON 和 XML 對 Unicode 字串(即人類可讀的文字)有很好的支援,但是它們不支援二進位制資料(即不帶 **字元編碼 (character encoding)** 的位元組序列)。二進位制串是很有用的功能,人們透過使用 Base64 將二進位制資料編碼為文字來繞過此限制。其特有的模式標識著這個值應當被解釋為 Base64 編碼的二進位制資料。這種方案雖然管用,但比較 Hacky並且會增加三分之一的資料大小。
* JSON 和 XML 對 Unicode 字串(即人類可讀的文字)有很好的支援,但是它們不支援二進位制資料(即不帶 **字元編碼character encoding** 的位元組序列)。二進位制串是很有用的功能,人們透過使用 Base64 將二進位制資料編碼為文字來繞過此限制。其特有的模式標識著這個值應當被解釋為 Base64 編碼的二進位制資料。這種方案雖然管用,但比較 Hacky並且會增加三分之一的資料大小。
* XML 【11】和 JSON 【12】都有可選的模式支援。這些模式語言相當強大所以學習和實現起來都相當複雜。 XML 模式的使用相當普遍,但許多基於 JSON 的工具才不會去折騰模式。對資料的正確解讀(例如區分數值與二進位制串)取決於模式中的資訊,因此不使用 XML/JSON 模式的應用程式可能需要對相應的編碼 / 解碼邏輯進行硬編碼。
* CSV 沒有任何模式,因此每行和每列的含義完全由應用程式自行定義。如果應用程式變更添加了新的行或列,那麼這種變更必須透過手工處理。 CSV 也是一個相當模糊的格式如果一個值包含逗號或換行符會發生什麼。儘管其轉義規則已經被正式指定【13】但並不是所有的解析器都正確的實現了標準。
@ -177,7 +177,7 @@ Thrift CompactProtocol 編碼在語義上等同於 BinaryProtocol但是如 [
向後相容性呢?只要每個欄位都有一個唯一的標籤號碼,新的程式碼總是可以讀取舊的資料,因為標籤號碼仍然具有相同的含義。唯一的細節是,如果你新增一個新的欄位,你不能設定為必需。如果你要新增一個欄位並將其設定為必需,那麼如果新程式碼讀取舊程式碼寫入的資料,則該檢查將失敗,因為舊程式碼不會寫入你新增的新欄位。因此,為了保持向後相容性,在模式的初始部署之後 **新增的每個欄位必須是可選的或具有預設值**
刪除一個欄位就像新增一個欄位,只是這回要考慮的是向前相容性。這意味著你只能刪除一個可選的欄位(必需欄位永遠不能刪除),而且你不能再次使用相同的標籤號碼(因為你可能仍然有資料寫在包含舊標籤號碼的地方,而該欄位必須被新程式碼忽略)。
刪除一個欄位就像新增一個欄位,只是這回要考慮的是向前相容性。這意味著你只能刪除可選的欄位(必需欄位永遠不能刪除),而且你不能再次使用相同的標籤號碼(因為你可能仍然有資料寫在包含舊標籤號碼的地方,而該欄位必須被新程式碼忽略)。
#### 資料型別和模式演變
@ -289,7 +289,7 @@ Avro 的關鍵思想是 Writer 模式和 Reader 模式不必是相同的 - 他
#### 程式碼生成和動態型別的語言
Thrift 和 Protobuf 依賴於程式碼生成:在定義了模式之後,可以使用你選擇的程式語言生成實現此模式的程式碼。這在 Java、C++ 或 C# 等靜態型別語言中很有用,因為它允許將高效的記憶體中結構用於解碼的資料,並且在編寫訪問資料結構的程式時允許在 IDE 中進行型別檢查和自動補全。
Thrift 和 Protobuf 依賴於程式碼生成:在定義了模式之後,可以使用你選擇的程式語言生成實現此模式的程式碼。這在 Java、C++ 或 C# 等靜態型別語言中很有用,因為它允許將高效的記憶體中的資料結構用於解碼的資料,並且在編寫訪問資料結構的程式時允許在 IDE 中進行型別檢查和自動補全。
在動態型別程式語言(如 JavaScript、Ruby 或 Python生成程式碼沒有太多意義因為沒有編譯時型別檢查器來滿足。程式碼生成在這些語言中經常被忽視因為它們避免了顯式的編譯步驟。而且對於動態生成的模式例如從資料庫表生成的 Avro 模式),程式碼生成對獲取資料是一個不必要的障礙。
@ -370,7 +370,7 @@ Avro 為靜態型別程式語言提供了可選的程式碼生成功能,但是
### 服務中的資料流REST與RPC
當你需要透過網路進行通訊的程序時,安排該通訊的方式有幾種。最常見的安排是有兩個角色:客戶端和伺服器。伺服器透過網路公開 API並且客戶端可以連線到伺服器以向該 API 發出請求。伺服器公開的 API 被稱為服務。
當你需要透過網路進行程序間的通訊時,安排該通訊的方式有幾種。最常見的安排是有兩個角色:客戶端和伺服器。伺服器透過網路公開 API並且客戶端可以連線到伺服器以向該 API 發出請求。伺服器公開的 API 被稱為服務。
Web 以這種方式工作客戶Web 瀏覽器)向 Web 伺服器發出請求,透過 GET 請求下載 HTML、CSS、JavaScript、影象等並透過 POST 請求提交資料到伺服器。 API 包含一組標準的協議和資料格式HTTP、URL、SSL/TLS、HTML 等)。由於網路瀏覽器、網路伺服器和網站作者大多同意這些標準,你可以使用任何網路瀏覽器訪問任何網站(至少在理論上!)。

View File

@ -114,7 +114,7 @@
* 如果資料庫需要和其他外部儲存相協調,那麼丟棄寫入內容是極其危險的操作。例如在 GitHub 【13】的一場事故中一個過時的 MySQL 從庫被提升為主庫。資料庫使用自增 ID 作為主鍵,因為新主庫的計數器落後於老主庫的計數器,所以新主庫重新分配了一些已經被老主庫分配掉的 ID 作為主鍵。這些主鍵也在 Redis 中使用,主鍵重用使得 MySQL 和 Redis 中的資料產生不一致,最後導致一些私有資料洩漏到錯誤的使用者手中。
* 發生某些故障時(見 [第八章](ch8.md))可能會出現兩個節點都以為自己是主庫的情況。這種情況稱為 **腦裂 (split brain)**,非常危險:如果兩個主庫都可以接受寫操作,卻沒有衝突解決機制(請參閱 “[多主複製](#多主複製)”),那麼資料就可能丟失或損壞。一些系統採取了安全防範措施:當檢測到兩個主庫節點同時存在時會關閉其中一個節點 [^ii]但設計粗糙的機制可能最後會導致兩個節點都被關閉【14】。
* 發生某些故障時(見 [第八章](ch8.md))可能會出現兩個節點都以為自己是主庫的情況。這種情況稱為 **腦裂split brain**,非常危險:如果兩個主庫都可以接受寫操作,卻沒有衝突解決機制(請參閱 “[多主複製](#多主複製)”),那麼資料就可能丟失或損壞。一些系統採取了安全防範措施:當檢測到兩個主庫節點同時存在時會關閉其中一個節點 [^ii]但設計粗糙的機制可能最後會導致兩個節點都被關閉【14】。
[^ii]: 這種機制稱為 **屏障fencing**,或者更充滿感情的術語是:**爆彼之頭Shoot The Other Node In The Head, STONITH**。我們將在 “[領導者和鎖](ch8.md#領導者和鎖)” 中對屏障進行詳細討論。

View File

@ -17,7 +17,7 @@
> #### 術語澄清
>
> 上文中的 **分割槽 (partition)**,在 MongoDBElasticsearch 和 Solr Cloud 中被稱為 **分片 (shard)**,在 HBase 中稱之為 **區域 (Region)**Bigtable 中則是 **表塊tablet**Cassandra 和 Riak 中是 **虛節點vnode)**Couchbase 中叫做 **虛桶 (vBucket)**。但是 **分割槽 (partitioning)** 是最約定俗成的叫法。
> 上文中的 **分割槽partition**,在 MongoDBElasticsearch 和 Solr Cloud 中被稱為 **分片shard**,在 HBase 中稱之為 **區域Region**Bigtable 中則是 **表塊tablet**Cassandra 和 Riak 中是 **虛節點vnode**Couchbase 中叫做 **虛桶vBucket**。但是 **分割槽partitioning** 是最約定俗成的叫法。
>
通常情況下,每條資料(每條記錄,每行或每個文件)屬於且僅屬於一個分割槽。有很多方法可以實現這一點,本章將進行深入討論。實際上,每個分割槽都是自己的小型資料庫,儘管資料庫可能支援同時進行多個分割槽的操作。

View File

@ -65,7 +65,7 @@
**圖 II-1 一個數據庫切分為兩個分割槽,每個分割槽都有兩個副本**
理解了這些概念,就可以開始討論在分散式系統中需要做出的困難抉擇。[第七章](ch7.md) 將討論 **事務 (Transaction)**,這對於瞭解資料系統中可能出現的各種問題,以及我們可以做些什麼很有幫助。[第八章](ch8.md) 和 [第九章](ch9.md) 將討論分散式系統的根本侷限性。
理解了這些概念,就可以開始討論在分散式系統中需要做出的困難抉擇。[第七章](ch7.md) 將討論 **事務Transaction**,這對於瞭解資料系統中可能出現的各種問題,以及我們可以做些什麼很有幫助。[第八章](ch8.md) 和 [第九章](ch9.md) 將討論分散式系統的根本侷限性。
在本書的 [第三部分](part-iii.md) 中,將討論如何將多個(可能是分散式的)資料儲存整合為一個更大的系統,以滿足複雜的應用需求。 但首先,我們來聊聊分散式的資料。