深度剖析 | 關於數據鎖定和讀取一致性問題

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1 背景介紹","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"傳統的 RDBMS 系統在三件事上值得注意:鎖定:即鎖定記錄的功能,以便其他人無法更改它們。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"閱讀一致性:您(僅您自己)可以看到您所做的更改,直到您提交爲止,這時其他人才可以看到它們。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"遺憾的是,其較差的可伸縮性:在線事務處理(OLTP)工作負載無法很好地擴展。在現實情況下,將CPU內核數量加倍不會使您的容量翻倍。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這種失敗導致許多人嘗試使用NoSQL解決方案,但是隨着時間的流逝,越來越明顯的是,如果沒有這些解決方案,鎖定和讀取一致性將很難實現。VOLTDB是唯一的數據平臺,可讓企業按比例進行鎖定和讀取一致性。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文解釋了爲什麼很難做到這一點,以及VOLTDB是如何做到這一點的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2 爲什麼縮放OLTP很難?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了讓大家更直觀地瞭解爲什麼擴展OLTP很難,先來讓我們看一下簡單的白板交易的典型生命週期:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在表格“ a”中插入一行","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"更新表“ b”中的行","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"更新表“ c”中的行","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"做外部活動","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"更新表“ a”中的行","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"犯罪","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"乍一看,可能很難看出這是如何擴展的。但是,讓我們看一下使用舊版RDBMS的實際實現:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/82/822786ecf69b897a3148a0c2b8879492.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在此圖中,有這樣幾件事變得顯而易見:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1.此操作不會立即完成","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"您需要12次網絡運行,每次運行都需要花費不少時間。在任意一段時間內,“現實世界的設備”都會關閉,並會做任何需要做的事情。簡而言之:即使一切工作正常,此事務的耗時也將是幾毫秒。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2. 長時間運行的數據交換將是數據庫服務器的挑戰","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每次更改數據庫服務器中的內容時,您都需要做更多工作,因爲所有其他正在進行的數據交換都需要查看錶的“舊”版本,直到提交爲止。出於實際目的的考量,每個不完整的交易都需要自己的數據庫版本,該數據庫由現有數據及其未提交的更改組成。這意味着,如果您每秒運行一千筆交易,並且每筆交易的端到端需要 10 毫秒(即每次網絡行程少於 1 毫秒),則隨時將至少有 100 種不同版本的數據庫存在,並且必須仔細檢查任何新交易,以確保它不會與其他人的更改衝突。無論您使用SELECT FOR UPDATE,MVCC還是任何其他機制,此開銷仍然存在。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"3.當您增加CPU芯數時,遞減收益法則就會生效","attrs":{}},{"type":"text","text":"隨着工作量的增加,常規解決方法是添加更多的CPU內核並將工作分散在它們之間。雖然這在短期內會有所幫助,但它會帶來另一個問題:當您只有一個CPU內核時,可以肯定的是,當嘗試處理會話請求時,數據庫的其他100個實時版本不會改變。這正是我們正在做的。但是,添加第二個CPU內核後,數據庫需要協調它們的活動。這引入了一個全新的層的開銷,每當您在“幫助”中添加另一個CPU內核時,問題就會以幾何級的速度變得更糟。最終的結果是形成了一個惡性循環,在其中添加CPU內核以提高TPS,但是每個新內核都需要關聯消耗所有其他核心,最終將消耗您通過添加額外核心獲得的CPU容量。如果額外的CPU容量來自羣集中的另一個節點,那麼事情將會出錯。因爲CPU內核之間相互爭論的問題現在變成了到另一個數據庫節點的網絡訪問。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"4.隨着容量的增加,性能變得越來越不穩定","attrs":{}},{"type":"text","text":"實際經驗告訴我們,即使您在各方面都做到最佳,您仍然會在實際環境中遇到鎖定問題,因爲實際數據使用模式可能與測試場景大不相同。一個典型的例子是網站訪問者在添加購物車或購物籃並按下“重新加載”時會不耐煩,這可能會導致以下情況:舊請求已鎖定記錄,而新請求則通知用戶“其他人”已鎖定它。物聯網(IoT)和電信應用程序尤其容易出現這種情況,因爲許多API的默認行爲是在未收到即時響應時自動重試。這可能會導致完全違背直覺的情況,即減少請求數量將大大增加成功完成的交易數量,因爲交易妨礙對方的機會較少。現實生活中發生的是,任何阻止其他更多交易完成的單個交易都可能導致活動量激增,尤其是當應用程序開始盲目重試時。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"5.應用服務器或微服務器成爲系統中的薄弱環節","attrs":{}},{"type":"text","text":"市場上幾乎每臺數據庫服務器都具有某種形式的高可用性,但是應用程序服務器和微服務器通常被視爲“無狀態”,因爲數據庫服務器負責管理狀態。但是,如果您所有的客戶都被路由到單個組件,並且該組件有大約100筆未完成的交易,那麼如果死機了該怎麼辦?數據庫服務器從已連接的會話的角度看待世界,其中一些會話已鎖定。在已結束組件的會話持有數百個行級鎖的世界中,您可以期望數據庫服務器在幾分鐘內遵守該鎖定,直到最終弄清該組件已結束並關閉所涉及的會話,釋放他們的鎖定狀態。這意味着,即使您已經準備好另一個應用服務器或容器立即承擔其已結束前置的工作量,否則它將無法對鎖定了幾分鐘的任何記錄進行任何更改,這意味着“有效”多組數據將凍結幾分鐘,在此期間它將無法進行修改。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"6.沒有任何明顯的方法可以解決此問題","attrs":{}},{"type":"text","text":"嘗試擴展OLTP的最簡單方法是切換到NoSQL存儲,該存儲要求客戶端在進行更改之前發送證明已讀取特定版本的記錄的證據。這將爲您帶來更快的性能,直到人們開始爭用數據爲止。最常見的實現是將值的哈希值與值本身一起發送回客戶端。然後,將該哈希作爲一種密碼通過網絡發送,以證明該更改是對先前狀態的合法修改。如果哈希錯誤,則意味着其他人同時更改了該值,您需要重新開始。這是一個不能令人滿意的解決方案,因爲當多個人開始同時更改同一條記錄時,它會導致與傳統系統相同的負載下不穩定的性能。這也意味着,在上述情況下,您可能需要操縱兩個或甚至三個鍵值對。實際上,您要做的就是將事務複雜性降低到客戶端層。顯然,您需要另一種解決方案。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3 VOLTDB是如何做到這一點的?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"VoltDB的創建者,包括圖靈獎獲得者Michael Stonebraker,都考慮到了這一特定問題,開發了VoltDB數據平臺,並有效地解決了該問題。VoltDB數據平臺在做三件事上有不同之處:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1.IT分區將工作負載分配給每個分區,而這是控制CPU核心的單一物理線程的專有責任","attrs":{}},{"type":"text","text":"是的,許多現代數據平臺都在劃分工作負載。但是,我們僅需將分區與在單個CPU內核上運行的單線程對齊即可,這意味着該內核無需擔心另一個內核在做什麼,因此,VoltDB立即消除了上述幾何可伸縮性問題。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2.它允許任意數量的SQL語句和每個TRIP的邏輯關聯到VOLTDB","attrs":{}},{"type":"text","text":"儘管您可以愉快地將JDBC與VoltDB一起使用,但是當您嘗試將事例名稱和您使用的參數傳遞到 VoltDB 上的服務器側邏輯時,您可以減少網絡訪問次數和VoltDB必須跟蹤的中間狀態數量。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"3.它表明每次訪問都以提交結束","attrs":{}},{"type":"text","text":"這似乎有些劇烈,但對性能有重大影響。在任何時候,VoltDB分區都僅僅處理一個事務,因爲它只有單個線程“擁有”其中的所有數據。通過堅持所有事務都是“提交”或“返回”狀態,VoltDB不必從客戶的角度跟蹤存儲狀態數據庫的任何額外“副本”。因此,在上面的實例中,VoltDB實現無需跟蹤數據庫的100個版本, 每個分區僅使用一個活動副本。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"綜上,這些更改既爲您提供了傳統RDBMS的功能,並且具有出色的可伸縮性,其性能是同一個硬件的大約9倍。現在,讓我們看一下同一筆交易在VoltDB中是如何進展的。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/13/13d72ff030fe6a42c2c0470e191783be.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這可以通過兩次調用VoltDB來完成。第一次調用執行前三個更改,並將會話ID /到期日期添加到另外兩個軟鎖列中。這允許其他交互查看正在進行的交易,並自行決定要做什麼。當外部任務完成時,第二個調用觸發,並清除軟鎖列。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e6/e69d9fc76baa8177102944b463cdd85c.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們比較兩種方法的統計信息:如您所見,VoltDB的真實事務是通過更少的網絡行程,更少的客戶端API調用以及通過避免應用服務器節點丟失的明確方法來完成的。但這並不意味着沒有其他可考慮的情況。讓我們看看有關VoltDB如何進行鎖定和讀取一致性的常見問題。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4 Q & A","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1.如果數據庫服務器出故障了怎麼辦?","attrs":{}},{"type":"text","text":"我們在序列圖中未顯示的是,分區每次收到請求時,都會立即同步將該請求轉發到位於另一臺物理服務器上的一個或多個“備份”分區。然後,所有分區將同時開始處理同一任務。這意味着,如果一個節點死亡,則在羣集中的其他節點上會存在該分區的可行且最新副本,數據庫將以最小的時間損失和機上交易損失,重新啓動。","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"2.如果應用程序服務器出現故障,該怎麼辦?","attrs":{}},{"type":"text","text":"只要客戶可以使用正確的鎖標識符找我們,我們的處理將照常進行。在傳統的RDBMS中,當涉及到鎖定時,狀態將有效地保留在客戶端和服務器上,因爲服務器已使用客戶端會話唯一的標識符標記行。但是,如果客戶端銷戶,則該會話將無效。這意味着您需要等待服務器將數據庫連接標識爲過去狀態並結束它,然後其他人才能修改該記錄。在VoltDB的系統裏,我們通過允許多個SQL語句和關聯的邏輯在服務器上運行,來“設計”大多數應用場景。如果邏輯交易在關聯的交易事件完成之前依然無法完成,您可以使用簡單的 SQL 自行鎖定邏輯,從而重新控制情況並滿足您的 SLAs 。","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"3.VoltDB是否會自動執行此操作?","attrs":{}},{"type":"text","text":"不會,但是它在數據庫表中多了兩列,並增加了大約十二行代碼。與處理傳統 RDBMS 或 NoSQL 交易和鎖定行爲所需的開發人員時間相比,這是完全合理的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"4.我們仍然可以使用JDBC嗎?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"是的,我們的許多應用程序代碼是基於JDBC的。在大多數應用程序中,20% 的開發人員時間用於編寫 80% 的 SQL,這些 SQL 是友好的或直接的。其他 20% 涉及複雜的交易,正是這種方法使其變得非常有價值。","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"5.“每個內核一個分區一個線程”爲何比共享工作負載的多線程和多內核更快?","attrs":{}},{"type":"text","text":"乍一看,似乎任何核心能夠處理任何問題看起來是最佳選擇。但是,正如我們上面討論的那樣,隨着您線性地添加多個內核,協調多個內核活動所需的努力會以幾何方式升級。而將事務強制進入虛擬隊列並讓每個隊列進行單個線程。這個過程要高效得多。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5 結論","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"鎖定和讀取一致性是當今世紀的兩個重要領域,RDBMS和較新的NoSQL系統都無法滿足其需求,提供合理答案。在VoltDB,我們的使命是專注於可預測的、符合嚴苛標準的大規模交易。雖然我們理解我們的一些設計決策可能看起來非常規,但這些決策卻是由多年的實際經驗決定的。如果您還有其他疑問,或者想了解更多有關VoltDB如何在保持低延遲的情況下支持現代應用程序的信息,請聯繫我們吧!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic","attrs":{}}],"text":"關於VoltDBVoltDB支持強ACID和實時智能決策的應用程序,以實現互聯世界。沒有其它數據庫產品可以像VoltDB這樣,可以同時需要低延時、大規模、高併發數和準確性相結合的應用程序加油。VoltDB由2014年圖靈獎獲得者Mike Stonebraker博士創建,他對關係數據庫進行了重新設計,以應對當今不斷增長的實時操作和機器學習挑戰。Stonebraker博士對數據庫技術研究已有40多年,在快速數據,流數據和內存數據庫方面帶來了衆多創新理念。在VoltDB的研發過程中,他意識到了利用內存事務數據庫技術挖掘流數據的全部潛力,不但可以滿足處理數據的延遲和併發需求,還能提供實時分析和決策。VoltDB是業界可信賴的名稱,在諾基亞、金融時報、三菱電機、HPE、巴克萊、華爲等領先組織合作有實際場景落地案例。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"VoltDB中國:","attrs":{}},{"type":"link","attrs":{"href":"https://link.zhihu.com/?target=https%3A//www.voltdb-china.cn/","title":null,"type":null},"content":[{"type":"text","text":"https://www.voltdb-china.cn/","attrs":{}}],"marks":[{"type":"underline"}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章