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所在的資料庫容易產生瓶頸.
mysql分表分庫實現 MySql分表分庫思路
一.資料庫瓶頸 1.1io瓶頸 第一種 磁碟讀io瓶頸,熱點資料太多,資料庫快取放不下,每次查詢時會產生大量的io 分庫和垂直分表 第二種 網路io瓶頸,請求的資料太多,網路頻寬不夠 分庫 1.2cpu瓶頸 第一種 sql問題,如sql中包含join,group by,order by,非索引字段條...
MySQL範圍分表分庫 mysql 分表分庫策略
唯一id的生成 下面列舉幾種常見的唯一id生成方案,需要滿足兩大核心需求 1.全域性唯一 2趨勢有序 1.用資料庫的auto increment 自增id 來生成,每次通過寫入資料庫一條記錄,利用資料庫id自增的特性獲取唯一,有序的id。優點 使用資料庫原有的功能,相對簡單 能夠保證唯一 能夠保證遞...
mysql 分庫分表實戰 MySQL分庫分表實戰
為什麼要分庫分表 在大型 中,當使用者量以及使用者產生的業務資料量達到單庫單錶效能極限時,為了支撐業務可持續發展,對於重要的核心業務必然要進行分庫分表來儲存業務資料。對於非核心業務產生的大量資料,例如爬蟲爬取的資訊,論壇產生的資料等,可以考慮把資料儲存在像mongodb這樣的nosql儲存裡面,這些...