
分享嘉賓:王鵬飛 PingCAP 資深專家
編輯整理:張德通 數數科技
出品平台:DataFunTalk
導讀:本文將以點帶面地從現有的TiDB架構觸出發,為大家介紹如何設計新的雲原生分布式數據庫架構。
本文會圍繞下面三點展開:
對雲原生的樸素理解
對「雲原生數據庫」 架構設計理念與設計思路的思考
淺談逃生、容災與擴容
雲原生是一個比較新的概念,TiDB有在雲上為客戶提供PaaS服務的業務。客戶實際上需要的不是雲原生,客戶需要的是儘可能壓低使用服務的成本。這裡成本指的是綜合成本,不只是資源成本。
客戶想要的雲原生,其真正含義是:要業務資源有足夠彈性,一方面是按需計費,這個是技術上的彈性;另一方面由於客戶業務SLA不同、重要性也不同,客戶需要業務上有足夠靈活的選擇。
客戶還希望PaaS服務的列表價格能做到比雲服務提供商的服務器價格更便宜。而分布式數據庫會有很多消耗,做到比服務器價格更便宜很有難度。但價格做到比服務器價格更便宜才能收穫長尾客戶。
雲原生是藉助雲上基礎設施達成目標的手段。
作為第三方數據庫廠商,想要幫助客戶降低成本,只有通過利用雲廠商能里一個選項。
雲原生的數據庫一定是分布式的數據庫,因此後面所有談及雲原生數據庫的內容都是雲原生的分布式的數據庫。
與其講雲原生數據庫,不如反樸歸真,來談談分布式數據庫在雲上應有的表現吧。下面會以Pingcap的TiDB為例舉例說明。
上圖是TiDB的基本結構。TiDB進程從TiKV節點上獲取到數據,完成計算。TiDB進程是無狀態的進程,是負責計算的進程,可以連接任意TiKV節點。TiKV是有狀態的,事務相關的操作都是在TiKV層實現的。TiKV每個節點上存儲了哪些數據會被記錄在元數據中。TiKV節點之間通過Raft保證數據一致性。
這個架構中計算存儲分離的邊界是在TiDB和TiKV之間。TiDB與TiKV計算和存儲使用資源的比例並不固定。例如對計算要求不高而對存儲需求大的場景中(例如知乎),TiDB節點數不多,但TiKV節點數非常大;另一些用戶可能會要求計算和存儲節點數量要保持1:1的關係。
把TiDB放在公有雲上、讓TiDB作為公有雲服務的過程中,我們發現了TiDB的一些設計方面的局限性,即現有的TiDB、TiKV是面向IDC的設計而不是真正面向雲的設計。
專有雲和雲上的應⽤並不⼀樣。下面談2點雲上應用的優勢:
亞馬遜提供的塊存儲服務gp3雲盤其IOPS和容量不相關,解決了EBS(塊存儲)IOPS底的問題。這個功能讓雲上數據庫服務有了很大優化空間。亞馬遜的S3對象存儲服務價格非常便宜,它提供了11個9的數據持久性。
利用雲服務的能力,可以完全實現按需付費,按量計費。另外客戶也有根據業務場景定製可以使用的服務能力的需求,例如客戶需求是「我的訂單邏輯可以 100¥/h,但是收藏夾邏輯可以 10¥/h 嗎?」 ,可以通過雲服務進行定製。
多個VM連接同一塊雲盤,每個VM讀寫雲盤的性能和代價是一致的。前面提到的亞馬遜gp3能夠達到接近本地磁盤的效果,其數據持久性是3個9。可以認為gp3的表現和電腦上的普通磁盤存儲已經比較接近了,從這點看來,雲廠商在不斷試圖讓雲上服務達到「返祖」的效果。
既然提到「返祖」,那麼TiDB的架構演進上可不可以也「返祖」呢?我們來考慮一下把「存算分離」的邊界從TiDB-TiKV之間,移動到TiKV和持久化存儲之間。
這個考慮是基於,從任意節點訪問共享/遠程存儲的性能已經可以做到與訪問本地磁盤的消耗接近,意味着TiDB和TiKV都變成無狀態服務從技術上已經具備了可行性。
繼續對這個移動存算分離邊界的設計進行細化和質疑:
雲存儲服務用塊存儲EBS還是對象存儲S3?能不能讓成本更低?
TiDB/TiKV都已經被劃分到計算那一側了,也沒有狀態,分開還有意義嗎?分成兩個獨立服務有什麼好處?合併有什麼好處?這一點本次分享里不再討論,感興趣的同學可以繼續思考。
如果TiDB與TiKV合併,這個合併後的進程會負責寫文件,如何解決數據持久性問題、或者說如何不丟數據?寫多少份拷貝,3份、2份還是1份就夠?不同拷貝之間可不可以性能不同、可靠性可不可以不同(一般客戶對OLTP要求是約穩定越好)?能否在做拷貝時利用不同存儲(EBS/S3)的特性對服務取長補短、達到既要高可靠性也要儘可能降低成本的效果?
EBS優點是可以和本地磁盤性能媲美,但是價格更貴;S3是對象存儲,不能直接拿來和本地磁盤一樣使用,優點是吞吐量和容量幾乎無限、數據持久性是11個9,缺點是延遲高。雖然S3的讀延遲對於一些離線分析場景是可以接受的,但是OLTP場景下對延遲容忍度低,通常OLTP場景下需要在幾毫秒完成數據存取,顯然單獨用S3不能完全滿足需求,能否組合他們的優缺點達到目的?
EBS不能跨AZ,AWS整個可用區域全部不可用並不少見,而如果同時發生了用戶在其他AZ的機器也有故障,即使是用本地盤也會發生用戶數據丟失的事故。當一個AZ掛掉,會導致集群內數據要重新分布,集群也要補副本,這時客戶集群負載高,用戶體驗在這段時間不易保證,如何解決?
如何滿足客戶希望按不同應用場景的重要程度付費、且願意忍受因為預算減少帶來的使用體驗降低的場景需求?
如何設計架構,緊跟雲廠商存儲服務快速迭代的步伐?
根據提出的問題,我們對「雲原生分布式數據庫」的設計進行細化。
下圖中TiDB作為TiDB與TiKV合併後的進程,WAL是事務日誌。TiDB進程都來讀寫S3。
為了兼顧可靠性和價格,也為了防止AZ故障問題,我們選擇S3作為默認的存儲選項。當然不排除部分客戶更願意選擇EBS這類價格更高的存儲。
但S3存儲讀寫速度慢,同步讀寫會導致用戶體驗差,需要引入異步讀寫機制。異步讀寫的過程不與用戶讀寫的流程耦合。讀過程首選讀緩存內數據,儘量避免直接讀S3;寫過程是先寫入緩存,當條件合適時異步地把數據寫入S3。為了保持讀寫的高性能,緩存進程和TiDB進程應該部署在一起。
有了緩存,就意味着數據存儲了兩份,一份是緩存數據一份在S3中持久化存儲。OLTP數據庫的特徵是需要保持數據的持久性,在發生故障時可以恢復數據,因此要記錄事務日誌。當一個TiDB節點掛掉後,利用S3上持久化存儲的數據配合事務日誌就可以做到數據恢復。
事務日誌與S3上持久化存儲的數據不同,必須同步寫,其安全性需要得到保障。任何事務寫操作執行前,需要保障事務日誌寫成功。參考其他的關係型數據庫和分布式數據庫的實現是:在事務日誌寫成功、緩存更新完畢後,向用戶返回日誌寫成功的消息。日誌需要保障跨AZ可用。
有了跨AZ的事務日誌,S3存儲本身就可以跨區訪問的,數據非常安全,這時可以考慮只寫一份。
上面我們粗略地細化了「雲原生分布式數據庫」的設計,真正決定成敗的是細節,我們繼續打磨這個架構。
這個抽象已經幾乎完全利用到了雲存儲服務的所有優點。除非雲廠商可以提供比緩存性價比更高的服務,這個架構幾乎不會被動搖。
異步寫的操作讓任意吞吐量滿足要求的存儲介質都能夠成為持久化存儲,甚至可以使用磁帶機作為持久化存儲。但如果真的使用磁帶機,由於其讀性能很差,如果有緩存節點宕機,重新建立緩存的過程會非常漫長。但如果所有節點正常運行的情況下,是可以把使用磁帶機做持久化存儲作為極端情況考慮的。這個架構讓持久化存儲的下限可以接受磁帶機,上限可以是一種緩存。
這個架構也滿足了緊跟雲廠商步伐、可以快速迭代持久化存儲層存儲介質的需求,不論使用EBS還是哪一種新存儲都可以很方便地替換。
這個架構的風險點在於緩存擊穿。如果遇到緩存擊穿,查詢延遲會很高。但是這個問題可以轉化為商業問題解決:讓客戶選擇不同價位的服務,服務提供不同級別擊穿率保證。例如訂單和計費類業務購買100%不擊穿的服務,收藏夾類業務購買70%擊穿率服務、但是減少收費。
我們來考慮一下擊穿率,如果用戶要求0%擊穿率,其實現是緩存中多了一份數據拷貝。這時返回來看Cache選型,用戶可以選擇全部數據放在內存、追求極致速度,但內存價格更高。本地SSD的讀寫速度也足夠滿足緩存場景需求。甚至也可以考慮使用EBS、用EBS也能夠加快節點故障後恢復速度加。
使用緩存這個設計使系統失去了原有的TiDB與TiKV節點可以按任意比例配比的靈活性。但這個靈活性並不一定在所有場景下對客戶都非常重要,在這個架構中,客戶對於緩存命中率的需求比系統節點數配比的需求強烈更多。
關於存儲格式,如果迭代到上圖中這個架構模式,就不必須要KV格式存儲了。TiDB使用Percolator實現分布式事務,Percolator是基於KV實現的;而這個架構中,我們可以用更緊湊的方式實現事務。KV格式中,Value是一行數據,而我們可以把這一行數據設計得非常緊湊。當前其他KV引擎大多使用LSM-Tree數據結構實現,LSM-Tree在試圖用讀時開銷換取寫時的開銷。到底要用LSM-Tree組織數據還是用其他格式組織數據,需要根據客戶使用場景判斷、也要根據使用場景做針對性優化。在S3上的LSM-Tree做Compaction時,由於存算分離的架構、外加異步讀寫的設計,Compaction過程幾乎對主計算進程無影響。
在一些場景中,客戶會希望能夠分析到幾秒/幾分鐘之內的數據,但同時分析的操作量也很重。為了達到這種HTAP的效果,異步寫S3也可以考慮直接寫成列式存儲。LSM-Tree加列存加Compaction,在TiFlash讀數據時候控制好Checkpoint就可以達到實時讀數據的效果,為整個系統橫向擴展提供了可能。
TiDB和緩存合併後,在EKS和K8S存儲中會作為一個Pod部署。這時如果利用基於共享資源池的多租戶體系就可以實現順暢地實現超賣,而不需要在單一TiDB集群內做多租戶的邏輯。多租戶需要安全隔離、需要性能隔離,在進程級別做這兩項隔離的複雜度遠遠高於基於虛擬化實現多租戶。
這個新架構的分布式事務實現、數據分⽚、failover 流程、死鎖檢測、擴縮容等等,今天我們沒有討論。
1. 逃生
單 AZ 部署⽆論如何也解決不了 AZ 掛掉的問題,多 AZ 容災是必選。舊架構中(現有架構下),多AZ容災的實現是3份拷貝分別放到不同AZ內。如果客戶需要TiDB數量是N,為了實現容災,最終TiDB的機器數量是3N。改進後的架構使用的S3存儲本身就是跨AZ的服務,外加跨AZ的WAL(可以依靠Raft協議保證其一致性)。
假設⽀撐⽤戶業務需要 n 台服務器並⾏⼯作,使用新架構後不再需要購買3n台服務器做高可用,az1購買n台機器、az2購買m台機器、az3購買k台機器,其中 m,k ≤ n 且 m + k ≥ n,就能保證相當不錯的可⽤性。這個特性可以大幅降雲數據庫運營成本,同時降低用戶需要付出的費用。
有用戶需要具備跨 Region 逃生⽅案。Region1上需要一套系統、Region2也需要一套同樣的系統。如果使用現有的架構,實現起來代價很高很重;新架構能簡單的多地實現這個需求,直接通過事物日誌WAL做跨Region的複製。WAL複製其實現可以參考RDBMS的主從複製,不論是同步複製、半同步複製、完全異步複製都可以借鑑;也可以通過Raft協議直接向其他Region複製事務日誌。一旦事務日誌到達對應Region,計算進程就可以處理這些日誌並對數據做同步。
新架構大大降低了雲上數據庫逃生與容災的複雜度。
2.擴容
現有架構在業務高峰期時為了解決集群能力不足的問題擴容節點,此時擴容的結果可能很嚴重:
TiKV節點都很忙。
新增TiKV節點會導致數據重新分布。
在TiKV節點都很忙的情況下,有一個或多個節點因為數據重新分布宕機、需要重新分布的數據量增大,引發整個集群的雪崩。
現有架構下有什麼解決問題的辦法?
不搬遷數據,結果節點負載不會降低,不能根本上解決問題。
搬遷更少的數據,對整個集群的調度和性能監控系統考驗很大、難以實現。
能否在流量控制之下溫柔的搬遷數據?時間足夠的情況下可以,但線上問題救火的場景下很難有充足時間做這類操作。例如雙十一錯誤估計了負載,那麼此時留給技術人員做數據遷移的時間非常短。
集群負載高的情況下做停機擴容是業務上不能接受的。
要求⽤戶別在集群健康邊界內做擴容,但客戶可能會因為系統賬單和業務預估量不買單。
用上新架構後似乎可以更好地做擴容了:
首先數據都在S3上存儲,不再需要在節點之間搬遷數據。
擴容節點後新增的節點可從S3存儲中異步地把數據加載到緩存。這個操作不會對正在運行的節點造成任何影響。
緩存加載完成、事務日誌同步數據過程執行完成後,擴容的節點就可以正常工作。雖然事務日誌同步數據的過程需要占用WAL集群的IO,但WAL系統資源開銷單一、性能消耗也更容易預測,可控性方面相比於直接控制TiKV集群好很多。
新提出的架構對非雲客戶有幫助嗎?是的。
新架構可以用HDFS替換S3作為持久化存儲、也可以根據客戶定製化需求和定製化硬件方便地進行改造。新架構不僅能根據不同場景提升用戶對延遲的要求,也可以大幅提升整個系統性能。比如激活了HDFS EC功能後只需要存1.5份空間的數據即可保證數據可靠性,相比於傳統的3副本,在空間上減少了很多。
這個新架構並沒有實際落地,落地過程中的細節決定了整個雲原生分布式數據庫能否成功。
今天的分享就到這裡,謝謝大家。
在文末分享、點讚、在看,給個3連擊唄~
分享嘉賓:
福利時刻
《大數據典藏版合集》電子書目錄如上,感興趣的小夥伴,歡迎識別二維碼,添加小助手微信,回復『大數據典藏版合集』,即可下載。
關於我們:
🧐分享、點讚、在看,給個3連擊唄!👇