1、 使用Spring AOP實現MySQL數據庫讀寫分離案例分析:
http://blog.csdn.net/xlgen157387/article/details/53930382
2、MySQL5.6 數據庫主從(Master/Slave)同步安裝與配置詳解:
http://blog.csdn.net/xlgen157387/article/details/51331244
3、MySQL主從復制的常見拓撲、原理分析以及如何提高主從復制的效率總結:
http://blog.csdn.net/xlgen157387/article/details/52451613
4、使用mysqlreplicate命令快速搭建 Mysql 主從復制:
http://blog.csdn.net/xlgen157387/article/details/52452394
5、大型網站應用之海量數據和高并發(fā)解決方案總結一二:
隨著業(yè)務規(guī)模的不斷擴大,需要選擇合適的方案去應對數據規(guī)模的增長,以應對逐漸增長的訪問壓力和數據量。
關于數據庫的擴展主要包括:業(yè)務拆分、主從復制,數據庫分庫與分表。這篇文章主要講述數據庫分庫與分表
(1)業(yè)務拆分
在 大型網站應用之海量數據和高并發(fā)解決方案總結一二 一篇文章中也具體講述了為什么要對業(yè)務進行拆分。
業(yè)務起步初始,為了加快應用上線和快速迭代,很多應用都采用集中式的架構。隨著業(yè)務系統(tǒng)的擴大,系統(tǒng)變得越來越復雜,越來越難以維護,開發(fā)效率變得越來越低,并且對資源的消耗也變得越來越大,通過硬件提高系統(tǒng)性能的方式帶來的成本也越來越高。
因此,在選型初期,一個優(yōu)良的架構設計是后期系統(tǒng)進行擴展的重要保障。
例如:電商平臺,包含了用戶、商品、評價、訂單等幾大模塊,最簡單的做法就是在一個數據庫中分別創(chuàng)建users、shops、comment、order四張表。
但是,隨著業(yè)務規(guī)模的增大,訪問量的增大,我們不得不對業(yè)務進行拆分。每一個模塊都使用單獨的數據庫來進行存儲,不同的業(yè)務訪問不同的數據庫,將原本對一個數據庫的依賴拆分為對4個數據庫的依賴,這樣的話就變成了4個數據庫同時承擔壓力,系統(tǒng)的吞吐量自然就提高了。
(2)主從復制
1、MySQL5.6 數據庫主從(Master/Slave)同步安裝與配置詳解
2、MySQL主從復制的常見拓撲、原理分析以及如何提高主從復制的效率總結
3、使用mysqlreplicate命令快速搭建 Mysql 主從復制
上述三篇文章中,講述了如何配置主從數據庫,以及如何實現數據庫的讀寫分離,這里不再贅述,有需要的選擇性點擊查看。
上圖是網上的一張關于MySQL的Master和Slave之間數據同步的過程圖。
主要講述了MySQL主從復制的原理:數據復制的實際就是Slave從Master獲取Binary log文件,然后再本地鏡像的執(zhí)行日志中記錄的操作。由于主從復制的過程是異步的,因此Slave和Master之間的數據有可能存在延遲的現象,此時只能保證數據最終的一致性。
(3)數據庫分庫與分表
我們知道每臺機器無論配置多么好它都有自身的物理上限,所以當我們應用已經能觸及或遠遠超出單臺機器的某個上限的時候,我們惟有尋找別的機器的幫助或者繼續(xù)升級的我們的硬件,但常見的方案還是通過添加更多的機器來共同承擔壓力。
我們還得考慮當我們的業(yè)務邏輯不斷增長,我們的機器能不能通過線性增長就能滿足需求?因此,使用數據庫的分庫分表,能夠立竿見影的提升系統(tǒng)的性能,關于為什么要使用數據庫的分庫分表的其他原因這里不再贅述,主要講具體的實現策略。請看下邊章節(jié)。
關鍵字:用戶ID、表容量
對于大部分數據庫的設計和業(yè)務的操作基本都與用戶的ID相關,因此使用用戶ID是最常用的分庫的路由策略。用戶的ID可以作為貫穿整個系統(tǒng)用的重要字段。因此,使用用戶的ID我們不僅可以方便我們的查詢,還可以將數據平均的分配到不同的數據庫中。(當然,還可以根據類別等進行分表操作,分表的路由策略還有很多方式)
接著上述電商平臺假設,訂單表order存放用戶的訂單數據,sql腳本如下(只是為了演示,省略部分細節(jié)):
當數據比較大的時候,對數據進行分表操作,首先要確定需要將數據平均分配到多少張表中,也就是:表容量。
這里假設有100張表進行存儲,則我們在進行存儲數據的時候,首先對用戶ID進行取模操作,根據
user_id%100
獲取對應的表進行存儲查詢操作,示意圖如下:
例如,
user_id = 101
那么,我們在獲取值的時候的操作,可以通過下邊的sql語句:
其中,
order_1
是根據
101%100
計算所得,表示分表之后的第一章order表。
注意:
在實際的開發(fā)中,如果你使用MyBatis做持久層的話,MyBatis已經提供了很好得支持數據庫分表的功能,例如上述sql用MyBatis實現的話應該是:
接口定義:
xml配置映射文件:
其中${tableNum}含義是直接讓參數加入到sql中,這是MyBatis支持的特性。
注意:
另外,在實際的開發(fā)中,我們的用戶ID更多的可能是通過UUID生成的,這樣的話,
我們可以首先將UUID進行hash獲取到整數值,然后在進行取模操作。
數據庫分表能夠解決單表數據量很大的時候數據查詢的效率問題,但是無法給數據庫的并發(fā)操作帶來效率上的提高,因為分表的實質還是在一個數據庫上進行的操作,很容易受數據庫IO性能的限制。
因此,如何將數據庫IO性能的問題平均分配出來,很顯然將數據進行分庫操作可以很好地解決單臺數據庫的性能問題。
分庫策略與分表策略的實現很相似,最簡單的都是可以通過取模的方式進行路由。
還是上例,將用戶ID進行取模操作,這樣的話獲取到具體的某一個數據庫,同樣關鍵字有:
用戶ID、庫容量
路由的示意圖如下:
上圖中庫容量為100。
同樣,如果用戶ID為UUID請先hash然后在進行取模。
上述的配置中,數據庫分表可以解決單表海量數據的查詢性能問題,分庫可以解決單臺數據庫的并發(fā)訪問壓力問題。
有時候,我們需要同時考慮這兩個問題,因此,我們既需要對單表進行分表操作,還需要進行分庫操作,以便同時擴展系統(tǒng)的并發(fā)處理能力和提升單表的查詢性能,就是我們使用到的分庫分表。
分庫分表的策略相對于前邊兩種復雜一些,一種常見的路由策略如下:
1、中間變量 = user_id%(庫數量*每個庫的表數量);
2、庫序號?。健∪≌ㄖ虚g變量/每個庫的表數量);
3、表序號 = 中間變量%每個庫的表數量;
例如:數據庫有256 個,每一個庫中有1024個數據表,用戶的user_id=262145,按照上述的路由策略,可得:
1、中間變量 = 262145%(256*1024)= 1;
2、庫序號 = 取整(1/1024)= 0;
3、表序號?。健?%1024 = 1;
這樣的話,對于user_id=262145,將被路由到第0個數據庫的第1個表中。
示意圖如下:
關于分庫分表策略的選擇有很多種,上文中根據用戶ID應該是比較簡單的一種。其他方式比如使用號段進行分區(qū)或者直接使用hash進行路由等。有興趣的可以自行查找學習。
關于上文中提到的,如果用戶的ID是通過UUID的方式生成的話,我們需要單獨的進行一次hash操作,然后在進行取模操作等,其實hash本身就是一種分庫分表的策略,使用hash進行路由策略的時候,我們需要知道的是,也就是hash路由策略的優(yōu)缺點,優(yōu)點是:數據分布均勻;缺點是:數據遷移的時候麻煩,不能按照機器性能分攤數據。
上述的分庫和分表操作,查詢性能和并發(fā)能力都得到了提高,但是還有一些需要注意的就是,例如:原本跨表的事物變成了分布式事物;由于記錄被切分到不同的數據庫和不同的數據表中,難以進行多表關聯查詢,并且不能不指定路由字段對數據進行查詢。分庫分表之后,如果我們需要對系統(tǒng)進行進一步的擴陣容(路由策略變更),將變得非常不方便,需要我們重新進行數據遷移。
最后需要指出的是,分庫分表目前有很多的中間件可供選擇,最常見的是使用淘寶的中間件Cobar。
GitHub地址:https://github.com/alibaba/cobara
文檔地址為:https://github.com/alibaba/cobar/wiki
關于淘寶的中間件Cobar本篇內容不具體介紹,會在后邊的學習中在做介紹。
另外Spring也可以實現數據庫的讀寫分離操作,后邊的文章,會進一步學習。
上述中,我們學到了如何進行數據庫的讀寫分離和分庫分表,那么,是不是可以實現一個可擴展、高性能、高并發(fā)的網站那?很顯然還不可以!一個大型的網站使用到的技術遠不止這些,可以說,這些都是其中的最基礎的一個環(huán)節(jié),因為還有很多具體的細節(jié)我們沒有掌握到,比如:數據庫的集群控制,集群的負載均衡,災難恢復,故障自動切換,事務管理等等技術。因此,還有很多需要去學習去研究的地方。
總之:
前方道路美好而光明,2017年新征程!
Java后端技術QQ群,群文件分享大量學習資料,歡迎加群下載: 586855725,歡迎加入
聯系客服