當前位置:
首頁 > 最新 > 資料庫的服務化切分

資料庫的服務化切分

本文是微服務入門系列的第二篇文章,本系列一共有如下內容:

《走進微服務的世界》

《微服務架構下的分散式事務基礎入門》

《微服務架構下的分散式事務解決方案》

《資料庫的服務化切分》

《服務部署》


1. 什麼是「分庫分表」?

隨著大數據時代的到來,業務系統的數據量日益增大,數據存儲能力逐漸成為影響系統性能的瓶頸。目前主流的關係型資料庫單表存儲上限為1000萬條記錄,而這一存儲能力顯然已經無法滿足大數據背景下的業務系統存儲要求了。隨著微服務架構、分散式存儲等概念的出現,數據存儲問題也漸漸迎來了轉機。而數據分片是目前解決海量數據持久化存儲與高效查詢的一種重要手段。數據分庫分表的過程在系統設計階段完成,要求系統設計人員根據系統預期的業務量,將未來可能出現瓶頸的資料庫、數據表按照一定規則拆分成多個庫、多張表。這些資料庫和數據表需要部署在不同的伺服器上,從而將數據讀寫壓力分攤至集群中的各個節點,提升資料庫整體處理能力,避免出現讀寫瓶頸的現象。

目前數據分片的方式一共有兩種:離散分片和連續分片。

離散分片是按照數據的某一欄位哈希取模後進行分片存儲。只要哈希演算法選擇得當,數據就會均勻地分布在不同的分片中,從而將讀寫壓力平均分配給所有分片,整體上提升數據的讀寫能力。然而,離散存儲要求數據之間有較強的獨立性,但實際業務系統並非如此,不同分片之間的數據往往存在一定的關聯性,因此在某些場景下需要跨分片連接查詢。由於目前所有的關係型資料庫出於安全性考慮,均不支持跨庫連接。因此,跨庫操作需要由數據分庫分表中間件來完成,這極大影響數據的查詢效率。此外,當數據存儲能力出現瓶頸需要擴容時,離散分片規則需要將所有數據重新進行哈希取模運算,這無疑成為限制系統可擴展性的一個重要因素。雖然,一致性哈希能在一定程度上減少系統擴容時的數據遷移,但數據遷移問題仍然不可避免。對於一個已經上線運行的系統而言,系統停止對外服務進行數據遷移的代價太大。

第二種數據分片的方式即為連續分片,它能解決系統擴容時產生的數據遷移問題。這種方式要求數據按照時間或連續自增主鍵連續存儲。從而一段時間內的數據或相鄰主鍵的數據會被存儲在同一個分片中。當需要增加分片時,不會影響現有的分片。因此,連續分片能解決擴容所帶來的數據遷移問題。但是,數據的存儲時間和讀寫頻率往往呈正比,也就是大量的讀寫往往都集中在最新存儲的那一部分數據,這就會導致熱點問題,並不能起到分攤讀寫壓力的初衷。


資料庫擴展一共有四種分配方式,分別是:垂直分庫、垂直分表、水平分表、水平數據分片。每一種策略都有各自的適用場景。

垂直分庫

垂直分庫即是將一個完整的資料庫根據業務功能拆分成多個獨立的資料庫,這些資料庫可以運行在不同的伺服器上,從而提升資料庫整體的數據讀寫性能。這種方式在微服務架構中非常常用。微服務架構的核心思想是將一個完整的應用按照業務功能拆分成多個可獨立運行的子系統,這些子系統稱為「微服務」,各個服務之間通過RPC介面通信,這樣的結構使得系統耦合度更低、更易於擴展。垂直分庫的理念與微服務的理念不謀而合,可以將原本完整的數據按照微服務拆分系統的方式,拆分成多個獨立的資料庫,使得每個微服務系統都有各自獨立的資料庫,從而可以避免單個資料庫節點壓力過大,影響系統的整體性能,如下圖所示。

title

垂直分表

垂直分表如果一張表的欄位非常多,那麼很有可能會引起數據的跨頁存儲,這會造成資料庫額外的性能開銷,而垂直分表可以解決這個問題。垂直分表就是將一張表中不常用的欄位拆分到另一張表中,從而保證第一章表中的欄位較少,避免出現資料庫跨頁存儲的問題,從而提升查詢效率。而另一張表中的數據通過外鍵與第一張表進行關聯,如下圖所示。

title

水平分表

如果一張表中的記錄數過多(超過1000萬條記錄),那麼會對資料庫的讀寫性能產生較大的影響,雖然此時仍然能夠正確地讀寫,但讀寫的速度已經到了業務無法忍受的地步,此時就需要使用水平分表來解決這個問題。水平分表是將一張含有很多記錄數的表水平切分,拆分成幾張結構相同的表。舉個例子,假設一張訂單表目前存儲了2000萬條訂單的數據,導致數據讀寫效率極低。此時可以採用水平分表的方式,將訂單表拆分成100張結構相同的訂單表,分別叫做order_1、order_2……、order_100。然後可以根據訂單所屬用戶的id進行哈希取模後均勻地存儲在這100張表中,從而每張表中只存儲了20萬條訂單記錄,極大提升了訂單的讀寫效率,如下圖所示。

當然,如果拆分出來的表都存儲在同一個資料庫節點上,那麼當請求量過大的時候,畢竟單台伺服器的處理能力是有限的,資料庫仍然會成為系統的瓶頸,所以為了解決這個問題,就出現了水平數據分片的解決方案。

title

水平分庫分表

水平數據分片與數據分片區別在於:水平數據分片首先將數據表進行水平拆分,然後按照某一分片規則存儲在多台資料庫伺服器上。從而將單庫的壓力分攤到了多庫上,從而避免因為資料庫硬體資源有限導致的資料庫性能瓶頸,如下圖所示。

title


目前常用的數據分片策略有兩種,分別是連續分片和離散分片。

離散分片

離散分片是指將數據打散之後均勻地存儲在邏輯表的各個分片中,從而使的對同一張邏輯表的數據讀取操作均勻地落在不同庫的不同表上,從而提高讀寫速度。離散分片一般以哈希取模的方式實現。比如:一張邏輯表有4個分片,那麼在讀寫數據的時候,中間件首先會取得分片欄位的哈希值,然後再模以4,從而計算出該條記錄所在的分片。在這種方法中,只要哈希演算法選的好,那麼數據分片將會比較均勻,從而數據讀寫就會比較均勻地落在各個分片上,從而就有較高的讀寫效率。但是,這種方式也存在一個最大的缺陷——資料庫擴容成本較高。採用這種方式,如果需要再增加分片,原先的分片演算法將失效,並且所有記錄都需要重新計算所在分片的位置。對於一個已經上線的系統來說,行級別的數據遷移成本相當高,而且由於數據遷移期間系統仍在運行,仍有新數據產生,從而無法保證遷移過程數據的一致性。如果為了避免這個問題而停機遷移,那必然會對業務造成巨大影響。當然,如果為了避免數據遷移,在一開始的時候就分片較多的分片,那需要承擔較高的費用,這對於中小公司來說是無法承受的。

連續分片

連續分片指的是按照某一種分片規則,將某一個區間內的數據存儲在同一個分片上。比如按照時間分片,每個月生成一張物理表。那麼在讀寫數據時,直接根據當前時間就可以找到數據所在的分片。再比如可以按照記錄ID分片,這種分片方式要求ID需要連續遞增。由於Mysql資料庫單表支持最大的記錄數約為1000萬,因此我們可以根據記錄的ID,使得每個分片存儲1000萬條記錄,當目前的記錄數即將到達存儲上限時,我們只需增加分片即可,原有的數據無需遷移。連續分片的一個最大好處就是方便擴容,因為它不需要任何的數據遷移。但是,連續分片有個最大的缺點就是熱點問題。連續分片使得新插入的數據集中在同一個分片上,而往往新插入的數據讀寫頻率較高,因此,讀寫操作都會集中在最新的分片上,從而無法體現數據分片的優勢。


跨庫操作

在關係型資料庫中,多張表之間往往存在關聯,我們在開發過程中需要使用JOIN操作進行多表連接。但是當我們使用了分庫分表模式後,由於資料庫廠商處於安全考慮,不允許跨庫JOIN操作,從而如果需要連接的兩張表被分到不同的庫中後,就無法使用SQL提供的JOIN關鍵字來實現表連接,我們可能需要在業務系統層面,通過多次SQL查詢,完成數據的組裝和拼接。這一方面會增加業務系統的複雜度,另一方面會增加業務系統的負載。

因此,當我們使用分庫分表模式時,需要根據具體的業務場景,合理地設置分片策略、設置分片欄位,這將會在本文的後續章節中介紹。

分散式事務

我們知道,資料庫提供了事務的功能,以保證數據一致性。然而,這種事務只是針對單資料庫而言的,資料庫廠商並未提供跨庫事務。因此,當我們使用了分庫分表之後,就需要我們在業務系統層面實現分散式事務。關於分散式事務的詳細內容,可以參考筆者的另一篇文章《常用的分散式事務解決方案》。


Cobar實現資料庫的透明分庫,讓開發人員能夠在無感知的情況下操縱資料庫集群,從而簡化資料庫的編程模型。然而Cobar僅實現了分庫功能,並未實現分表功能。分庫可以解決單庫IO、CPU、內存的瓶頸,但無法解決單表數據量過大的問題。此外,Cobar是一個獨立運行的系統,它處在應用系統與資料庫系統之間,因此增加了額外的部署複雜度,增加了運維成本。

為了解決上述問題,Cobar還推出了一個Cobar-Client項目,它只是一個安裝在應用程序的Jar包,並不是一個獨立運行的系統,一定程度上降低了系統的複雜度。但和Cobar一樣,仍然只支持分庫,並不支持分表,也不支持讀寫分離。

MyCat是基於Cobar二次開發的資料庫中間件,和Cobar相比,它增加了讀寫分離的功能,並修復了Cobar的一些bug。但是,MyCat和Cobar一樣,都是一套需要獨立部署的系統,因此會增加部署的複雜度,提高了後期系統運維的成本。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 大閑人柴毛毛 的精彩文章:

TAG:大閑人柴毛毛 |