真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

DDIA 學習筆記

第一章 可靠性、可擴展性、可維護性

? 可靠性: 系統(tǒng)在困境(adversity)(硬件故障、軟件故障、人為錯誤)中仍可正常工作(正確完成功能,并能達到期望的性能水準。

我們提供的服務有:成都做網站、成都網站建設、成都外貿網站建設、微信公眾號開發(fā)、網站優(yōu)化、網站認證、永城ssl等。為超過千家企事業(yè)單位解決了網站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的永城網站制作公司

? 可靠性(Reliability) 意味著即使發(fā)生故障,系統(tǒng)也能正常工作。故障可能發(fā)生在硬件(通常是隨機的和不相關的),軟件(通常是系統(tǒng)性的Bug,很難處理),和人類(不可避免地時不時出錯)。 容錯技術 可以對終端用戶隱藏某些類型的故障。

? 可擴展性: 有合理的辦法應對系統(tǒng)的增長(數(shù)據(jù)量、流量、復雜性)

? 可擴展性(Scalability) 意味著即使在負載增加的情況下也有保持性能的策略。為了討論可擴展性,我們首先需要定量描述負載和性能的方法。我們簡要了解了推特主頁時間線的例子,介紹描述負載的方法,并將響應時間百分位點作為衡量性能的一種方式。在可擴展的系統(tǒng)中可以添加 處理容量(processing capacity) 以在高負載下保持可靠。

? 可維護性:許多不同的人(工程師、運維)在不同的生命周期,都能高效地在系統(tǒng)上工作(使系統(tǒng)保持現(xiàn)有行為,并適應新的應用場景)

? 可維護性(Maintainability) 有許多方面,但實質上是關于工程師和運維團隊的生活質量的。良好的抽象可以幫助降低復雜度,并使系統(tǒng)易于修改和適應新的應用場景。良好的可操作性意味著對系統(tǒng)的健康狀態(tài)具有良好的可見性,并擁有有效的管理手段。

第二章 數(shù)據(jù)模型與查詢語言

? 文檔數(shù)據(jù)庫的應用場景是:數(shù)據(jù)通常是自我包含的,而且文檔之間的關系非常稀少

? 圖形數(shù)據(jù)庫用于相反的場景:任意事物都可能與任何事物相關聯(lián)

第三章 存儲與檢索

? 在高層次上,我們看到存儲引擎分為兩大類:優(yōu)化 事務處理(OLTP)在線分析(OLAP) 。這些用例的訪問模式之間有很大的區(qū)別:

  • OLTP系統(tǒng)通常面向用戶,這意味著系統(tǒng)可能會收到大量的請求。為了處理負載,應用程序通常只訪問每個查詢中的少部分記錄。應用程序使用某種鍵來請求記錄,存儲引擎使用索引來查找所請求的鍵的數(shù)據(jù)。磁盤尋道時間往往是這里的瓶頸。

  • 數(shù)據(jù)倉庫和類似的分析系統(tǒng)會低調一些,因為它們主要由業(yè)務分析人員使用,而不是由最終用戶使用。它們的查詢量要比OLTP系統(tǒng)少得多,但通常每個查詢開銷高昂,需要在短時間內掃描數(shù)百萬條記錄。磁盤帶寬(而不是查找時間)往往是瓶頸,列式存儲是這種工作負載越來越流行的解決方案。

    第四章 編碼與演化

? Json XML 編碼 --> 二進制編碼的發(fā)展

? 二進制編碼技術:Apache Thrift / Protocol Buffers(protobuf)/

? 服務中的數(shù)據(jù)流:REST & RPC

? REST不是一個協(xié)議,而是一個基于HTTP原則的設計哲學。它強調簡單的數(shù)據(jù)格式,使用URL來標識資源,并使用HTTP功能進行緩存控制,身份驗證和內容類型協(xié)商。與SOAP相比,REST已經越來越受歡迎,至少在跨組織服務集成的背景下,并經常與微服務相關。根據(jù)REST原則設計的API稱為restful, 通常涉及較少的代碼生成和自動化工具。

? RPC調用和本地函數(shù)調用的不同:

  • 本地函數(shù)調用是可預測的,并且成功或失敗,這僅取決于受您控制的參數(shù)。網絡請求是不可預知的:由于網絡問題,請求或響應可能會丟失,或者遠程計算機可能很慢或不可用,這些問題完全不在您的控制范圍之內。網絡問題是常見的,所以你必須預測他們,例如通過重試失敗的請求。
  • 本地函數(shù)調用要么返回結果,要么拋出異常,或者永遠不返回(因為進入無限循環(huán)或進程崩潰)。網絡請求有另一個可能的結果:由于超時,它可能會返回沒有結果。在這種情況下,你根本不知道發(fā)生了什么:如果你沒有得到來自遠程服務的響應,你無法知道請求是否通過。
  • 如果您重試失敗的網絡請求,可能會發(fā)生請求實際上正在通過,只有響應丟失。在這種情況下,重試將導致該操作被執(zhí)行多次,除非您在協(xié)議中引入除重( 冪等(idempotence))機制。本地函數(shù)調用沒有這個問題。
  • 每次調用本地功能時,通常需要大致相同的時間來執(zhí)行。網絡請求比函數(shù)調用要慢得多,而且其延遲也是非??勺兊模涸诓坏揭缓撩氲臅r間內它可能會完成,但是當網絡擁塞或者遠程服務超載時,可能需要幾秒鐘的時間完全一樣的東西。
  • 調用本地函數(shù)時,可以高效地將引用(指針)傳遞給本地內存中的對象。當你發(fā)出一個網絡請求時,所有這些參數(shù)都需要被編碼成可以通過網絡發(fā)送的一系列字節(jié)。沒關系,如果參數(shù)是像數(shù)字或字符串這樣的基本類型,但是對于較大的對象很快就會變成問題。

第五章 復制

? 復制意味著在通過網絡連接的多臺機器上保留相同數(shù)據(jù)的副本,需要復制的原因:

  • 使得數(shù)據(jù)與用戶在地理上接近(從而減少延遲)
  • 即使系統(tǒng)的一部分出現(xiàn)故障,系統(tǒng)也能繼續(xù)工作(從而提高可用性)
  • 擴展可以接受讀請求的機器數(shù)量(從而提高讀取吞吐量)

? 復制算法:單領導者(single leader)多領導者(multi leader)無領導者(leaderless)

? 基于領導者的復制原理:

  1. 副本之一被指定為 領導者(leader),也稱為 主庫(master|primary) 。當客戶端要向數(shù)據(jù)庫寫入時,它必須將請求發(fā)送給領導者,領導者會將新數(shù)據(jù)寫入其本地存儲。
  2. 其他副本被稱為追隨者(followers),亦稱為只讀副本(read replicas),從庫(slaves),備庫( sencondaries),熱備(hot-standby)i。每當領導者將新數(shù)據(jù)寫入本地存儲時,它也會將數(shù)據(jù)變更發(fā)送給所有的追隨者,稱之為復制日志(replication log)記錄或變更流(change stream)。每個跟隨者從領導者拉取日志,并相應更新其本地數(shù)據(jù)庫副本,方法是按照領導者處理的相同順序應用所有寫入。
  3. 當客戶想要從數(shù)據(jù)庫中讀取數(shù)據(jù)時,它可以向領導者或追隨者查詢。 但只有領導者才能接受寫操作(從客戶端的角度來看從庫都是只讀的)。

?

? 同步復制和異步復制:

?

? 同步復制的優(yōu)點是,從庫保證有與主庫一致的最新數(shù)據(jù)副本。如果主庫突然失效,我們可以確信這些數(shù)據(jù)仍然能在從庫上上找到。缺點是,如果同步從庫沒有響應(比如它已經崩潰,或者出現(xiàn)網絡故障,或其它任何原因),主庫就無法處理寫入操作。主庫必須阻止所有寫入,并等待同步副本再次可用。

? 因此,將所有從庫都設置為同步的是不切實際的:任何一個節(jié)點的中斷都會導致整個系統(tǒng)停滯不前。實際上,如果在數(shù)據(jù)庫上啟用同步復制,通常意味著其中一個跟隨者是同步的,而其他的則是異步的。如果同步從庫變得不可用或緩慢,則使一個異步從庫同步。這保證你至少在兩個節(jié)點上擁有最新的數(shù)據(jù)副本:主庫和同步從庫。 這種配置有時也被稱為 半同步。

? 通常情況下,基于領導者的復制都配置為完全異步。 在這種情況下,如果主庫失效且不可恢復,則任何尚未復制給從庫的寫入都會丟失。 這意味著即使已經向客戶端確認成功,寫入也不能保證 持久(Durable)。 然而,一個完全異步的配置也有優(yōu)點:即使所有的從庫都落后了,主庫也可以繼續(xù)處理寫入。

? 如何確保新的從庫擁有主庫數(shù)據(jù)的精確副本?

  1. 在某個時刻獲取主庫的一致性快照(如果可能),而不必鎖定整個數(shù)據(jù)庫。大多數(shù)數(shù)據(jù)庫都具有這個功能,因為它是備份必需的。對于某些場景,可能需要第三方工具,例如MySQL的innobackupex 【12】。
  2. 將快照復制到新的從庫節(jié)點。
  3. 從庫連接到主庫,并拉取快照之后發(fā)生的所有數(shù)據(jù)變更。這要求快照與主庫復制日志中的位置精確關聯(lián)。該位置有不同的名稱:例如,PostgreSQL將其稱為 日志序列號(log sequence number, LSN),MySQL將其稱為 二進制日志坐標(binlog coordinates)。
  4. 當從庫處理完快照之后積壓的數(shù)據(jù)變更,我們說它趕上(caught up)了主庫?,F(xiàn)在它可以繼續(xù)處理主庫產生的數(shù)據(jù)變化了。

? 節(jié)點宕機:

? 從庫失效:追趕恢復

? 在其本地磁盤上,每個從庫記錄從主庫收到的數(shù)據(jù)變更。如果從庫崩潰并重新啟動,或者,如果主庫和從庫之間的網絡暫時中斷,則比較容易恢復:從庫可以從日志中知道,在發(fā)生故障之前處理的最后一個事務。因此,從庫可以連接到主庫,并請求在從庫斷開連接時發(fā)生的所有數(shù)據(jù)變更。當應用完所有這些變化后,它就趕上了主庫,并可以像以前一樣繼續(xù)接收數(shù)據(jù)變更流。

? 主庫失效:故障切換

  1. 確認主庫失效。有很多事情可能會出錯:崩潰,停電,網絡問題等等。沒有萬無一失的方法來檢測出現(xiàn)了什么問題,所以大多數(shù)系統(tǒng)只是簡單使用 超時(Timeout) :節(jié)點頻繁地相互來回傳遞消息,并且如果一個節(jié)點在一段時間內(例如30秒)沒有響應,就認為它掛了(因為計劃內維護而故意關閉主庫不算)。
  2. 選擇一個新的主庫。這可以通過選舉過程(主庫由剩余副本以多數(shù)選舉產生)來完成,或者可以由之前選定的控制器節(jié)點(controller node)來指定新的主庫。主庫的最佳人選通常是擁有舊主庫最新數(shù)據(jù)副本的從庫(最小化數(shù)據(jù)損失)。讓所有的節(jié)點同意一個新的領導者,是一個共識問題,將在第9章詳細討論。
  3. 重新配置系統(tǒng)以啟用新的主庫。客戶端現(xiàn)在需要將它們的寫請求發(fā)送給新主庫,如果老領導回來,可能仍然認為自己是主庫,沒有意識到其他副本已經讓它下臺了。系統(tǒng)需要確保老領導認可新領導,成為一個從庫。

故障切換的麻煩:

? 如果使用異步復制,則新主庫可能沒有收到老主庫宕機前最后的寫入操作

? 如果數(shù)據(jù)庫需要和其他外部存儲相協(xié)調,那么丟棄寫入內容是極其危險的操作。

? 發(fā)生某些故障時可能會出現(xiàn)兩個節(jié)點都以為自己是主庫的情況,這種情況稱為 腦裂(split brain)。一些系統(tǒng)采取了安全防范措施:當檢測到兩個主庫節(jié)點同時存在時會關閉其中一個節(jié)點ii,但設計粗糙的機制可能最后會導致兩個節(jié)點都被關閉。

復制日志的實現(xiàn):

? 1、基于語句的復制

? 2、傳輸預寫式日志(WAL)

? 3、邏輯日志復制(基于行)

? 另一種方法是,復制和存儲引擎使用不同的日志格式,這樣可以使復制日志從存儲引擎內部分離出來。這種復制日志被稱為邏輯日志,以將其與存儲引擎的(物理)數(shù)據(jù)表示區(qū)分開來。

? 4、基于觸發(fā)器的復制

復制延遲問題

? 1、讀己之寫

?

? 圖 用戶寫入后從舊副本中讀取數(shù)據(jù)。需要寫后讀(read-after-write)的一致性來防止這種異常

? 2、單調讀

? 圖 用戶首先從新副本讀取,然后從舊副本讀取。時光倒流。為了防止這種異常,我們需要單調的讀取。

? 3、一致前綴讀

?

? 圖 如果某些分區(qū)的復制速度慢于其他分區(qū),那么觀察者在看到問題之前可能會看到答案。

復制延遲問題的解決方案:事務(性能和可用性代價過高)和其他替代機制

多主復制

? 應用場景

? 1、運維多個數(shù)據(jù)中心

?

? 圖 跨多個數(shù)據(jù)中心的多主復制

? 2、需要離線的客戶端

? 考慮手機,筆記本電腦和其他設備上的日歷應用。無論設備目前是否有互聯(lián)網連接,你需要能隨時查看你的會議(發(fā)出讀取請求),輸入新的會議(發(fā)出寫入請求)。如果在離線狀態(tài)下進行任何更改,則設備下次上線時,需要與服務器和其他設備同步。

在這種情況下,每個設備都有一個充當領導者的本地數(shù)據(jù)庫(它接受寫請求),并且在所有設備上的日歷副本之間同步時,存在異步的多主復制過程。復制延遲可能是幾小時甚至幾天,具體取決于何時可以訪問互聯(lián)網。

從架構的角度來看,這種設置實際上與數(shù)據(jù)中心之間的多領導者復制類似,每個設備都是一個“數(shù)據(jù)中心”,而它們之間的網絡連接是極度不可靠的。從歷史上各類日歷同步功能的破爛實現(xiàn)可以看出,想把多活配好是多么困難的一件事。

? 3、協(xié)同編輯

? 我們通常不會將協(xié)作式編輯視為數(shù)據(jù)庫復制問題,但與前面提到的離線編輯用例有許多相似之處。當一個用戶編輯文檔時,所做的更改將立即應用到其本地副本(Web瀏覽器或客戶端應用程序中的文檔狀態(tài)),并異步復制到服務器和編輯同一文檔的任何其他用戶。

如果要保證不會發(fā)生編輯沖突,則應用程序必須先取得文檔的鎖定,然后用戶才能對其進行編輯。如果另一個用戶想要編輯同一個文檔,他們首先必須等到第一個用戶提交修改并釋放鎖定。這種協(xié)作模式相當于在領導者上進行交易的單領導者復制。

但是,為了加速協(xié)作,您可能希望將更改的單位設置得非常?。ɡ纾粋€按鍵),并避免鎖定。這種方法允許多個用戶同時進行編輯,但同時也帶來了多領導者復制的所有挑戰(zhàn),包括需要解決沖突。

? 處理寫入沖突(多領導者復制的最大問題)

?

圖 兩個主庫同時更新同一記錄引起的寫入沖突

無主復制

? 當節(jié)點故障時寫入數(shù)據(jù)庫

?

? 圖5-10 仲裁寫入,法定讀取,并在節(jié)點中斷后讀修復。

? 檢測并發(fā)寫入

?

? 圖 并發(fā)寫入Dynamo風格的數(shù)據(jù)存儲:沒有明確定義的順序。

? 捕獲"此前發(fā)生"關系

? 最初,購物車是空的。在它們之間,客戶端向數(shù)據(jù)庫發(fā)出五次寫入:

  1. 客戶端 1 將牛奶加入購物車。這是該鍵的第一次寫入,服務器成功存儲了它并為其分配版本號1,最后將值與版本號一起回送給客戶端。
  2. 客戶端 2 將雞蛋加入購物車,不知道客戶端 1 同時添加了牛奶(客戶端 2 認為它的雞蛋是購物車中的唯一物品)。服務器為此寫入分配版本號 2,并將雞蛋和牛奶存儲為兩個單獨的值。然后它將這兩個值反回給客戶端 2 ,并附上版本號 2 。
  3. 客戶端 1 不知道客戶端 2 的寫入,想要將面粉加入購物車,因此認為當前的購物車內容應該是 [牛奶,面粉]。它將此值與服務器先前向客戶端 1 提供的版本號 1 一起發(fā)送到服務器。服務器可以從版本號中知道[牛奶,面粉]的寫入取代了[牛奶]的先前值,但與[雞蛋]的值是并發(fā)的。因此,服務器將版本 3 分配給[牛奶,面粉],覆蓋版本1值[牛奶],但保留版本 2 的值[蛋],并將所有的值返回給客戶端 1 。
  4. 同時,客戶端 2 想要加入火腿,不知道客端戶 1 剛剛加了面粉。客戶端 2 在最后一個響應中從服務器收到了兩個值[牛奶]和[蛋],所以客戶端 2 現(xiàn)在合并這些值,并添加火腿形成一個新的值,[雞蛋,牛奶,火腿]。它將這個值發(fā)送到服務器,帶著之前的版本號 2 。服務器檢測到新值會覆蓋版本 2 [雞蛋],但新值也會與版本 3 [牛奶,面粉]并發(fā),所以剩下的兩個是v3 [牛奶,面粉],和v4:[雞蛋,牛奶,火腿]
  5. 最后,客戶端 1 想要加培根。它以前在v3中從服務器接收[牛奶,面粉]和[雞蛋],所以它合并這些,添加培根,并將最終值[牛奶,面粉,雞蛋,培根]連同版本號v3發(fā)往服務器。這會覆蓋v3[牛奶,面粉](請注意[雞蛋]已經在最后一步被覆蓋),但與v4[雞蛋,牛奶,火腿]并發(fā),所以服務器保留這兩個并發(fā)值。

第六章 分區(qū)

分區(qū)與復制

? 分區(qū)通常與復制結合使用,使得每個分區(qū)的副本存儲在多個節(jié)點上。

? 圖6-1 組合使用復制和分區(qū):每個節(jié)點充當某些分區(qū)的領導者,其他分區(qū)充當追隨者。

鍵值數(shù)據(jù)的分區(qū)

? 1、根據(jù)鍵的范圍分區(qū)(字典)

? 2、根據(jù)鍵的散列分區(qū)

分區(qū)與次級索引

? 次級索引是關系型數(shù)據(jù)庫的基礎,并且在文檔數(shù)據(jù)庫中也很普遍。許多鍵值存儲(如HBase和Volde-mort)為了減少實現(xiàn)的復雜度而放棄了次級索引,但是一些(如Riak)已經開始添加它們,因為它們對于數(shù)據(jù)模型實在是太有用了。并且次級索引也是Solr和Elasticsearch等搜索服務器的基石。

? 次級索引的問題是它們不能整齊地映射到分區(qū)。有兩種用二級索引對數(shù)據(jù)庫進行分區(qū)的方法:基于文檔的分區(qū)(document-based)基于關鍵詞(term-based)的分區(qū)

? 按文檔的二級索引

?

? 根據(jù)關鍵詞(Term)的二級索引

?

分區(qū)再平衡

? 隨著時間的推移,數(shù)據(jù)庫會有各種變化。

  • 查詢吞吐量增加,所以您想要添加更多的CPU來處理負載。
  • 數(shù)據(jù)集大小增加,所以您想添加更多的磁盤和RAM來存儲它。
  • 機器出現(xiàn)故障,其他機器需要接管故障機器的責任。

所有這些更改都需要數(shù)據(jù)和請求從一個節(jié)點移動到另一個節(jié)點。 將負載從集群中的一個節(jié)點向另一個節(jié)點移動的過程稱為再平衡(reblancing)

無論使用哪種分區(qū)方案,再平衡通常都要滿足一些最低要求:

  • 再平衡之后,負載(數(shù)據(jù)存儲,讀取和寫入請求)應該在集群中的節(jié)點之間公平地共享。
  • 再平衡發(fā)生時,數(shù)據(jù)庫應該繼續(xù)接受讀取和寫入。
  • 節(jié)點之間只移動必須的數(shù)據(jù),以便快速再平衡,并減少網絡和磁盤I/O負載。

? 平衡策略:

* 反面教材:hash mod N
* 固定數(shù)量的分區(qū)

* 動態(tài)分區(qū)
* 按節(jié)點比例分區(qū)

請求路由(客戶端發(fā)送請求時連接數(shù)據(jù)庫的那個節(jié)點?)

  1. 允許客戶聯(lián)系任何節(jié)點(例如,通過循環(huán)策略的負載均衡(Round-Robin Load Balancer))。如果該節(jié)點恰巧擁有請求的分區(qū),則它可以直接處理該請求;否則,它將請求轉發(fā)到適當?shù)墓?jié)點,接收回復并傳遞給客戶端。
  2. 首先將所有來自客戶端的請求發(fā)送到路由層,它決定了應該處理請求的節(jié)點,并相應地轉發(fā)。此路由層本身不處理任何請求;它僅負責分區(qū)的負載均衡。
  3. 要求客戶端知道分區(qū)和節(jié)點的分配。在這種情況下,客戶端可以直接連接到適當?shù)墓?jié)點,而不需要任何中介。

? 許多分布式數(shù)據(jù)系統(tǒng)都依賴于一個獨立的協(xié)調服務,比如ZooKeeper來跟蹤集群元數(shù)據(jù)。 下圖每個節(jié)點在ZooKeeper中注冊自己,ZooKeeper維護分區(qū)到節(jié)點的可靠映射。 其他參與者(如路由層或分區(qū)感知客戶端)可以在ZooKeeper中訂閱此信息。 只要分區(qū)分配發(fā)生的改變,或者集群中添加或刪除了一個節(jié)點,ZooKeeper就會通知路由層使路由信息保持最新狀態(tài)。

第七章 事務

ACID

? 原子性(Atomicity)

? 在多線程編程中,如果一個線程執(zhí)行一個原子操作,這意味著另一個線程無法看到該操作的一半結果。系統(tǒng)只能處于操作之前或操作之后的狀態(tài),而不是介于兩者之間的狀態(tài)。

? ACID原子性的定義特征是:能夠在錯誤時中止事務,丟棄該事務進行的所有寫入變更的能力。如果這些寫操作被分組到一個原子事務中,并且該事務由于錯誤而不能完成(提交),則該事務將被中止,并且數(shù)據(jù)庫必須丟棄或撤消該事務中迄今為止所做的任何寫入。

? 一致性(Consistency)

? 對數(shù)據(jù)的一組特定陳述必須始終成立。即不變量(invariants)。例如,在會計系統(tǒng)中,所有賬戶整體上必須借貸相抵。如果一個事務開始于一個滿足這些不變量的有效數(shù)據(jù)庫,且在事務處理期間的任何寫入操作都保持這種有效性,那么可以確定,不變量總是滿足的。

? 原子性,隔離性和持久性是數(shù)據(jù)庫的屬性,而一致性(在ACID意義上)是應用程序的屬性。應用可能依賴數(shù)據(jù)庫的原子性和隔離屬性來實現(xiàn)一致性,但這并不僅取決于數(shù)據(jù)庫。

? 隔離性(Isolation)

? 同時執(zhí)行的事務是相互隔離的:它們不能相互冒犯。大多數(shù)數(shù)據(jù)庫都會同時被多個客戶端訪問。如果它們各自讀寫數(shù)據(jù)庫的不同部分,這是沒有問題的,但是如果它們訪問相同的數(shù)據(jù)庫記錄,則可能會遇到并發(fā)問題。

?

? 持久性(Durability)

? 持久性 是一個承諾,即一旦事務成功完成,即使發(fā)生硬件故障或數(shù)據(jù)庫崩潰,寫入的任何數(shù)據(jù)也不會丟失。

單對象和多對象操作

?

? 圖 違反隔離性:一個事務讀取另一個事務的未被執(zhí)行的寫入(“臟讀”)

? 沒有原子性,錯誤處理就要復雜得多,缺乏隔離性,就會導致并發(fā)問題。

事務隔離級別

? 讀已提交(Read Committed)

  1. 從數(shù)據(jù)庫讀時,只能看到已提交的數(shù)據(jù)(沒有臟讀(dirty reads))。
  2. 寫入數(shù)據(jù)庫時,只會覆蓋已經寫入的數(shù)據(jù)(沒有臟寫(dirty writes))。

?

圖 沒有臟讀:用戶2只有在用戶1的事務已經提交后才能看到x的新值。

圖 如果存在臟寫,來自不同事務的沖突寫入可能會混淆在一起

? 讀取偏差(不可重復讀)

? 在同一個事務中,客戶端在不同的時間點會看見數(shù)據(jù)庫的不同狀態(tài)。快照隔離經常用于解決這個問題??煺崭綦x的實現(xiàn)通常使用寫鎖來防止臟寫,從性能的角度來看,快照隔離的一個關鍵原則是:讀不阻塞寫,寫不阻塞讀。為了實現(xiàn)快照隔離,數(shù)據(jù)庫必須可能保留一個對象的幾個不同的提交版本,這種技術被稱為多版本并發(fā)控制。

? 如果一個數(shù)據(jù)庫只需要提供讀已提交的隔離級別,而不提供快照隔離,那么保留一個對象的兩個版本就足夠了:提交的版本和被覆蓋但尚未提交的版本。支持快照隔離的存儲引擎通常也使用MVCC來實現(xiàn)讀已提交隔離級別。一種典型的方法是讀已提交為每個查詢使用單獨的快照,而快照隔離對整個事務使用相同的快照。

?

? 圖中,當事務12 從賬戶2 讀取時,它會看到 $500 的余額,因為 $500 余額的刪除是由事務13 完成的(根據(jù)規(guī)則3,事務12 看不到事務13 執(zhí)行的刪除),且400美元記錄的創(chuàng)建也是不可見的(按照相同的規(guī)則)

圖 使用多版本對象實現(xiàn)快照隔離

? 更新丟失

兩個客戶端同時執(zhí)行**讀取-修改-寫入序列**。其中一個寫操作,在沒有合并另一個寫入變更情況下,直接覆蓋了另一個寫操作的結果。所以導致數(shù)據(jù)丟失??煺崭綦x的一些實現(xiàn)可以自動防止這種異常,而另一些實現(xiàn)則需要手動鎖定(`SELECT FOR UPDATE`)。

? 幻讀

? 事務讀取符合某些搜索條件的對象。另一個客戶端進行寫入,影響搜索結果。快照隔離可以防止直接的幻像讀取,但是寫入歪斜環(huán)境中的幻影需要特殊處理,例如索引范圍鎖定。

在存儲過程中封裝事務

? 即使人類已經找到了關鍵路徑,事務仍然以交互式的客戶端/服務器風格執(zhí)行,一次一個語句。應用程序進行查詢,讀取結果,可能根據(jù)第一個查詢的結果進行另一個查詢,依此類推。查詢和結果在應用程序代碼(在一臺機器上運行)和數(shù)據(jù)庫服務器(在另一臺機器上)之間來回發(fā)送。

在這種交互式的事務方式中,應用程序和數(shù)據(jù)庫之間的網絡通信耗費了大量的時間。如果不允許在數(shù)據(jù)庫中進行并發(fā)處理,且一次只處理一個事務,則吞吐量將會非常糟糕,因為數(shù)據(jù)庫大部分的時間都花費在等待應用程序發(fā)出當前事務的下一個查詢。在這種數(shù)據(jù)庫中,為了獲得合理的性能,需要同時處理多個事務。

出于這個原因,具有單線程串行事務處理的系統(tǒng)不允許交互式的多語句事務。取而代之,應用程序必須提前將整個事務代碼作為存儲過程提交給數(shù)據(jù)庫。這些方法之間的差異如圖所示。如果事務所需的所有數(shù)據(jù)都在內存中,則存儲過程可以非??斓貓?zhí)行,而不用等待任何網絡或磁盤I/O。

?

? 圖 交互式事務和存儲過程之間的區(qū)別

? 存儲過程與內存存儲,使得在單個線程上執(zhí)行所有事務變得可行。由于不需要等待I/O,且避免了并發(fā)控制機制的開銷,它們可以在單個線程上實現(xiàn)相當好的吞吐量。

可序列化快照隔離(SSI, serializable snapshot isolation)

? 檢測舊MVCC讀取(讀之前存在未提交的寫入)

?

? 當一個事務從MVCC數(shù)據(jù)庫中的一致快照讀時,它將忽略取快照時尚未提交的任何其他事務所做的寫入。上圖中,事務43 認為Alice的 on_call = true ,因為事務42(修改Alice的待命狀態(tài))未被提交。然而,在事務43想要提交時,事務42 已經提交。這意味著在讀一致性快照時被忽略的寫入已經生效,事務43 的前提不再為真。

? 為了防止這種異常,數(shù)據(jù)庫需要跟蹤一個事務由于MVCC可見性規(guī)則而忽略另一個事務的寫入。當事務想要提交時,數(shù)據(jù)庫檢查是否有任何被忽略的寫入現(xiàn)在已經被提交。如果是這樣,事務必須中止。

為什么要等到提交?當檢測到陳舊的讀取時,為什么不立即中止事務43 ?因為如果事務43 是只讀事務,則不需要中止,因為沒有寫入偏差的風險。當事務43 進行讀取時,數(shù)據(jù)庫還不知道事務是否要稍后執(zhí)行寫操作。此外,事務42 可能在事務43 被提交的時候中止或者可能仍然未被提交,因此讀取可能終究不是陳舊的。通過避免不必要的中止,SSI 保留快照隔離對從一致快照中長時間運行的讀取的支持。

? 檢測影響之前讀取的寫入(讀之后寫入)

? 上圖中,事務42 和43 都在班次1234 查找值班醫(yī)生。如果在shift_id上有索引,則數(shù)據(jù)庫可以使用索引項1234 來記錄事務42 和43 讀取這個數(shù)據(jù)的事實。 (如果沒有索引,這個信息可以在表級別進行跟蹤)。這個信息只需要保留一段時間:在一個事務完成(提交或中止)之后,所有的并發(fā)事務完成之后,數(shù)據(jù)庫就可以忘記它讀取的數(shù)據(jù)了。

? 當事務寫入數(shù)據(jù)庫時,它必須在索引中查找最近曾讀取受影響數(shù)據(jù)的其他事務。這個過程類似于在受影響的鍵范圍上獲取寫鎖,但鎖并不會阻塞事務到其他事務完成,而是像一個引線一樣只是簡單通知其他事務:你們讀過的數(shù)據(jù)可能不是最新的啦。

? 上圖中,事務43 通知事務42 其先前讀已過時,反之亦然。事務42首先提交并成功,盡管事務43 的寫影響了42 ,但因為事務43 尚未提交,所以寫入尚未生效。然而當事務43 想要提交時,來自事務42 的沖突寫入已經被提交,所以事務43 必須中止。

第八章 分布式系統(tǒng)的麻煩

? 部分失效是分布式系統(tǒng)的決定性特征。為了容忍錯誤,第一步是檢測它們,但即使這樣也很難。大多數(shù)系統(tǒng)沒有檢測節(jié)點是否發(fā)生故障的準確機制,所以大多數(shù)分布式算法依靠超時來確定遠程節(jié)點是否仍然可用。 一旦檢測到故障,使系統(tǒng)容忍它也并不容易:沒有全局變量,沒有共享內存,沒有共同的知識,或機器之間任何其他種類的共享狀態(tài)。

? 大多數(shù)非安全關鍵系統(tǒng)會選擇便宜而不可靠,而不是昂貴和可靠。分布式系統(tǒng)可以永久運行而不會在服務層面中斷,因為所有的錯誤和維護都可以在節(jié)點級別進行處理——至少在理論上是如此。 (實際上,如果一個錯誤的配置變更被應用到所有的節(jié)點,仍然會使分布式系統(tǒng)癱瘓)。

第九章 一致性與共識

一致性保證

? 最終一致性:非常弱的保證

? 線性一致性:最強一致性模型之一

? 因果一致性

線性一致性

?

? 圖 這個系統(tǒng)是非線性一致的,導致了球迷的困惑

? 線性一致性背后的基本思想很簡單:使系統(tǒng)看起來好像只有一個數(shù)據(jù)副本。

? 圖 可視化讀取和寫入看起來已經生效的時間點。 B的最后讀取不是線性一致性的

? 上圖中有一些有趣的細節(jié)需要指出:

  • 第一個客戶端B發(fā)送一個讀取 x 的請求,然后客戶端D發(fā)送一個請求將 x 設置為 0,然后客戶端A發(fā)送請求將 x 設置為 1。盡管如此,返回到B的讀取值為 1(由A寫入的值)。這是可以的:這意味著數(shù)據(jù)庫首先處理D的寫入,然后是A的寫入,最后是B的讀取。雖然這不是請求發(fā)送的順序,但這是一個可以接受的順序,因為這三個請求是并發(fā)的。也許B的讀請求在網絡上略有延遲,所以它在兩次寫入之后才到達數(shù)據(jù)庫。

  • 在客戶端A從數(shù)據(jù)庫收到響應之前,客戶端B的讀取返回 1 ,表示寫入值 1 已成功。這也是可以的:這并不意味著在寫之前讀到了值,這只是意味著從數(shù)據(jù)庫到客戶端A的正確響應在網絡中略有延遲。

  • 此模型不假設有任何事務隔離:另一個客戶端可能隨時更改值。例如,C首先讀取 1 ,然后讀取 2,因為兩次讀取之間的值由B更改??梢允褂迷?strong>比較并設置(cas)操作來檢查該值是否未被另一客戶端同時更改:B和C的cas請求成功,但是D的cas請求失?。ㄔ跀?shù)據(jù)庫處理它時,x 的值不再是 0 )。

  • 客戶B的最后一次讀?。幱皸l柱中)不是線性一致性的。 該操作與C的cas寫操作并發(fā)(它將 x2 更新為 4 )。在沒有其他請求的情況下,B的讀取返回 2 是可以的。然而,在B的讀取開始之前,客戶端A已經讀取了新的值 4 ,因此不允許B讀取比A更舊的值。再次,與圖9-1中的Alice和Bob的情況相同。

    這就是線性一致性背后的直覺。 正式的定義【6】更準確地描述了它。 通過記錄所有請求和響應的時序,并檢查它們是否可以排列成有效的順序,測試一個系統(tǒng)的行為是否線性一致性是可能的(盡管在計算上是昂貴的)【11】。

線性一致性的有效場景

? 鎖定和領導選舉 (zookeeper etcd 使用一致性算法以容錯方式保證)

? 約束和唯一性保證 (用戶名或電子郵件地址必須唯一標識一個用戶)

? 跨信道的時序依賴

? 圖 Web服務器和圖像調整器通過文件存儲和消息隊列進行通信,打開競爭條件的可能性

? 出現(xiàn)這個問題是因為Web服務器和縮放器之間存在兩個不同的信道:文件存儲與消息隊列。沒有線性一致性的新鮮性保證,這兩個信道之間的競爭條件是可能的。

因果一致性

? 因果性對系統(tǒng)中的事件施加了順序(什么發(fā)生在什么之前,基于因與果)。與線性一致不同,線性一致性將所有操作放在單一的全序時間線中,因果一致性為我們提供了一個較弱的一致性模型:某些事件可以是并發(fā)的,所以版本歷史就像是一條不斷分叉與合并的時間線。因果一致性沒有線性一致性的協(xié)調開銷,而且對網絡問題的敏感性要低得多。

分布式事務與共識

? 共識:所有節(jié)點一致同意所做決定,且這一決定不可撤銷。

? 共識問題

? 線性一致性的CAS寄存器

	寄存器需要基于當前值是否等于操作給出的參數(shù),原子地**決定**是否設置新值。

? 原子事務提交

	數(shù)據(jù)庫必須**決定**是否提交或中止分布式事務。

? 全序廣播

	消息系統(tǒng)必須**決定**傳遞消息的順序。

? 鎖和租約

	當幾個客戶端爭搶鎖或租約時,由鎖來**決定**哪個客戶端成功獲得鎖。

? 成員/協(xié)調服務

	給定某種故障檢測器(例如超時),系統(tǒng)必須**決定**哪些節(jié)點活著,哪些節(jié)點因為會話超時需		 要被宣告死亡。

? 唯一性約束

	當多個事務同時嘗試使用相同的鍵創(chuàng)建沖突記錄時,約束必須**決定**哪一個被允許,哪些因為		 違反約束而失敗。

第十章 批處理

三種系統(tǒng)類型

? *服務(在線系統(tǒng))*:每收到一個,服務會試圖盡快處理它,并發(fā)回一個響應。響應時間通常 是服務性能的主要衡量指標,可用性通常非常重要

? 批處理系統(tǒng)(離線系統(tǒng))*:大量的輸入數(shù)據(jù),跑一個作業(yè)(job)*來處理它,并生成一些輸出 數(shù)據(jù),這往往需要一段時間(從幾分鐘到幾天),所以通常不會有用戶等待作業(yè)完成。相反,批 量作業(yè)通常會定期運行(例如,每天一次)。批處理作業(yè)的主要性能衡量標準通常是吞吐量(處 理特定大小的輸入所需的時間).

? *流處理系統(tǒng)(準實時系統(tǒng))*: 介于兩者之間。流處理消費輸入并產生輸出,在事件發(fā)生后不久就會對事件進行操作,不會等待一組固定的輸入數(shù)據(jù)(批處理的特點),因此具有低延遲的特點。

UNIX 分析簡單日志

cat /var/log/nginx/access.log | #1
    awk '{print $7}' | #2
    sort             | #3
    uniq -c          | #4
    sort -r -n       | #5
    head -n 5          #6
1. 讀取日志文件
2. 將每一行按空格分割成不同的字段,每行只輸出第七個字段,恰好是請求的URL。在我們的例子中是`/css/typography.css`。
3. 按字母順序排列請求的URL列表。如果某個URL被請求過n次,那么排序后,文件將包含連續(xù)重復出現(xiàn)n次的該URL。
4. `uniq`命令通過檢查兩個相鄰的行是否相同來過濾掉輸入中的重復行。 `-c`則表示還要輸出一個計數(shù)器:對于每個不同的URL,它會報告輸入中出現(xiàn)該URL的次數(shù)。
5. 第二種排序按每行起始處的數(shù)字(`-n`)排序,這是URL的請求次數(shù)。然后逆序(`-r`)返回結果,大的數(shù)字在前。
6. 最后,只輸出前五行(`-n 5`),并丟棄其余的

output:
4189 /favicon.ico
    3631 /2013/05/24/improving-security-of-ssh-private-keys.html
    2124 /2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html
    1369 /
     915 /css/typography.css

? 優(yōu)點:接受任意形式輸入,符合萬物皆文件的概念 (進程的輸出可以是下一個進程的輸入)

? 各命令之間的性能高。

? 缺點:只能在一臺機器上運行(進程到進程) ---> 引出Hadoop

MapReduce

? MapReduce是一個編程框架,你可以使用它編寫代碼來處理HDFS等分布式文件系統(tǒng)中的大型數(shù)據(jù)集。支持多臺機器上進行并行計算。Mapper和Reducer一次只能處理一條記錄;它們不需要知道它們的輸入來自哪里,或者輸出去往什么地方,所以框架可以處理在機器之間移動數(shù)據(jù)的復雜性。

? 要創(chuàng)建MapReduce作業(yè),你需要實現(xiàn)兩個回調函數(shù),Mapper和Reducer。

? Mapper

? Mapper會在每條輸入記錄上調用一次,其工作是從輸入記錄中提取鍵值。對于每個輸入,它可以生成任意數(shù)量的鍵值對(包括None)。它不會保留從一個輸入記錄到下一個記錄的任何狀態(tài),因此每個記錄都是獨立處理的。

? Reducer

? MapReduce框架拉取由Mapper生成的鍵值對,收集屬于同一個鍵的所有值,并使用在這組值列表上迭代調用Reducer。 Reducer可以產生輸出記錄(例如相同URL的出現(xiàn)次數(shù))。

? 分布式執(zhí)行MapReduce

?

? 每個輸入文件的大小通常是數(shù)百兆字節(jié)。 MapReduce調度器(圖中未顯示)試圖在其中一臺存儲輸入文件副本的機器上運行每個Mapper,只要該機器有足夠的備用RAM和CPU資源來運行Mapper任務【26】。這個原則被稱為將計算放在數(shù)據(jù)附近【27】:它節(jié)省了通過網絡復制輸入文件的開銷,減少網絡負載并增加局部性。

? 計算的Reduce端也被分區(qū)。雖然Map任務的數(shù)量由輸入文件塊的數(shù)量決定,但Reducer的任務的數(shù)量是由作業(yè)作者配置的(它可以不同于Map任務的數(shù)量)。為了確保具有相同鍵的所有鍵值對最終落在相同的Reducer處,框架使用鍵的散列值來確定哪個Reduce任務應該接收到特定的鍵值對。

? 只要當Mapper讀取完輸入文件,并寫完排序后的輸出文件,MapReduce調度器就會通知Reducer可以從該Mapper開始獲取輸出文件。Reducer連接到每個Mapper,并下載自己相應分區(qū)的有序鍵值對文件。按Reducer分區(qū),排序,從Mapper向Reducer復制分區(qū)數(shù)據(jù),這一整個過程被稱為混洗(shuffle)

? Reduce任務從Mapper獲取文件,并將它們合并在一起,并保留有序特性。因此,如果不同的Mapper生成了鍵相同的記錄,則在Reducer的輸入中,這些記錄將會相鄰。Reducer調用時會收到一個鍵,和一個迭代器作為參數(shù),迭代器會順序地掃過所有具有該鍵的記錄(因為在某些情況可能無法完全放入內存中)。Reducer可以使用任意邏輯來處理這些記錄,并且可以生成任意數(shù)量的輸出記錄。這些輸出記錄會寫入分布式文件系統(tǒng)上的文件中

? 排序合并連接

?

? 為了在批處理過程中實現(xiàn)良好的吞吐量,計算必須(盡可能)限于單臺機器上進行。為待處理的每條記錄發(fā)起隨機訪問的網絡請求實在是太慢了。更好的方法是獲取用戶數(shù)據(jù)庫的副本,并將它和用戶行為日志放入同一個分布式文件系統(tǒng)中。

? 當MapReduce框架通過鍵對Mapper輸出進行分區(qū),然后對鍵值對進行排序時,效果是具有相同ID的所有活動事件和用戶記錄在Reducer輸入中彼此相鄰。 Map-Reduce作業(yè)甚至可以也讓這些記錄排序,使Reducer總能先看到來自用戶數(shù)據(jù)庫的記錄,緊接著是按時間戳順序排序的活動事件 —— 這種技術被稱為二次排序(secondary sort)

? 由于Reducer一次處理一個特定用戶ID的所有記錄,因此一次只需要將一條用戶記錄保存在內存中,而不需要通過網絡發(fā)出任何請求。這個算法被稱為排序合并連接(sort-merge join),因為Mapper的輸出是按鍵排序的,然后Reducer將來自連接兩側的有序記錄列表合并在一起。

? 處理傾斜

? 在單個Reducer中收集與某個名流相關的所有活動(例如他們發(fā)布內容的回復)可能導致嚴重的傾斜(也稱為熱點(hot spot))—— 也就是說,一個Reducer必須比其他Reducer處理更多的記錄(參見“負載傾斜與消除熱點“)。由于MapReduce作業(yè)只有在所有Mapper和Reducer都完成時才完成,所有后續(xù)作業(yè)必須等待最慢的Reducer才能啟動。

? Pig中的傾斜連接(skewed join)方法首先運行一個抽樣作業(yè)來確定哪些鍵是熱鍵。連接實際執(zhí)行時,Mapper會將熱鍵的關聯(lián)記錄隨機(相對于傳統(tǒng)MapReduce基于鍵散列的確定性方法)發(fā)送到幾個Reducer之一。對于另外一側的連接輸入,與熱鍵相關的記錄需要被復制到所有處理該鍵的Reducer上

? 廣播散列連接

? 兩個連接輸入之一很小,所以它并沒有分區(qū),而且能被完全加載進一個哈希表中。因此,你可以為連接輸入大端的每個分區(qū)啟動一個Mapper,將輸入小端的散列表加載到每個Mapper中,然后掃描大端,一次一條記錄,并為每條記錄查詢散列表。

? 分區(qū)散列連接

? 如果兩個連接輸入以相同的方式分區(qū)(使用相同的鍵,相同的散列函數(shù)和相同數(shù)量的分區(qū)),則可以獨立地對每個分區(qū)應用散列表方法。

? 回調函數(shù)

? 分布式批處理引擎有一個刻意限制的編程模型:回調函數(shù)(比如Mapper和Reducer)被假定是無狀態(tài)的,而且除了指定的輸出外,必須沒有任何外部可見的副作用。這一限制允許框架在其抽象下隱藏一些困難的分布式系統(tǒng)問題:當遇到崩潰和網絡問題時,任務可以安全地重試,任何失敗任務的輸出都被丟棄。如果某個分區(qū)的多個任務成功,則其中只有一個能使其輸出實際可見。

? 得益于這個框架,你在批處理作業(yè)中的代碼無需操心實現(xiàn)容錯機制:框架可以保證作業(yè)的最終輸出與沒有發(fā)生錯誤的情況相同,也許不得不重試各種任務。在線服務處理用戶請求,并將寫入數(shù)據(jù)庫作為處理請求的副作用,比起在線服務,批處理提供的這種可靠性語義要強得多。

批處理的特點總結

? 批處理作業(yè)的顯著特點是,它讀取一些輸入數(shù)據(jù)并產生一些輸出數(shù)據(jù),但不修改輸入—— 換句話說,輸出是從輸入衍生出的。最關鍵的是,輸入數(shù)據(jù)是有界的(bounded):它有一個已知的,固定的大小(例如,它包含一些時間點的日志文件或數(shù)據(jù)庫內容的快照)。因為它是有界的,一個作業(yè)知道自己什么時候完成了整個輸入的讀取,所以一個工作在做完后,最終總是會完成的。

第十一章 流處理

? 消息代理和事件日志可以視作文件系統(tǒng)的流式等價物。

消息代理(消息隊列)

? 與數(shù)據(jù)庫的差異

  • 數(shù)據(jù)庫通常保留數(shù)據(jù)直至顯式刪除,而大多數(shù)消息代理在消息成功遞送給消費者時會自動刪除消息。這樣的消息代理不適合長期的數(shù)據(jù)存儲。
  • 由于它們很快就能刪除消息,大多數(shù)消息代理都認為它們的工作集相當小—— 即隊列很短。如果代理需要緩沖很多消息,比如因為消費者速度較慢(如果內存裝不下消息,可能會溢出到磁盤),每個消息需要更長的處理時間,整體吞吐量可能會惡化【6】。
  • 數(shù)據(jù)庫通常支持二級索引和各種搜索數(shù)據(jù)的方式,而消息代理通常支持按照某種模式匹配主題,訂閱其子集。機制并不一樣,對于客戶端選擇想要了解的數(shù)據(jù)的一部分,這是兩種基本的方式。
  • 查詢數(shù)據(jù)庫時,結果通?;谀硞€時間點的數(shù)據(jù)快照;如果另一個客戶端隨后向數(shù)據(jù)庫寫入一些改變了查詢結果的內容,則第一個客戶端不會發(fā)現(xiàn)其先前結果現(xiàn)已過期(除非它重復查詢或輪詢變更)。相比之下,消息代理不支持任意查詢,但是當數(shù)據(jù)發(fā)生變化時(即新消息可用時),它們會通知客戶端。

? 多個消費者

? 負載均衡與扇出

?

? 圖(a)負載平衡:在消費者間共享消費主題;(b)扇出:將每條消息傳遞給多個消費者。

? 兩種模式可以組合使用:例如,兩個獨立的消費者組可以每組各訂閱一個主題,每一組都共同收到所有消息,但在每一組內部,每條消息僅由單個節(jié)點處理。

? 分區(qū)日志(基于日志的消息代理)

?

圖 生產者通過將消息追加寫入主題分區(qū)文件來發(fā)送消息,消費者依次讀取這些文件

? 變更數(shù)據(jù)捕獲(CDC)

?

圖 將數(shù)據(jù)按順序寫入一個數(shù)據(jù)庫,然后按照相同的順序將這些更改應用到其他系統(tǒng)

流處理的三種類型

? 流流連接

? 兩個輸入流都由活動事件組成,而連接算子在某個時間窗口內搜索相關的事件。例如,它可能會將同一個用戶30分鐘內進行的兩個活動聯(lián)系在一起。如果你想要找出一個流內的相關事件,連接的兩側輸入可能實際上都是同一個流(自連接(self-join))。

? 流表連接

? 一個輸入流由活動事件組成,另一個輸入流是數(shù)據(jù)庫變更日志。變更日志保證了數(shù)據(jù)庫的本地副本是最新的。對于每個活動事件,連接算子將查詢數(shù)據(jù)庫,并輸出一個擴展的活動事件。

? 表表連接

? 兩個輸入流都是數(shù)據(jù)庫變更日志。在這種情況下,一側的每一個變化都與另一側的最新狀態(tài)相連接。結果是兩表連接所得物化視圖的變更流。

第十二章 數(shù)據(jù)系統(tǒng)的未來

? 某些系統(tǒng)被指定為記錄系統(tǒng),而其他數(shù)據(jù)則通過轉換衍生自記錄系統(tǒng)。通過這種方式,我們可以維護索引,物化視圖,機器學習模型,統(tǒng)計摘要等等。通過使這些衍生和轉換操作異步且松散耦合,能夠防止一個區(qū)域中的問題擴散到系統(tǒng)中不相關部分,從而增加整個系統(tǒng)的穩(wěn)健性與容錯性。

? 將數(shù)據(jù)流表示為從一個數(shù)據(jù)集到另一個數(shù)據(jù)集的轉換也有助于演化應用程序:如果你想變更其中一個處理步驟,例如變更索引或緩存的結構,則可以在整個輸入數(shù)據(jù)集上重新運行新的轉換代碼,以便重新衍生輸出。同樣,出現(xiàn)問題時,你也可以修復代碼并重新處理數(shù)據(jù)以便恢復。

? 這些過程與數(shù)據(jù)庫內部已經完成的過程非常類似,因此我們將數(shù)據(jù)流應用的概念重新改寫為,分拆(unbundling) 數(shù)據(jù)庫組件,并通過組合這些松散耦合的組件來構建應用程序。

? 衍生狀態(tài)可以通過觀察底層數(shù)據(jù)的變更來更新。此外,衍生狀態(tài)本身可以進一步被下游消費者觀察。我們甚至可以將這種數(shù)據(jù)流一路傳送至顯示數(shù)據(jù)的終端用戶設備,從而構建可動態(tài)更新以反映數(shù)據(jù)變更,并在離線時能繼續(xù)工作的用戶界面。

? 接下來,我們討論了如何確保所有這些處理在出現(xiàn)故障時保持正確。我們看到可擴展的強完整性保證可以通過異步事件處理來實現(xiàn),通過使用端到端操作標識符使操作冪等,以及通過異步檢查約束??蛻舳丝梢缘鹊綑z查通過,或者不等待繼續(xù)前進,但是可能會冒有違反約束需要道歉的風險。這種方法比使用分布式事務的傳統(tǒng)方法更具可擴展性與可靠性,并且在實踐中適用于很多業(yè)務流程。

? 通過圍繞數(shù)據(jù)流構建應用,并異步檢查約束,我們可以避免絕大多數(shù)的協(xié)調工作,創(chuàng)建保證完整性且性能仍然表現(xiàn)良好的系統(tǒng),即使在地理散布的情況下與出現(xiàn)故障時亦然。然后,我們對使用審計來驗證數(shù)據(jù)完整性,以及損壞檢測進行了一些討論。

? 最后,我們退后一步,審視了構建數(shù)據(jù)密集型應用的一些道德問題。我們看到,雖然數(shù)據(jù)可以用來做好事,但它也可能造成很大傷害:作出嚴重影響人們生活的決定卻難以申訴,導致歧視與剝削,監(jiān)視常態(tài)化,曝光私密信息。我們也冒著數(shù)據(jù)被泄露的風險,并且可能會發(fā)現(xiàn),即使是善意地使用數(shù)據(jù)也可能會導致意想不到的后果。

? 由于軟件和數(shù)據(jù)對世界產生了如此巨大的影響,我們工程師們必須牢記,我們有責任為我們想要的那種世界而努力:一個尊重人們,尊重人性的世界。我希望我們能夠一起為實現(xiàn)這一目標而努力。


網站欄目:DDIA 學習筆記
網頁鏈接:http://weahome.cn/article/dsoisjh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部