MySQL分庫分表
MySQL處理大規模業務資料的方案一般都是分庫分表.
最開始一般都選擇垂直拆分.
比如電商網站,可能按照家電,圖書,母嬰等商品分類進行拆分.
這樣做的好處是拆分簡單,並且沒有破壞資料庫事務.
但是隨著業務的增長,比如圖書分類的訂單資料表已經到達了10個T的規模.
就需要考慮做水平拆分了.把邏輯上一個表的資料,分別存放到不同的資料庫伺服器.
水平拆分的好處是
多個資料庫伺服器分擔CPU,記憶體,網路頻寬的壓力.
多個資料庫伺服器分擔備份、恢復的壓力.
缺點是
破壞了原生的資料庫事務.如果使用分散式事務,則會拖累資料庫效能.
增加了運維管理的負擔.原來管一臺伺服器就行了,現在得管一堆伺服器.
水平拆分的三種主要方式
1.Hash拆分.比如按照 userId mod 64.將資料分佈在64個伺服器上
2.範圍拆分.比如每臺伺服器計劃存放一個億的資料,先將資料寫入伺服器A.一旦伺服器A寫滿,則將資料寫入伺服器B,以此類推.
這種方式的好處是擴充套件方便.資料在各個伺服器上分佈均勻.
3.路由表.自定義分佈方式.
呂海波老師SACC2015的內容.
用事務補償的方式,實現最終一致性.
下圖是水平拆分之後的結構. 假設使用者A向B轉賬100元.
由於水平拆分破壞了原有的事務.一個轉賬的業務,可能遇到如下的幾個情況.
第一種情況,應用寫佇列超時導致重發了訊息.那麼結果是A本來向B轉賬100元.結果卻轉賬了200元..
第二種情況,應用將訊息成功寫入佇列,但是佇列伺服器掛了.結果是A向B轉賬失敗.
第三種情況,中間層(佇列的消費者)將訊息取出,修改A的賬戶餘額,但是使用者A的庫掛了,導致事務失敗.結果是A向B轉賬失敗.
第四種情況,中間層已經成功修改了使用者A的賬戶餘額,但是在修改B使用者餘額的時候,使用者B的資料庫掛了。結果是使用者A的錢扣了,但是使用者B的錢沒有增加.
第五種情況.中間層從佇列拿到了訊息,但是還未及處理,中間層本身掛了..
最終一致性.
1.應用先將本次事務的業務日誌寫入業務日誌的資料庫,暫不提交
然後,向佇列傳送兩個訊息.一個訊息是使用者A -100元,另一個訊息是使用者B +100元.
確保兩個訊息都成功入隊,則提交業務日誌的事務,獲取全域性事務ID(tran_id).一旦有任何異常,回滾事務.
提交了事務,應用則可以直接返回.提示使用者交易完成.
2.中間層獲取訊息.先連線使用者A的資料庫.
查詢業務日誌表(tran_log),如果沒有該全域性事務ID,則不予處理.(確認有這個全域性事務,才處理)
查詢訊息日誌表(msg_log),如果存在記錄,則不予處理.(防止訊息超時重發)
然後,開始事務.
先update使用者A,減100元.
再寫訊息日誌表,記錄本次處理
最後提交事務.
3.中間層連線使用者B的資料庫,做相同的操作.
每隔5分鐘,檢查tran_log和msg_log.如果有不一致的情況,則進行事務補償.
呂老師說到這裡的時候,我覺得tran_log應該在如下的位置,然後作為各個底層庫的Master.
用MySQL非同步複製,將tran_log複製到使用者A、B所在的庫.
但是當面問呂老師,他說他們不是這麼弄的.因為這個tran_log的資料量也是非常巨大.
他們把tran_log放在了底層庫,但是我實在想不出來這樣怎麼弄.
可惜當時的環境也不容許我再刨根問底了.
不過留著自己琢磨,也挺有意思.
如果按照我的這個方式設計,後期問題會比較多,一個是tran_log資料量巨大.另外,tran_log所在的資料庫容易產生瓶頸.
最開始一般都選擇垂直拆分.
比如電商網站,可能按照家電,圖書,母嬰等商品分類進行拆分.
這樣做的好處是拆分簡單,並且沒有破壞資料庫事務.
但是隨著業務的增長,比如圖書分類的訂單資料表已經到達了10個T的規模.
就需要考慮做水平拆分了.把邏輯上一個表的資料,分別存放到不同的資料庫伺服器.
水平拆分的好處是
多個資料庫伺服器分擔CPU,記憶體,網路頻寬的壓力.
多個資料庫伺服器分擔備份、恢復的壓力.
缺點是
破壞了原生的資料庫事務.如果使用分散式事務,則會拖累資料庫效能.
增加了運維管理的負擔.原來管一臺伺服器就行了,現在得管一堆伺服器.
水平拆分的三種主要方式
1.Hash拆分.比如按照 userId mod 64.將資料分佈在64個伺服器上
2.範圍拆分.比如每臺伺服器計劃存放一個億的資料,先將資料寫入伺服器A.一旦伺服器A寫滿,則將資料寫入伺服器B,以此類推.
這種方式的好處是擴充套件方便.資料在各個伺服器上分佈均勻.
3.路由表.自定義分佈方式.
呂海波老師SACC2015的內容.
用事務補償的方式,實現最終一致性.
下圖是水平拆分之後的結構. 假設使用者A向B轉賬100元.
由於水平拆分破壞了原有的事務.一個轉賬的業務,可能遇到如下的幾個情況.
第一種情況,應用寫佇列超時導致重發了訊息.那麼結果是A本來向B轉賬100元.結果卻轉賬了200元..
第二種情況,應用將訊息成功寫入佇列,但是佇列伺服器掛了.結果是A向B轉賬失敗.
第三種情況,中間層(佇列的消費者)將訊息取出,修改A的賬戶餘額,但是使用者A的庫掛了,導致事務失敗.結果是A向B轉賬失敗.
第四種情況,中間層已經成功修改了使用者A的賬戶餘額,但是在修改B使用者餘額的時候,使用者B的資料庫掛了。結果是使用者A的錢扣了,但是使用者B的錢沒有增加.
第五種情況.中間層從佇列拿到了訊息,但是還未及處理,中間層本身掛了..
最終一致性.
1.應用先將本次事務的業務日誌寫入業務日誌的資料庫,暫不提交
然後,向佇列傳送兩個訊息.一個訊息是使用者A -100元,另一個訊息是使用者B +100元.
確保兩個訊息都成功入隊,則提交業務日誌的事務,獲取全域性事務ID(tran_id).一旦有任何異常,回滾事務.
提交了事務,應用則可以直接返回.提示使用者交易完成.
2.中間層獲取訊息.先連線使用者A的資料庫.
查詢業務日誌表(tran_log),如果沒有該全域性事務ID,則不予處理.(確認有這個全域性事務,才處理)
查詢訊息日誌表(msg_log),如果存在記錄,則不予處理.(防止訊息超時重發)
然後,開始事務.
先update使用者A,減100元.
再寫訊息日誌表,記錄本次處理
最後提交事務.
3.中間層連線使用者B的資料庫,做相同的操作.
每隔5分鐘,檢查tran_log和msg_log.如果有不一致的情況,則進行事務補償.
呂老師說到這裡的時候,我覺得tran_log應該在如下的位置,然後作為各個底層庫的Master.
用MySQL非同步複製,將tran_log複製到使用者A、B所在的庫.
但是當面問呂老師,他說他們不是這麼弄的.因為這個tran_log的資料量也是非常巨大.
他們把tran_log放在了底層庫,但是我實在想不出來這樣怎麼弄.
可惜當時的環境也不容許我再刨根問底了.
不過留著自己琢磨,也挺有意思.
如果按照我的這個方式設計,後期問題會比較多,一個是tran_log資料量巨大.另外,tran_log所在的資料庫容易產生瓶頸.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1819422/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [Mysql]分庫分表MySql
- Mysql分庫分表方案MySql
- 【Mysql】OneProxy分庫分表MySql
- 徹底搞清MySQL分庫分表(垂直分庫,垂直分表,水平分庫,水平分表)MySql
- 3.1 MYSQL分庫分表實踐MySql
- MySQL分庫分表的原則MySql
- MySQL全面瓦解28:分庫分表MySql
- Linux MySQL分庫分表之MycatLinuxMySql
- MySql分表、分庫、分片和分割槽MySql
- MySQL分庫分表總結參考MySql
- MYSQL效能最佳化分享(分庫分表)MySql
- MySQL 分庫分表方案,總結太全了。。MySql
- 分庫分表系列:分庫分表的前世今生
- 分庫分表
- MySQL 常用分庫分表方案,都在這裡了!MySql
- 分庫分表注意
- MySQL資料庫之分庫分表方案MySql資料庫
- 資料庫分庫分表資料庫
- Mysql分庫分表的主鍵生成演算法MySql演算法
- MySQL訂單分庫分表多維度查詢MySql
- mycat配置分庫分表
- Mycat分庫分表配置
- 分庫分表總結
- Mycat分庫分表(一)
- 常用分庫分表方案
- 基因法分庫分表
- MySQL 資料庫之網際網路常用分庫分表方案MySql資料庫
- [資料庫][分庫分表]分庫分表之後,id主鍵如何處理資料庫
- MySQL運維9-Mycat分庫分表之列舉分片MySql運維
- 使用淘寶中介軟體cobar實現mysql分庫分表MySql
- oracle分表效率,資料庫分庫分表是什麼,什麼情況下需要用分庫分表Oracle資料庫
- 徹底搞清分庫分表(垂直分庫,垂直分表,水平分庫,水平分表)
- MyCat分庫分表、讀寫分離
- Mycat 讀寫分離+分庫分表
- 讀寫分離 & 分庫分表 & 深度分頁
- 使用ShardingSphere-JDBC完成Mysql的分庫分表和讀寫分離JDBCMySql
- 輕鬆理解分庫分表
- 分庫分表插入資料