MySQL9-可擴展性設計之數據切分

何謂數據切分

簡單來說,就是指通過某種特定的條件,將我們存放在同一個數據庫中的數據分散存放到多個數據庫(主機)上面,以達到分散單臺設備負載的效果。數據的切分同時還可以提高系統的總體可用性,因爲單臺設備Crash 之後,只有總體數據的某部分不可用,而不是所有的數據。

數據的切分(Sharding)根據其切分規則的類型,可以分爲兩種切分模式:一種是按照不同的表(或者Schema)來切分到不同的數據庫(主機)之上,這種切可以稱之爲數據的垂直(縱向)切分;另外一種則是根據表中的數據的邏輯關係,將同一個表中的數據按照某種條件拆分到多臺數據庫(主機)上面,這種切分稱之爲數據的水平(橫向)切分。

垂直切分的最大特點就是規則簡單,實施也更爲方便,尤其適合各業務之間的耦合度非常低,相互影響很小,業務邏輯非常清晰的系統。在這種系統中,可以很容易做到將不同業務模塊所使用的表分拆到不同的數據庫中。根據不同的表來進行拆分,對應用程序的影響也更小,拆分規則也會比較簡單清晰。

水平切分於垂直切分相比,相對來說稍微複雜一些。因爲要將同一個表中的不同數據拆分到不同的數據庫中,對於應用程序來說,拆分規則本身就較根據表名來拆分更爲複雜,後期的數據維護也會更爲複雜一些。

數據的垂直切分

一個架構設計較好的應用系統,其總體功能肯定是由很多個功能模塊所組成的,而每一個功能模塊所需要的數據對應到數據庫中就是一個或者多個表。而在架構設計中,各個功能模塊相互之間的交互點越統一越少,系統的耦合度就越低,系統各個模塊的維護性以及擴展性也就越好。這樣的系統,實現數據的垂直切分也就越容易。

當我們的功能模塊越清晰,耦合度越低,數據垂直切分的規則定義也就越容易。完全可以根據功能模塊來進行數據的切分,不同功能模塊的數據存放於不同的數據庫主機中,可以很容易就避免掉跨數據庫的Join 存在,同時系統架構也非常的清晰。

當然,很難有系統能夠做到所有功能模塊所使用的表完全獨立,完全不需要訪問對方的表或者需要兩個模塊的表進行Join 操作。這種情況下,我們就必須根據實際的應用場景進行評估權衡。決定是遷就應用程序將需要Join 的表的相關某快都存放在同一個數據庫中,還是讓應用程序做更多的事情,也就是程序完全通過模塊接口取得不同數據庫中的數據,然後在程序中完成Join 操作。

垂直切分的優點

◆ 數據庫的拆分簡單明瞭,拆分規則明確;

◆ 應用程序模塊清晰明確,整合容易;

◆ 數據維護方便易行,容易定位;

垂直切分的缺點

◆ 部分表關聯無法在數據庫級別完成,需要在程序中完成;

◆ 對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不一定能滿足要求;

◆ 事務處理相對更爲複雜;

◆ 切分達到一定程度之後,擴展性會遇到限制;

◆ 過讀切分可能會帶來系統過渡複雜而難以維護。

數據的水平切分

簡單來說,我們可以將數據的水平切分理解爲是按照數據行的切分,就是將表中的某些行切分到一個數據庫,而另外的某些行又切分到其他的數據庫中。當然,爲了能夠比較容易的判定各行數據被切分到哪個數據庫中了,切分總是都需要按照某種特定的規則來進行的。如根據某個數字類型字段基於特定數目取模,某個時間類型字段的範圍,或者是某個字符類型字段的hash 值。如果整個系統中大部分核心表都可以通過某個字段來進行關聯,那這個字段自然是一個進行水平分區的上上之選了,當然,非常特殊無法使用就只能另選其他了。

水平切分的優點

◆ 表關聯基本能夠在數據庫端全部完成;

◆ 不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;

◆ 應用程序端整體架構改動相對較少;

◆ 事務處理相對簡單;

◆ 只要切分規則能夠定義好,基本上較難遇到擴展性限制;

水平切分的缺點

◆ 切分規則相對更爲複雜,很難抽象出一個能夠滿足整個數據庫的切分規則;

◆ 後期數據的維護難度有所增加,人爲手工定位數據更困難;

◆ 應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分造成一定的困難。

垂直與水平聯合切分的使用

聯合切分的優點

◆ 可以充分利用垂直切分和水平切分各自的優勢而避免各自的缺陷;

◆ 讓系統擴展性得到最大化提升;

聯合切分的缺點

◆ 數據庫系統架構比較複雜,維護難度更大;

◆ 應用程序架構也相對更復雜;

數據切分及整合方案

總的來說,存在兩種解決思路:

1. 在每個應用程序模塊中配置管理自己需要的一個(或者多個)數據源,直接訪問各個數據庫,在模塊內完成數據的整合;

2. 通過中間代理層來統一管理所有的數據源,後端數據庫集羣對前端應用程序透明;

可能90%以上的人在面對上面這兩種解決思路的時候都會傾向於選擇第二種,尤其是系統不斷變得龐大複雜的時候。確實,這是一個非常正確的選擇,雖然短期內需要付出的成本可能會相對更大一些,但是對整個系統的擴展性來說,是非常有幫助的。

①自行開發中間代理層。

②利用MySQL Proxy 實現數據切分及整合。

③利用Amoeba 實現數據切分及整合。

④利用HiveDB 實現數據切分及整合

⑤其他實現數據切分及整合的解決方案

數據切分與整合中可能存在的問題

問題:引入分佈式事務的問題

在MySQL 各個版本中,只有從MySQL 5.0 開始以後的各個版本纔開始對分佈式事務提供支持,而且目前僅有Innodb 提供分佈式事務支持。不僅如此,即使我們剛好使用了支持分佈式事務的MySQL 版本,同時也是使用的Innodb 存儲引擎,分佈式事務本身對於系統資源的消耗就是很大的,性能本身也並不是太高。而且引入分佈式事務本身在異常處理方面就會帶來較多比較難控制的因素。

其實我們可以可以通過一個變通的方法來解決這種問題,首先需要考慮的一件事情就是:是否數據庫是唯一一個能夠解決事務的地方呢?其實並不是這樣的,我們完全可以結合數據庫以及應用程序兩者來共同解決。各個數據庫解決自己身上的事務,然後通過應用程序來控制多個數據庫上面的事務。也就是說,只要我們願意,完全可以將一個跨多個數據庫的分佈式事務分拆成多個僅處於單個數據庫上面的小事務,並通過應用程序來總控各個小事務。當然,這樣作的要求就是我們的應用程序必須要有足夠的健壯性,當然也會給應用程序帶來一些技術難度。

問題:跨節點Join 的問題

對待這類問題,我還是推薦通過應用程序來進行處理,在驅動表所在的MySQL Server中取出相應的驅動結果集,然後根據驅動結果集再到被驅動表所在的MySQL Server 中取出相應的數據。可能很多讀者朋友會認爲這樣做對性能會產生一定的影響,是的,確實是會對性能有一定的負面影響,但是除了此法,基本上沒有太多其他更好的解決辦法了。而且,由於數據庫通過較好的擴展之後,每臺MySQL Server 的負載就可以得到較好的控制,單純針對單條Query 來說,其響應時間可能比不切分之前要提高一些,所以性能方面所帶來的負面影響也並不是太大。更何況,類似於這種需要跨節點Join 的需求也並不是太多,相對於總體性能而言,可能也只是很小一部分而已。所以爲了整體性能的考慮,偶爾犧牲那麼一點點,其實是值得的,畢竟系統優化本身就是存在很多取捨和平衡的過程。

問題:跨節點合併排序分頁問題

如何解決?解決的思路大體上和跨節點Join 的解決類似,但是有一點和跨節點Join不太一樣,Join 很多時候都有一個驅動與被驅動的關係,所以Join 本身涉及到的多個表之間的數據讀取一般都會存在一個順序關係。但是排序分頁就不太一樣了,排序分頁的數據源基本上可以說是一個表(或者一個結果集),本身並不存在一個順序關係,所以在從多個數據源取數據的過程是完全可以並行的。這樣,排序分頁數據的取數效率我們可以做的比跨庫Join 更高,所以帶來的性能損失相對的要更小,在有些情況下可能比在原來未進行數據切分的數據庫中效率更高了。當然,不論是跨節點Join 還是跨節點排序分頁,都會使我們的應用服務器消耗更多的資源,尤其是內存資源,因爲我們在讀取訪問以及合併結果集的這個過程需要比原來處理更多的數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章