最佳實踐 | OceanBase事務引擎的技術創新
顏然,螞蟻金服 OceanBase 團隊資深技術專家,OceanBase 初創成員之一,目前負責事務引擎以及效能優化相關的研發工作。
首先,我們先來聊一個大家都很感興趣的話題:跟已有的經典資料庫比如:Oracle、SQL Server等,OceanBase跟他們最大的區別在哪裡? OceanBase是一個雲原生的資料庫 。而我們所做的軟體全部是基於硬體的基礎之上。那麼,我們首先就需要了解現在的硬體到底處在什麼水平?
如上圖所示,IBM的解決方案是最為大家所熟識的,從五十多年前的System 360到去年新出的IBM z14,時至今日依然還有很多機構在沿用這套解決方案。
我們每天都在說雲端計算,那麼到底什麼是雲端計算?雲端計算不是從石頭縫裡蹦出來的解決方案,它最早起源於DEC的小型機。DEC是和IBM大型機同時代的產物,以較低的價格解決儲存和計算的需求。它與IBM大型機的區別在於:DEC價格低,獲得方式更靈活。
DEC之後被基於晶片的解決方案打破了,諸如SUN工作站的解決方案提供了更好的效能和更低價格,平臺也更通用。再之後PC Server接過接力棒,此時的CPU、記憶體、儲存可以來自於不同的廠商,但大家組合起來以後仍然可以提供一套標準化的計算和儲存的平臺。
相比較IBM大型機,基於PC Server的資料中心以一種更產業鏈化的方式提供了計算和儲存的解決方案,具有更好的價效比,也更易於擴充套件。但是IBM大型機是軟硬一體化設計,這也是大型機滿足需求可以採用很多硬體層面的解決思路。例如,金融業務對於高可靠性的需求,大型機是在硬體層面做了多種可靠性保障,從儲存到記憶體甚至CPU都是有冗餘策略來支援。但是PC Server的單臺機器的故障率相對來說是高的,所以需要使用完全不同的思路來解決業務高可靠和高可用的需求。
此處引用OceanBase團隊創始人陽振坤的一句話——“ 計算機天然不適合資料庫,但資料庫天然選擇了計算機 ”。為什麼計算機天然不適合資料庫?因為在處理資料的時候,一個非常關鍵的問題就是資料的可靠安全和一致。而計算機的硬體天然具有各種概率的損壞,不管是掉電,軟體出Bug,作業系統有問題,還是整個機房都掛掉,計算機是天然會出錯的。但我們要解決的問題又是不能出錯,所以在計算機上去解決資料庫的可靠安全一致性的問題,其實是一個非常大的挑戰。
要在一個更低可靠性的機器上實現更可靠的資料庫的事務服務能力,這就是我們當前所面臨的嚴峻挑戰。
OceanBase事務
當然,有挑戰的地方就有機遇。OceanBase在面對這樣的挑戰之下我們做了什麼?在這樣的一個基於PC Server的雲化環境下, OceanBase實現了彈性擴充套件的能力,同時實現了不依賴高階硬體解決資料庫事務的高可靠和高可用的能力。
OceanBase所依賴的硬體條件是一套通用的雲化環境。但在這個硬體基礎上,我們依然可以做到資料庫的事務,同樣能夠實現高效能,甚至能夠支撐金融級的可靠性。
何謂金融級可靠性?每個人都會有切身的感受。比如說你發了一條帖子,但是這條帖子丟了,你可能會不爽,但是不至於非常難受。再換一個場景,今天你給朋友轉賬100元,你朋友卻只收到98元,此時你的內心一定是恐懼的。所以在這種金融級場景下,必須做到的就是為使用者提供充足的保障,這就叫做金融級可靠性。但金融級可靠性的難度在於對細節的處理能力。細節是魔鬼,我們在做資料庫軟體的時候,需要對細節的把控能力極強。
這裡要重點提到的幾點,其實就延續著資料庫事務的幾個重要的特性。
- OceanBase架構下事務 ACID 的實現方式:
- Durability:事務日誌使用 Paxos做多副本同步
- Atomicity:使用兩階段提交保證跨機事務原子性
- Isolation:使用多版本機制進行併發控制
- Consistency:保證唯一性約束
OceanBase儲存引擎
OceanBase的架構基於LSM Tree。為什麼會基於LSM Tree?它有哪些特點?
在經典的資料庫裡,所有的資料是分片儲存在持久化儲存裡的,比如磁碟或者SSD。在讀取資料的時候,一定要先把它放在記憶體裡。當需要做修改的時候,也要把一塊資料放在記憶體裡。如果記憶體滿了之後,就會把這個頁面刷回去。
OceanBase所基於的LSMTree,可以把更多的修改更集中地放在一個記憶體結構裡。我們的做法是在後臺定期地做這件事情,前臺把資料儘可能存更久的時間,然後再讓後臺去做合併。OceanBase有一個機制叫每日合併,也就是說如果前臺能存一天的時間,我們到了每天夜裡才做後臺合併這件事情。
OceanBase會在系統內部做排程,第一臺機器在後臺刷髒頁的時候,讓業務的流量都跑在其他機器上,就可以不影響前臺的業務。當第一臺完成後,再把業務的流量切回來,然後讓第二臺機器做後臺刷髒頁的操作。我們通過這種“輪轉合併”的方法解決在叢集環境下利用不同機器不同服務的時間差去做刷髒頁這件事情。
OceanBase事務引擎設計也利用了LSM Tree的結構,讓事務的所有執行狀態都儲存在記憶體中,只有事務提交之後才會把事務修改的資料持久化。所以在實現事務原子性時,不需要做undo。這樣OceanBase可以以一個更簡潔的方式來做資料庫的事務。這個就是OceanBase儲存引擎的整體邏輯。
OceanBase記憶體事務引擎
OceanBase的事務執行操作都在記憶體裡發生。記憶體跟硬碟一個最大的差別,就是記憶體是可以以位元組為單位進行隨機定址的,而這帶來的一個非常大的好處就是使得資料結構更豐富了。
舉個例子,如上圖表格中的資料,現在要對第一行資料進行更新:條件是給Han加50萬薪水。現在需要給這張表格中這一列對應的Han寫一個新的值。在記憶體裡的表示方法就是這樣一個連結串列。如果Han漲了薪水以後突然希望換部門接受全新的挑戰,我們就需要再做一次更新操作。只需要在這個列表裡串上一次新的更新把他的部門進行更改。他從研發部門轉到投資部門了,那我們就把這一列對應的修改記錄在這裡。
這個是資料庫內部基於多版本的一種併發控制,記錄了每一次更新發生的時間,保證了修改操作跟讀取操作不會互相影響。因為即使一行資料被改了,我們還是可以直接拿到歷史資料。基於連結串列的資料結構對程式設計師來說是非常友好的。
相比較經典的基於硬碟的資料庫,無論資料讀取還是寫入都是定長資料塊為單位的操作,表達資訊的方式也是基於塊的。OceanBase的方式帶來的一個最大的好處就是大大提升了表達的簡潔性,也就是它本身的操作效率要高特別多。這也解釋了了為什麼OceanBase能在目前的硬體環境下提供更強的事務處理能力,這是其中一個很重要的原因。
我們再回顧一下OceanBase的架構,OceanBase把資料分片了之後,可以在多個叢集裡的多臺機器上把資料擴展出去做儲存,它提供了線性擴充套件能力。
像上圖所示同樣一份資料會有多個副本,比如P0在三臺機器上,這三臺機器可能在同一個機房,也可能來自不同機房。但是它們會服務於同一份資料,其中只有一個是當前的主,它負責做資料庫的操作,並且把資料庫事務的修改同步到其他的機器上。我們這裡提到OceanBase的資料組織與分佈的目的就是要解決後面資料庫的可靠性問題。
可靠性 vs 可用性
高可靠和高可用是被所有資料庫產品廣泛提及的概念。那麼,可靠性和可用性到底意味著什麼?
傳統的資料庫,ACID的理論裡並沒有availability這個概念,只保證了durable。但是資料不丟,卻不一定能保證服務的連續性。但是failover的能力在實際的系統中卻是非常重要的。所以所有的商業資料庫都有對應的解決可用性的方案。其中經典的就是基於主備同步的方案,當主壞掉的時候,備可以繼續提供服務,這就是在解決可用性的問題。
OceanBase採用Paxos協議來解決可靠性和可用性的問題。任何一個數據庫的事務要做持久化,事務的日誌都需要持久到多個副本上。在三個副本之中,我們認為只要持久化到兩個副本的硬碟上,就定義為這個事務是成功的。也就是說有任何一臺機器壞了的時候,至少還有一個副本在。
那麼,反過來思考是不是同步到越多的機器上越好?如果三個副本都同步到,是不是就更加可靠了?這就是可用性所帶來的問題,如果其中有一臺機器網路出現故障,或者系統負載太高無法響應,你是否認為這個事務成功?
如果要求三個都成功的話,就不能認為它成功,因為有一臺機器沒響應。Paxos協議只要求兩個機器同步到,就是即便有一個沒有應答,我們依然認為這個事務是成功的,因為多數派成功了。
保證三個裡面有一個壞掉是不受影響的,同時也不影響系統的持續服務。這是在可靠性和可用性中間的一個很好的平衡。如果你需要更高的保障,就可以選擇五個副本的方案,這樣可以保證有兩臺機器出故障的時候,同樣既不影響可靠性,也不影響可用性,這是一個很重要的平衡點。
所以我們在ACID裡再加入一個A,也就是我們既要讓事務有可靠性,也要讓事務的處理能力有可用性。
分散式事務二階段提交協議
資料庫在單機上寫日誌一定是隻寫自己機器上的日誌檔案,如果寫成功了就成功,不成功就失敗。但是在多臺機器上的時候就涉及到:A機器成功了,B機器失敗了。這件事情該怎麼辦?
兩階段提交協議的存在就是為了解決這個問題,也就是說提交再也不能是一次性就成功的,它要涉及到多個機器之間達成一致,每臺機器都成功了最終才能定義為成功。
事實上,兩階段提交協議在實際應用中非常少。為什麼呢?主要因為它很複雜,雖然理論很漂亮,但是存在的細節問題特別多。但是在OceanBase的業務場景下又一定要用兩階段提交協議來解決。
OceanBase的基礎是每一個參與者都是高可用的,因為OceanBase使用了Paxos協議保證了Partition高可用,所以任何一臺機器的故障不會導致服務停止,這是一個很重要的前提。另外,因為Paxos同步引入了跨網路、跨機房的同步延遲,原始的兩階段提交協議多次寫日誌會帶來較多的開銷,OceanBase做了一件事情就是讓協調者不寫日誌,只保留記憶體狀態。它帶來的一個非常重要的好處就是commit延遲低。同時因為所有參與者都是高可用的,我們不會出現兩階段狀態一般會出現的問題,比如協調者宕機卡住的問題。
OceanBase事務隔離
事務隔離涉及到事務的併發控制怎麼做,OceanBase使用的是多版本併發控制。讀取請求會拿到當前系統的publish version作為讀取的快照版本。事務提交的時候會生成一個版本號,版本號是連續遞增的,作為本事務所有修改資料的版本。
單機場景下,一條日誌就能決定這個事務最終是否能夠提交。那麼這條日誌的位置就決定了這個事務的版本號,它的版本號一定是遞增連續的。但是在分散式事務參與進來之後,舉個例子,就會出現230可能是一條prepare日誌,prepare日誌不代表這個事務能夠提交,但是232可能是另外一個事務的commit日誌,這也就意味著這個事務要commit的話,232版本就需要可讀,但是230又處在行鎖未解事務進行中的狀態。這個時候就需要另外一種控制方法,對於兩階段提交的prepare和commit之間的事務,這些事務所有操作的行要鎖住,不允許讀取。
這個影響很小是因為在prepare和commit之間不涉及到使用者的任何干預,是一個毫秒級的操作,也就是說,這個行在提交的過程中會在一個很短的瞬間被鎖住。這個瞬間裡讀取操作會等待事務提交掉,再去判斷該不該讀這一行的資料。
總結
基於以上的技術創新,OceanBase真正實現了在雲環境下事務的高可靠、高可用,同時還具有很好的效能。希望OceanBase可以幫助更多的業務解決資料儲存和查詢的需求,不再受困於傳統商業資料庫的價格高、擴充套件性差的問題。