天天看點

深度剖析 | 關于資料鎖定和讀取一緻性問題

1 背景介紹

傳統的 RDBMS 系統在三件事上值得注意:

鎖定:即鎖定記錄的功能,以便其他人無法更改它們。

閱讀一緻性:您(僅您自己)可以看到您所做的更改,直到您送出為止,這時其他人才可以看到它們。

遺憾的是,其較差的可伸縮性:線上事務處理(OLTP)工作負載無法很好地擴充。在現實情況下,将CPU核心數量加倍不會使您的容量翻倍。

這種失敗導緻許多人嘗試使用NoSQL解決方案,但是随着時間的流逝,越來越明顯的是,如果沒有這些解決方案,鎖定和讀取一緻性将很難實作。

VOLTDB是唯一的資料平台,可讓企業按比例進行鎖定和讀取一緻性。

本文解釋了為什麼很難做到這一點,以及VOLTDB是如何做到這一點的。

2 為什麼縮放OLTP很難?

為了讓大家更直覺地了解為什麼擴充OLTP很難,先來讓我們看一下簡單的白闆交易的典型生命周期:

  • 在表格“ a”中插入一行
  • 更新表“ b”中的行
  • 更新表“ c”中的行
  • 做外部活動
  • 更新表“ a”中的行
  • 犯罪

乍一看,可能很難看出這是如何擴充的。但是,讓我們看一下使用舊版RDBMS的實際實作:

深度剖析 | 關于資料鎖定和讀取一緻性問題

在此圖中,有這樣幾件事變得顯而易見:

1.此操作不會立即完成

您需要12次網絡運作,每次運作都需要花費不少時間。在任意一段時間内,“現實世界的裝置”都會關閉,并會做任何需要做的事情。

簡而言之:即使一切工作正常,此事務的耗時也将是幾毫秒。

2. 長時間運作的資料交換将是資料庫伺服器的挑戰

每次更改資料庫伺服器中的内容時,您都需要做更多工作,因為所有其他正在進行的資料交換都需要檢視表的“舊”版本,直到送出為止。

出于實際目的的考量,每個不完整的交易都需要自己的資料庫版本,該資料庫由現有資料及其未送出的更改組成。這意味着,如果您每秒運作一千筆交易,并且每筆交易的端到端需要 10 毫秒(即每次網絡行程少于 1 毫秒),則随時将至少有 100 種不同版本的資料庫存在,并且必須仔細檢查任何新交易,以確定它不會與其他人的更改沖突。

無論您使用SELECT FOR UPDATE,MVCC還是任何其他機制,此開銷仍然存在。

3.當您增加CPU芯數時,遞減收益法則就會生效

随着工作量的增加,正常解決方法是添加更多的CPU核心并将工作分散在它們之間。

雖然這在短期内會有所幫助,但它會帶來另一個問題:當您隻有一個CPU核心時,可以肯定的是,當嘗試處理會話請求時,資料庫的其他100個實時版本不會改變。這正是我們正在做的。

但是,添加第二個CPU核心後,資料庫需要協調它們的活動。這引入了一個全新的層的開銷,每當您在“幫助”中添加另一個CPU核心時,問題就會以幾何級的速度變得更糟。

最終的結果是形成了一個惡性循環,在其中添加CPU核心以提高TPS,但是每個新核心都需要關聯消耗所有其他核心,最終将消耗您通過添加額外核心獲得的CPU容量。

如果額外的CPU容量來自群集中的另一個節點,那麼事情将會出錯。因為CPU核心之間互相争論的問題現在變成了到另一個資料庫節點的網絡通路。

4.随着容量的增加,性能變得越來越不穩定

實際經驗告訴我們,即使您在各方面都做到最佳,您仍然會在實際環境中遇到鎖定問題,因為實際資料使用模式可能與測試場景大不相同。

一個典型的例子是網站通路者在添加購物車或購物籃并按下“重新加載”時會不耐煩,這可能會導緻以下情況:舊請求已鎖定記錄,而新請求則通知使用者“其他人”已鎖定它。物聯網(IoT)和電信應用程式尤其容易出現這種情況,因為許多API的預設行為是在未收到即時響應時自動重試。

這可能會導緻完全違背直覺的情況,即減少請求數量将大大增加成功完成的交易數量,因為交易妨礙對方的機會較少。現實生活中發生的是,任何阻止其他更多交易完成的單個交易都可能導緻活動量激增,尤其是當應用程式開始盲目重試時。

5.應用伺服器或微伺服器成為系統中的薄弱環節

市場上幾乎每台資料庫伺服器都具有某種形式的高可用性,但是應用程式伺服器和微伺服器通常被視為“無狀态”,因為資料庫伺服器負責管理狀态。但是,如果您所有的客戶都被路由到單個元件,并且該元件有大約100筆未完成的交易,那麼如果當機了該怎麼辦?

資料庫伺服器從已連接配接的會話的角度看待世界,其中一些會話已鎖定。在已結束元件的會話持有數百個行級鎖的世界中,您可以期望資料庫伺服器在幾分鐘内遵守該鎖定,直到最終弄清該元件已結束并關閉所涉及的會話,釋放他們的鎖定狀态。

這意味着,即使您已經準備好另一個應用伺服器或容器立即承擔其已結束前置的工作量,否則它将無法對鎖定了幾分鐘的任何記錄進行任何更改,這意味着“有效”多組資料将當機幾分鐘,在此期間它将無法進行修改。

6.沒有任何明顯的方法可以解決此問題

嘗試擴充OLTP的最簡單方法是切換到NoSQL存儲,該存儲要求用戶端在進行更改之前發送證明已讀取特定版本的記錄的證據。

這将為您帶來更快的性能,直到人們開始争用資料為止。最常見的實作是将值的哈希值與值本身一起發送回用戶端。然後,将該哈希作為一種密碼通過網絡發送,以證明該更改是對先前狀态的合法修改。如果哈希錯誤,則意味着其他人同時更改了該值,您需要重新開始。

這是一個不能令人滿意的解決方案,因為當多個人開始同時更改同一條記錄時,它會導緻與傳統系統相同的負載下不穩定的性能。這也意味着,在上述情況下,您可能需要操縱兩個或甚至三個鍵值對。實際上,您要做的就是将事務複雜性降低到用戶端層。

顯然,您需要另一種解決方案。

3 VOLTDB是如何做到這一點的?

VoltDB的建立者,包括圖靈獎獲得者Michael Stonebraker,都考慮到了這一特定問題,開發了VoltDB資料平台,并有效地解決了該問題。

VoltDB資料平台在做三件事上有不同之處:

1.IT分區将工作負載配置設定給每個分區,而這是控制CPU核心的單一實體線程的專有責任

是的,許多現代資料平台都在劃分工作負載。但是,我們僅需将分區與在單個CPU核心上運作的單線程對齊即可,這意味着該核心無需擔心另一個核心在做什麼,是以,VoltDB立即消除了上述幾何可伸縮性問題。

2.它允許任意數量的SQL語句和每個TRIP的邏輯關聯到VOLTDB

盡管您可以愉快地将JDBC與VoltDB一起使用,但是當您嘗試将事例名稱和您使用的參數傳遞到 VoltDB 上的伺服器側邏輯時,您可以減少網絡通路次數和VoltDB必須跟蹤的中間狀态數量。

3.它表明每次通路都以送出結束

這似乎有些劇烈,但對性能有重大影響。

在任何時候,VoltDB分區都僅僅處理一個事務,因為它隻有單個線程“擁有”其中的所有資料。通過堅持所有事務都是“送出”或“傳回”狀态,VoltDB不必從客戶的角度跟蹤存儲狀态資料庫的任何額外“副本”。是以,在上面的執行個體中,VoltDB實作無需跟蹤資料庫的100個版本, 每個分區僅使用一個活動副本。

綜上,這些更改既為您提供了傳統RDBMS的功能,并且具有出色的可伸縮性,其性能是同一個硬體的大約9倍。

現在,讓我們看一下同一筆交易在VoltDB中是如何進展的。

深度剖析 | 關于資料鎖定和讀取一緻性問題

這可以通過兩次調用VoltDB來完成。第一次調用執行前三個更改,并将會話ID /到期日期添加到另外兩個軟鎖列中。這允許其他互動檢視正在進行的交易,并自行決定要做什麼。當外部任務完成時,第二個調用觸發,并清除軟鎖列。

深度剖析 | 關于資料鎖定和讀取一緻性問題

讓我們比較兩種方法的統計資訊:

如您所見,VoltDB的真實事務是通過更少的網絡行程,更少的用戶端API調用以及通過避免應用伺服器節點丢失的明确方法來完成的。但這并不意味着沒有其他可考慮的情況。讓我們看看有關VoltDB如何進行鎖定和讀取一緻性的常見問題。

4 Q & A

1.如果資料庫伺服器出故障了怎麼辦?

我們在序列圖中未顯示的是,分區每次收到請求時,都會立即同步将該請求轉發到位于另一台實體伺服器上的一個或多個“備份”分區。然後,所有分區将同時開始處理同一任務。

這意味着,如果一個節點死亡,則在群集中的其他節點上會存在該分區的可行且最新副本,資料庫将以最小的時間損失和機上交易損失,重新啟動。

2.如果應用程式伺服器出現故障,該怎麼辦?

隻要客戶可以使用正确的鎖辨別符找我們,我們的處理将照常進行。在傳統的RDBMS中,當涉及到鎖定時,狀态将有效地保留在用戶端和伺服器上,因為伺服器已使用用戶端會話唯一的辨別符标記行。

但是,如果用戶端銷戶,則該會話将無效。這意味着您需要等待伺服器将資料庫連接配接辨別為過去狀态并結束它,然後其他人才能修改該記錄。

在VoltDB的系統裡,我們通過允許多個SQL語句和關聯的邏輯在伺服器上運作,來“設計”大多數應用場景。如果邏輯交易在關聯的交易事件完成之前依然無法完成,您可以使用簡單的 SQL 自行鎖定邏輯,進而重新控制情況并滿足您的 SLAs 。

3.VoltDB是否會自動執行此操作?

不會,但是它在資料庫表中多了兩列,并增加了大約十二行代碼。與處理傳統 RDBMS 或 NoSQL 交易和鎖定行為所需的開發人員時間相比,這是完全合理的。

4.我們仍然可以使用JDBC嗎?

是的,我們的許多應用程式代碼是基于JDBC的。在大多數應用程式中,20% 的開發人員時間用于編寫 80% 的 SQL,這些 SQL 是友好的或直接的。其他 20% 涉及複雜的交易,正是這種方法使其變得非常有價值。

5.“每個核心一個分區一個線程”為何比共享工作負載的多線程和多核心更快?

乍一看,似乎任何核心能夠處理任何問題看起來是最佳選擇。但是,正如我們上面讨論的那樣,随着您線性地添加多個核心,協調多個核心活動所需的努力會以幾何方式更新。而将事務強制進入虛拟隊列并讓每個隊列進行單個線程。這個過程要高效得多。

5 結論

鎖定和讀取一緻性是當今世紀的兩個重要領域,RDBMS和較新的NoSQL系統都無法滿足其需求,提供合理答案。在VoltDB,我們的使命是專注于可預測的、符合嚴苛标準的大規模交易。雖然我們了解我們的一些設計決策可能看起來非正常,但這些決策卻是由多年的實際經驗決定的。

如果您還有其他疑問,或者想了解更多有關VoltDB如何在保持低延遲的情況下支援現代應用程式的資訊,請聯系我們吧!

關于VoltDB

VoltDB支援強ACID和實時智能決策的應用程式,以實作互聯世界。沒有其它資料庫産品可以像VoltDB這樣,可以同時需要低延時、大規模、高并發數和準确性相結合的應用程式加油。

VoltDB由2014年圖靈獎獲得者Mike Stonebraker博士建立,他對關系資料庫進行了重新設計,以應對當今不斷增長的實時操作和機器學習挑戰。Stonebraker博士對資料庫技術研究已有40多年,在快速資料,流資料和記憶體資料庫方面帶來了衆多創新理念。

在VoltDB的研發過程中,他意識到了利用記憶體事務資料庫技術挖掘流資料的全部潛力,不但可以滿足處理資料的延遲和并發需求,還能提供實時分析和決策。VoltDB是業界可信賴的名稱,在諾基亞、金融時報、三菱電機、HPE、巴克萊、華為等領先組織合作有實際場景落地案例。

VoltDB中國:https://www.voltdb-china.cn/