歡迎訪問 OceanBase 官網獲取更多資訊:https://www.oceanbase.com/
3 月 25 日,第一屆 OceanBase 開發者大會在北京舉行,OceanBase 首席架構師楊志豐(花名:竹翁)帶來了 《OceanBase 的單機分散式一體化》 的分享,為大家介紹了單機分散式一體化架構的概念及思考,以及對業務的價值。
以下為演講實錄:
今天我的演講主題是《OceanBase 的單機分散式一體化》,主要來解釋 OceanBase 為什麼要做單機分散式一體化,我將從以下 3 個方面進行今天的分享:
首先,單機分散式一體化是什麼?
其次,單機部署時如何獲得與單機資料庫相當的效能?
最後,分散式部署時如何實現高效能低時延?
什麼是單機分散式一體化?
每個人聽到“單機分散式一體化”可能都會有自己不同的理解,也會有很多疑問,事實上,單機分散式一體化不是 OceanBase 突然冒出來的概念,而是基於三方面的原因。
第一,產品迭代。 OceanBase 從 2010 年開始自研,在走出螞蟻集團開始服務金融行業,到現在走到雲上去服務更多網際網路行業客戶的過程中,基於客戶的反饋,我們的產品不斷在演變、完善。
第二,硬體趨勢的不斷髮展。 OceanBase 在 1.0 最初設計的時候,當時我們在螞蟻集團的內部叢集,用的機器都是普通 16 核的機器,後面隨著硬體技術的發展,我們的主流機器都在 96 核以上,伺服器單機的效能有了極大的提升。
第三,雲技術的發展。 近幾年,雲技術發展突飛猛進,OceanBase 剛剛創立之初,雲技術剛剛興起,而現在雲基礎設施觸手可得。技術的發展伴隨著 OceanBase 架構的發展,OceanBase 的技術經歷了三個大的版本迭代。
▋ 從 0.1 到 4.0,OceanBase 的發展歷程
第一個版本是 0.5 版本,雖然是十幾年前的版本,但其實它已經完全是分散式的架構,在當時,OceanBase 把 SQL 層和儲存引擎做了分離,上面是一組 SQL 無狀態服務,下面是由 ChunkServer 和 UpdateServer 組成的儲存叢集,對外暴露的就是表的 API。當時由於我們剛剛開始去做資料庫的實現,所以我們做了一些限制——沒有多點寫入,所以當時實際上是不支援分散式事務的。
當 OceanBase 從 0.5 往 1.0 演進的時候,我們有一個深刻的感受:傳統單機資料庫採用緊耦合的設計,儲存和計算放在一起,後來因為有了 NoSQL,很多人覺得是不是應該把儲存層單獨隔離開,OceanBase 在零點幾版本的時候就遵循這樣的設計思路,所以我們做了分離,但分離以後帶來非常大的問題。
這個問題在於做 NoSQL 還可以,但是要做關係型資料庫並沒有那麼簡單,如果你對時延有要求的話,松耦合的方式會導致效率上有很大開銷。所以 OceanBase 從 1.0 開始,我們就在重新思考這個問題—— 把儲存事務 SQL 做成緊耦合的架構,即全分散式架構,將原來的三個 Server 合成一個 OBServer 的節點,同時處理儲存事務 SQL,同時我們將高可用的粒度,由原來機器級別的高可用粒度,切分成若干個 Zone, 這些都得益於我們在螞蟻集團的場景實踐。
當 OceanBase 發展到 2.0 版本時,OceanBase 從螞蟻集團走向了外部客戶,在這個過程中客戶反饋說:“OceanBase 只支援 MySQL,是很好,但我們這裡面有很多的 legacy(遺留) 系統是不可能把它完全的改成用 MySQL 或者用開源的方式去做的”,所以 OceanBase 在 2.0 的時候引入了重要的特性,在多租戶的能力之上又相容了 Oracle,但它的整體架構和 1.0 是一樣的,在 4.0 版本時,我們就進入了全新的單機分散式一體化的階段。
▋ 單機分散式一體化的三個含義
現在,我來正式定義一下 OceanBase 單機分散式一體化到底是什麼,單機分散式一體化有三個層面的含義。
第一個層面,OceanBase 以一個程式的形式存在,既可以在單機的形式下部署,也可以做成多機部署。 這個並不是非常容易做到的事情,只有我們把單機分散式一體化作為一個目標,才能去實現這樣的形態。
第二個層面,我們所謂的單機分散式一體化,其實有一個租戶的概念。 即使你部署了一個分散式的 OceanBase 叢集,但是裡面的某一個租戶如果在單機上,我們也認為這是一種單機的形態。
第三個層面,單機分散式可動態轉換。 在兩種形態之間,OceanBase 可以隨意切換,可以靈活地做動態的調整,單機可以變成分散式,分散式可以變成單機,同樣在租戶層面和叢集層面都可以做到。
雖然也會有其他方面的很多挑戰,但切換的最大挑戰顯然是關於效能的,所以接下來我將分享 OceanBase 怎麼做到在單機分散式一體化架構下面,在單機部署的時候可以做到單機資料庫相當,在分散式部署的時候我們在保證可擴充套件性的同時,又可以做到比其他的分散式資料庫更高的效能和更低的時延。
▋ 單機分散式一體化,匹配企業不同發展階段
首先看業務的價值,對於很多企業來說他是有一個從小到大的過程,或者說在大企業內部有個小的業務,業務都是從小開始變大,有一天可能某個業務突然冒出來,但最初的時候其實並不需要那麼多的資源,我們希望使用者既可以享受到分散式資料庫帶來的優勢,使用起來又不存在非常多的困難,可以一個資料庫解決企業多個不同發展階段的需求。
OceanBase 正式支援單機形態部署。如果你對讀寫分離有要求,你可以使用 OceanBase 主備庫的能力,就像傳統的 MySQL 的主備庫一樣,沒有任何的區別;如果你覺得 MySQL 的主備庫在切換的時候會產生丟資料的問題,特別是遠端容災的時候,可以從主備庫動態的升級到 OceanBase 三副本模式;如果你覺得高可用、三副本的模式不能在現階段掌握,或者對你來說不是很關鍵,那麼 OceanBase 其實具有非常強的單機模式下 scale-up 垂直擴充套件的能力,所以我們並不是做分散式資料庫就不管單機的效能。
當企業或者業務發展到大規模場景的時候,有非常多的問題要考慮。比如,業務特別多,在螞蟻集團內部,大家可以想象有非常多的業務、甚至有上萬臺的機器在使用 OceanBase,這個時候如果你只有 10 人的 DBA 團隊,你怎麼去管理一萬個 MySQL,這是非常大的挑戰,所以我們的多租戶和整個分散式的架構,使得我們可以把叢集的數目控制在一個合理範圍之內,在每個叢集內部有很多自動化運維的手段,讓我們的 DBA 真的可以安穩的睡一個好覺,此時有很多非功能性的需求就提出來了。
比如,分散式資料庫是很好,但是我可能在當前這個階段並不需要。但是我想說“有了 OceanBase 的單機分散式一體化架構,大家不會有擔心,你可以在你需要的時候選擇你所需要的特性”。反過來說,如果我引入了分散式資料庫,同時給你搭售了三副本和很多其他你不需要的能力,那不是我們所希望的,這也是我們單機資料庫核心的價值。
單機部署時如何獲得與單機資料庫相當的效能
▋ 過度分層設計雖然簡化了實現,但犧牲了效能
反過來想這個問題,如果我有一個分散式的資料庫,左側是其他的分散式資料庫的典型形態,將儲存節點和計算節點做一個分離,他們之間透過網路進行通訊,這樣的話是可以各自做擴充的。分散式資料庫當然不是僅分片那麼簡單,資料庫很重要的是事務處理的中心節點,資料庫要保證資料全域性的一致性和原子性,所以很多資料庫會引入這樣一個全域性事務管理器的模組。
OceanBase 也有類似的模組,我們叫全域性時間戳服務,功能都是類似的,像上邊的右圖一樣,將三個節點裝到一臺單機上。
很多人說這樣的“單機分散式一體化”我們也可以,但這裡面是有非常多開銷的,因為分散式處理所涉及的很多協議,對於單機來說都是開銷,各個元件之間,如果你透過 RPC 做通訊,會產生非常多額外的開銷,另外 RPC 協議是需要專門去設計的,所以在設計這種通訊協議的時候,不能像函式呼叫一樣,可以儘量靈活的做很多快捷的處理。
此外,還有一層隱藏的含義,就是從我們從事資料庫研發的視角來說,如果你以分散式作為開頭,你在實際實現過程中不會去想單機是什麼情況,這個是大家可以理解的。
▋ OceanBase 的單機分散式一體化
我們看一下 OceanBase 單機分散式一體化整體的架構,說起來非常簡單: 每一臺機器都具有自己獨立的 SQL 儲存事務的模組,在單機之內,SQL 儲存事務之間直接透過函式呼叫,和單機沒有任何區別;在機器和機器之間透過網路去做通訊。
上圖中的架構有幾個特徵:第一,每個節點單程式,OceanBase 沒有那麼多角色區分,整個 SQL 事務儲存是在單個程式內共享記憶體的;第二,單機內工作是沒有 RPC 的,並且對於單機資料庫來說,為了提升垂直的擴充套件性,OceanBase 還支援單機內並行,在更深層次上,每個元件的設計,OceanBase 都會兼顧單機和分散式。
在這樣的設計裡面,我們每一個功能的設計都要考慮在單機內怎麼樣做最好,分散式時怎麼做最好,所以我們的設計都會有這樣兩個維度。
首先看單機的兩個含義,第一,每個 Zone 裡面一個OBServer,所以即使一個 Zone 裡面有很多個資源的單元,即 Unit,如果你的租戶是單個 Unit,就等於這裡所講的單機。
為了提升單機內垂直的擴充套件性,OceanBase 在 SQL 引擎、事務引擎、儲存引擎都會做到極致的最佳化:第一,單機內可以並行;第二,在事務引擎裡,我們在做事務的高併發處理的時會做組提交的技術。同樣在儲存引擎裡面,我們的儲存引擎屬於準記憶體的儲存引擎,寫入的時候只需要放到記憶體裡就可以了,並不需要像傳統的 B+ 樹一樣,把它寫到資料塊裡。單機內同樣在 IO 層面支援很多並行。
你會看到早期的 MySQL 給他一個 96 核的叢集,想把 CPU 跑滿,是不可能的,這就是垂直擴充套件性的表現。
▋ OceanBase 4.0 VS MySQL 8.0
上圖是 OceanBase 4.0 和 MySQL 8.0 的效能對比,在六種場景下,OceanBase 4.0 和 MySQL 8.0 的效能都是相當的。
上圖是我們垂直擴充套件性的試驗,同樣在 Sysbench 的六種負載場景下, 從 4 核到 64 核的機器,大家都可以看到 OceanBase 具有非常好的垂直擴充套件性,多給一倍的核數,OceanBase 的效能就提升一倍。
分散式部署時如何實現高效能低時延
對於 OLTP 業務來說,大家用分散式資料庫很擔心時延的指標,那麼單個操作的時延指標是不是能像單機資料庫一樣呢?這是 OceanBase 著力在最佳化的點。基本原因就是:無論你在怎麼樣的資料中心,做一次 RPC 就需要 0.5 毫秒,這個時間不可忽略。
▋ 分散式效能需要高效能低時延
下圖是在某個特定的負載下面,隨著分散式事務比例的增加,單機資料庫和兩種分散式資料庫的效能表現,綠色是單機資料庫。
隨著某種分散式事務的增加,對於比如 TPC-C 來說,即跨 warehouse 交易的增加,和單機資料沒有什麼差別。如果有兩種資料庫, OceanBase 的設計目標是變成下面 DB1 的效能曲線,隨著分散式事務增加,肯定有開銷,但當我還沒有分散式事務的時候,DB2 的效能就比 MySQL 差非常多,這不是我們想設計的分散式資料庫。
此時有兩種方式可以做到,第一就是降低分散式事務和分散式查詢的這個比例,正如 CTO 楊傳輝所說: “實際上對於很多線上型的交易,全域性性的事務,他的比例往往並沒有大家想的那麼多。在典型的 TPC-C 場景下,TPC-C 裡跨 warehouse 的交易查詢只有10%” (可移步閱讀《OceanBase CTO楊傳輝:萬字解讀,打造開發者友好的分散式資料庫》)。做線上交易的時候,DBA 同學很清楚自己的業務,並不是所有的東西都要付出分散式的開銷,為了能夠達到這樣的效果,我們做了很多的工作,其中最主要的就是 4.0 裡面自適應的日誌流。
OceanBase 做了很多自適應的策略,去自動化的根據表的設計去做自動的負載均衡,自動的做資料排布減少分散式事務和分散式查詢的比例,如果這些自動化的措施都達不到這個目標,使用者同樣可以用我們提供的分割槽表和表組的功能自己去控制、降低分散式事務。
如果以上的要求都做不到怎麼辦呢?我們就必須硬碰硬地降低分散式事務和分散式查詢整個的開銷,這塊 OceanBase 有很多獨特的設計。
▋ OceanBase 分散式為何能高效經濟?
回到單機分散式一體化架構,在這個架構下面我們看看分散式場景下它是怎麼工作的。
對於上面這種分層的設計來說,如果 SQL 層、儲存層、事務層是分層的設計,無論自己怎麼操作,這個 SQL 和本地的事務之間是沒有感知的,所有的東西都是全域性的,本地的交易資料還是遠端的交易資料對於 SQL 層都沒有差別。OceanBase 不是這樣,我們顯式的就區分了這兩者的區別,所以 OceanBase 的 SQL 層可以直接訪問到另外一臺機器的儲存層。如果需要訪問另外一臺機器儲存層的時候我做 RPC,如果我訪問的儲存是在本地,就不需要做 RPC。
整體設計的時候有幾個不同的粒度,本質上設計時我們做得更加精細化,精細化是說單機分散式並不是簡單的概念,而是多個粒度的單機,在我們看起來有四個基本的粒度:
第一,租戶。 是分散式的租戶還是單機的租戶。
第二,會話。 OceanBase 會透過 Proxy 路由協議使得在很多其他資料庫裡面分散式的做一件事情,在 OceanBase 會變成單機的事情。最典型的就是我們會根據這條 SQL 的特徵,把它路由到儲存所在的節點上,這樣即使整體上看起來好像是分散式,但是對於那條 SQL 的執行,它就變成本地執行。
第三,事務。 在事務層面上,OceanBase 如果在單個事務內只操作一個日誌流內的分割槽,分散式事務提交的協議和單機的協議也是有區別的。
第四,SQL。 如果是一個單機的 SQL 執行和需要遠端訪問 SQL 的執行,我們有兩種獨立的執行路徑。在此基礎之上,為了使分散式的執行更加高效,我們整個 SQL 引擎在 OLTP 上面做序列執行的時候會有自適應的策略。
我們的設計從來都是一個整體,對於 LSM-Tree 來說,合併是非常消耗資源的後臺任務,但是如果在分散式的部署場景下,我們發明了一種聰明的方法: 使得每臺機器的合併和它的服務可以錯開,我們稱之為“輪轉合併”,就是如果一個副本在提供服務就先不合並,我讓 follower 副本去做合併,這樣使得後臺的 LSM-Tree 合併對於前臺的操作在這臺機器上沒有影響。
▋ 單機分散式自適應的執行引擎如何提升分散式查詢效能
如果我沒有辦法最佳化業務來減少分散式 SQL,對於分散式 SQL 這部分我怎麼去執行?OceanBase 整體的 SQL 自適應執行引擎,分為序列執行和並行執行。
並行執行可以在單機內並行,這一點相對於一些開源的單機資料庫是有優勢的,早期的 MySQL 版本單機內並行是沒法做到的,又可以利用多機,如果一臺機器 CPU 還不夠,我可以把整個叢集的 CPU 用起來去做並行執行。序列執行我們就顯式地去區分了,它到底是一個大資料量的訪問,還是一個小資料量的訪問。
如果是一個小資料量的訪問,我們會把資料拉到本機來執行;如果是一個大資料量訪問,我們會把整個 SQL 的執行計劃下壓到那臺機器上去做資料過濾,整個過程是最佳化器自適應去選擇的。
▋ 兼顧單機和分散式的事務處理協議以提升事務效能
最後,事務是非常難做分散式最佳化的,OceanBase 在事務引擎方面有非常多的創新的專利。在這裡我介紹兩個點,下圖是分散式事務執行提交的流程,事務從整體上來看分成 “事務開啟”和“事務提交” 兩個關鍵操作。
第一,在“事務開啟”的階段,左側是其他的分散式資料庫典型的兩階段提交的過程。在開啟事務的時候,為了實現多版本的隔離,讀和寫互相不影響,在 MVCC 的場景下,它需要獲得一個全域性的快照——即當前哪些事務在操作,哪些事務已經提交了快照,對於很多分散式資料庫來說,這個快照的操作是非常大的開銷。
而 OceanBase 在這個階段做了最佳化,我們在很多場景下,OceanBase不需要訪問全域性的時間戳服務。我們創新地實現了一些對於 GTS 服務的最佳化,使得這部分的開銷是可擴充套件的。證明就是 TPC-C 測試,TPC-C 有 1500 個節點,1500 臺機器每秒處理 2000 多萬次事務(是事務並不是 SQL),但只有一個 GTS 服務節點,看起來好像這個 GTS 不容易擴充套件的,實際上我們最佳化後變得很容易擴充套件。
第二,在“事務提交”的階段, 對於提交的協議來說,大家可以看到左側兩階段的提交協議,傳統的兩階段提交協議需要寫四個階段的日誌,在參與者上要寫事務的日誌,在協調者上也需要記錄日誌,使得兩階段提交在容災的場景上是安全的。
OceanBase 在兩階段提交上做了一個非常創新的設計,OceanBase 的參與者是三副本、高可用的,所以並不擔心協調者的節點資料丟失,所以我們在參與者上不記日誌,這樣就節省了兩條日誌。第二,我們會在第一個階段就給應用返回成功,這是我們非常獨特的一個最佳化,使得整體的 roundtrip 少了一次。所以整體來說,即使在分散式事務場景下面,OceanBase 的分佈事務比其他的分散式資料庫有很大的優勢。
最後附上 OceanBase 與市場上幾款常見的分散式資料庫在 Sysbench 500 執行緒下的效能對比,這也就是全分散式場景下 “OceanBase 的低時延是什麼” 的最好呈現,我的分享就到這裡,謝謝大家!
歡迎訪問 OceanBase 官網獲取更多資訊:https://www.oceanbase.com/