一般業界,對訂單資料的分庫分表,有兩類思路:按照訂單號來切分、按照使用者id來切分。
方案一、按照訂單號來做 hash分散訂單資料
把訂單號看作是乙個字串,做 hash,分散到多個伺服器去。
具體到哪個庫、哪個表儲存資料呢?訂單號裡面的數字來記錄著。
如果要查詢某使用者的所有訂單呢?
由於是根據訂單號來分散資料的。他的訂單分散在了多個庫、多個表中。
總不能去所有的庫,所有的表掃瞄吧。這樣效率很低。
解決:維護uid和oid的關係表, 此表可以作為快取,當資料量增大時此關係表也要進行分表。
一般使用方案二的比較多,乙個使用者的所有訂單,都在一張表裡面,那麼做分頁展示的時候,就容易。
方案二、按照使用者 id 打散訂單資料
以uid來切分資料,有兩種思路:
第一種是,某個範圍的uid訂單到哪些庫。0到2千萬uid,對應的訂單資料到a庫、a表。2千萬到4千萬對應的訂單到b庫。
為什麼這種方案用得比較少呢?
容易出現瓶頸嗎。某個範圍內的使用者,下單量比較多,那麼造成這個庫的壓力特別大。其他庫卻沒什麼壓力。
第二種是,使用uid取模運算。第二種方案業界用得比較多。
一方面、處理簡單,程式上做取模運算就好了。
另一方面、使用取模的方式,資料比較均勻分散到多個庫去了。不容易出現單個庫效能瓶頸。
但是不好處也有:即要擴容的時候,比較麻煩。就需要遷移資料了。
要擴容的時候,為了減少遷移的資料量,一般擴容是以倍數的形式增加。比如原來是8個庫,擴容的時候,就要增加到16個庫,再次擴容,就增加到32個庫。這樣遷移的資料量,就小很多了。這個問題不算很大問題,畢竟一次擴容,可以保證比較長的時間,而且使用倍數增加的方式,已經減少了資料遷移量。
下面分析一下按照使用者id取模的方式分庫分表。
按照使用者id作為key來切分訂單資料,具體如下:
1、 庫名稱定位:使用者id末尾4位 mod 32。
mod表示除以乙個數後,取餘下的數。比如除以32後,餘下8,餘數就是8。
**符號是用%表示:15%4=3。
2、表名稱定位:(使用者id末尾4位 dev 32) mod 32。
dev表示除以乙個數,取結果的整數。比如得到結果是25.6,取整就是25。
**用/來表示:$get_int = floor(15/4)。15除以4,是乙個小數3.75,向下取整就是3。一定是向下取整,向上取整就變成了4了。
按照上面的規則:總共可以表示多少張表呢?32個庫*每個庫32個表=1024張表。如果想表的數量小,就把32改小一些。
庫id = userid % 庫數量4 表id = userid / 庫數量4 % 表數量8
或者 庫id = userid / 表數量4 % 庫數量4 表id = userid % 表數量8
上面是用計算機術語來表示, 下面用通俗的話描述。
1、庫名稱計算
使用者id的後4位數,取32的模(取模就是除以這個數後,餘多少)。餘下的數,是0-31之間。
這樣可以表示從0-31之間,總共32個數字。用這個32個數字代表著32個庫名稱:order_db_0、order_db_2.........................order_db_31
2、表名稱計算
最後要儲存定到哪個表名裡面去呢?
使用者id的最後4位數,除以32,取整數。將整數除以32,得到餘數,能夠表示從0-31之間32個數字,表示表名稱。
表名稱類似這樣:order_tb_1、order_tb_2..........................order_tb_31。乙個庫裡面,總共32個表名稱。
比如使用者id:19408064,用最後4位數字8064除以32,得到是251.9,取它的整數是251。
接著將251除以32,取餘數,餘數為27。
為了保持效能,每張表的資料量要控制。單錶可以維持在一千萬-5千萬行的資料。1024*一千萬。哇,可以表示很多資料了。
優點訂單水平分庫分表,為什麼要按照使用者id來切分呢?
好處:查詢指定使用者的所有訂單,避免了跨庫跨表查詢。
因為,根據乙個使用者的id來計算節點,使用者的id是規定不變的,那麼計算出的值永遠是固定的(x庫的x表)
那麼儲存訂單的時候,a使用者的所有訂單,都是在x庫x表裡面。需要查詢a使用者所有訂單時,就不用進行跨庫、跨表去查詢了。
缺點缺點在於:資料分散不均勻,某些表的資料量特別大,某些表的資料量很小。因為某些使用者下單量多,打個比方,1000-2000這個範圍內的使用者,下單特別多,
而他們的id根據計算規則,都是分到了x庫x表。造成這個表的資料量大,單錶的資料量撐到極限後,咋辦呢?
總結一下:每種分庫分表方案也不是十全十美,都是有利有弊的。目前來說,這種使用使用者id來切分訂單資料的方案,還是被大部分公司給使用。實際效果還不錯。程式設計師省事,至於資料量暴漲,以後再說呢。畢竟公司業務發展到什麼程度,不知道的,專案存活期多久,未來不確定。先扛住再說。
思考一、b2b平台的訂單分賣家和買家的時候,選擇什麼欄位來分庫分表呢?
上面討論的情況是,b2c平台。訂單的賣家就乙個,就是平台自己。
b2b平台,上面支援開店,買家和賣家都要能夠登陸看到自己的訂單。
先來看看,分表使用買家id分庫分表和根據賣家id分庫分表,兩種辦法出現的問題
如果按買家id來分庫分表。有賣家的商品,會有n個使用者購買,他所有的訂單,會分散到多個庫多個表中去了,賣家查詢自己的所有訂單,跨庫、跨表掃瞄,效能低下。
如果按賣家id分庫分表。買家會在n個店鋪下單。訂單就會分散在多個庫、多個表中。買家查詢自己所有訂單,同樣要去所有的庫、所有的表搜尋,效能低下。
所以,無論是按照買家id切分訂單表,還是按照賣家id切分訂單表。兩邊都不討好。
**的做法是拆分買家庫和賣家庫,也就是兩個庫:買家庫、賣家庫。
買家庫,按照使用者的id來分庫分表。賣家庫,按照賣家的id來分庫分表。
實際上是通過資料冗餘解決的:乙個訂單,在買家庫裡面有,在賣家庫裡面也儲存了乙份。下訂單的時候,要寫兩份資料。先把訂單寫入買家庫裡面去,然後通過訊息中介軟體來同步訂單資料到賣家庫裡面去。
資料庫分庫分表思路
二.分庫分表帶來的問題 2 跨節點關聯查詢 join 問題 3 跨節點分頁 排序 函式問題 4 全域性主鍵避重問題 5 資料遷移 擴容問題 三.什麼時候考慮切分 四.案例分析 五.支援分庫分表中介軟體 六.參考 詳細內容 本篇簡單描述一下,思路概念詞。1 根據數值範圍 2 根據數值取模分布式事務 最...
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。優點 使用資料庫原有的功能,相對簡單 能夠保證唯一 能夠保證遞...