本文是《手把手項目實戰系列》的第二篇文章。上一篇《手把手0基礎教你搭建一套可自動化構建的微服務框架(SpringBoot+Dubbo+Docker+Jenkins)》受到巨大好評,在這裏也深表感謝。應你們要求繼續完成後續章節的撰寫。上一篇的實戰過程介紹的「高喜商城」項目實際上是一個真實項目,它是一個標準的在線商城(爲了避嫌,「高喜商城」是我隨意起的一個假名字),這個項目的不少技術具備必定的普適性。所以我計劃將它實現的方方面面以項目實戰的形式介紹給你們,讓你們體驗一個真實線上項目的開發、運維、升級過程。前端
相信不少同窗對「分庫分表」這一律念只知其一;不知其二,不用着急,本文的後續章節將會分紅知識點掃盲篇和實戰動手篇兩部分。知識點掃盲篇將會從零開始,介紹分庫分表的基本知識,而後再帶領你們開始動手實踐。但願可以給你帶來完美的閱讀體驗。接下來我將用盡可能通俗易懂的語言介紹分庫分表的相關知識,不裝逼,作一個低調的程序猿。算法
預告一下,整個系列會介紹以下內容:sql
隨着大數據時代的到來,業務系統的數據量日益增大,數據存儲能力逐漸成爲影響系統性能的瓶頸。目前主流的關係型數據庫單表存儲上限爲1000萬條記錄,而這一存儲能力顯然已經沒法知足大數據背景下的業務系統存儲要求了。隨着微服務架構、分佈式存儲等概念的出現,數據存儲問題也漸漸迎來了起色。而數據分片是目前解決海量數據持久化存儲與高效查詢的一種重要手段。數據分庫分表的過程在系統設計階段完成,要求系統設計人員根據系統預期的業務量,將將來可能出現瓶頸的數據庫、數據表按照必定規則拆分紅多個庫、多張表。這些數據庫和數據表須要部署在不一樣的服務器上,從而將數據讀寫壓力分攤至集羣中的各個節點,提高數據庫總體處理能力,避免出現讀寫瓶頸的現象。數據庫
目前數據分片的方式一共有兩種:離散分片和連續分片。編程
離散分片是按照數據的某一字段哈希取模後進行分片存儲。只要哈希算法選擇得當,數據就會均勻地分佈在不一樣的分片中,從而將讀寫壓力平均分配給全部分片,總體上提高數據的讀寫能力。然而,離散存儲要求數據之間有較強的獨立性,但實際業務系統並不是如此,不一樣分片之間的數據每每存在必定的關聯性,所以在某些場景下須要跨分片鏈接查詢。因爲目前全部的關係型數據庫出於安全性考慮,均不支持跨庫鏈接。所以,跨庫操做須要由數據分庫分表中間件來完成,這極大影響數據的查詢效率。此外,當數據存儲能力出現瓶頸須要擴容時,離散分片規則須要將全部數據從新進行哈希取模運算,這無疑成爲限制系統可擴展性的一個重要因素。雖然,一致性哈希能在必定程度上減小系統擴容時的數據遷移,但數據遷移問題仍然不可避免。對於一個已經上線運行的系統而言,系統中止對外服務進行數據遷移的代價太大。緩存
第二種數據分片的方式即爲連續分片,它能解決系統擴容時產生的數據遷移問題。這種方式要求數據按照時間或連續自增主鍵連續存儲。從而一段時間內的數據或相鄰主鍵的數據會被存儲在同一個分片中。當須要增長分片時,不會影響現有的分片。所以,連續分片能解決擴容所帶來的數據遷移問題。可是,數據的存儲時間和讀寫頻率每每呈正比,也就是大量的讀寫每每都集中在最新存儲的那一部分數據,這就會致使熱點問題,並不能起到分攤讀寫壓力的初衷。安全
數據庫擴展一共有四種分配方式,分別是:垂直分庫、垂直分表、水平分表、水平數據分片。每一種策略都有各自的適用場景。服務器
垂直分庫架構
垂直分庫便是將一個完整的數據庫根據業務功能拆分紅多個獨立的數據庫,這些數據庫能夠運行在不一樣的服務器上,從而提高數據庫總體的數據讀寫性能。這種方式在微服務架構中很是經常使用。微服務架構的核心思想是將一個完整的應用按照業務功能拆分紅多個可獨立運行的子系統,這些子系統稱爲「微服務」,各個服務之間經過RPC接口通訊,這樣的結構使得系統耦合度更低、更易於擴展。垂直分庫的理念與微服務的理念不謀而合,能夠將本來完整的數據按照微服務拆分系統的方式,拆分紅多個獨立的數據庫,使得每一個微服務系統都有各自獨立的數據庫,從而能夠避免單個數據庫節點壓力過大,影響系統的總體性能,以下圖所示。 框架
垂直分表
垂直分表若是一張表的字段很是多,那麼頗有可能會引發數據的跨頁存儲,這會形成數據庫額外的性能開銷,而垂直分表能夠解決這個問題。垂直分表就是將一張表中不經常使用的字段拆分到另外一張表中,從而保證第一章表中的字段較少,避免出現數據庫跨頁存儲的問題,從而提高查詢效率。而另外一張表中的數據經過外鍵與第一張表進行關聯,以下圖所示。
水平分表
若是一張表中的記錄數過多(超過1000萬條記錄),那麼會對數據庫的讀寫性能產生較大的影響,雖然此時仍然可以正確地讀寫,但讀寫的速度已經到了業務沒法忍受的地步,此時就須要使用水平分表來解決這個問題。水平分表是將一張含有不少記錄數的表水平切分,拆分紅幾張結構相同的表。舉個例子,假設一張訂單表目前存儲了2000萬條訂單的數據,致使數據讀寫效率極低。此時能夠採用水平分表的方式,將訂單表拆分紅100張結構相同的訂單表,分別叫作order_一、order_2……、order_100。而後能夠根據訂單所屬用戶的id進行哈希取模後均勻地存儲在這100張表中,從而每張表中只存儲了20萬條訂單記錄,極大提高了訂單的讀寫效率,以下圖所示。 固然,若是拆分出來的表都存儲在同一個數據庫節點上,那麼當請求量過大的時候,畢竟單臺服務器的處理能力是有限的,數據庫仍然會成爲系統的瓶頸,因此爲了解決這個問題,就出現了水平數據分片的解決方案。
水平分庫分表
水平數據分片與數據分片區別在於:水平數據分片首先將數據表進行水平拆分,而後按照某一分片規則存儲在多臺數據庫服務器上。從而將單庫的壓力分攤到了多庫上,從而避免由於數據庫硬件資源有限致使的數據庫性能瓶頸,以下圖所示。
目前經常使用的數據分片策略有兩種,分別是連續分片和離散分片。
離散分片
離散分片是指將數據打散以後均勻地存儲在邏輯表的各個分片中,從而使的對同一張邏輯表的數據讀取操做均勻地落在不一樣庫的不一樣表上,從而提升讀寫速度。離散分片通常以哈希取模的方式實現。好比:一張邏輯表有4個分片,那麼在讀寫數據的時候,中間件首先會取得分片字段的哈希值,而後再模以4,從而計算出該條記錄所在的分片。在這種方法中,只要哈希算法選的好,那麼數據分片將會比較均勻,從而數據讀寫就會比較均勻地落在各個分片上,從而就有較高的讀寫效率。可是,這種方式也存在一個最大的缺陷——數據庫擴容成本較高。採用這種方式,若是須要再增長分片,原先的分片算法將失效,而且全部記錄都須要從新計算所在分片的位置。對於一個已經上線的系統來講,行級別的數據遷移成本至關高,並且因爲數據遷移期間系統仍在運行,仍有新數據產生,從而沒法保證遷移過程數據的一致性。若是爲了不這個問題而停機遷移,那必然會對業務形成巨大影響。固然,若是爲了不數據遷移,在一開始的時候就分片較多的分片,那須要承擔較高的費用,這對於中小公司來講是沒法承受的。
連續分片
連續分片指的是按照某一種分片規則,將某一個區間內的數據存儲在同一個分片上。好比按照時間分片,每月生成一張物理表。那麼在讀寫數據時,直接根據當前時間就能夠找到數據所在的分片。再好比能夠按照記錄ID分片,這種分片方式要求ID須要連續遞增。因爲Mysql數據庫單表支持最大的記錄數約爲1000萬,所以咱們能夠根據記錄的ID,使得每一個分片存儲1000萬條記錄,當目前的記錄數即將到達存儲上限時,咱們只需增長分片便可,原有的數據無需遷移。連續分片的一個最大好處就是方便擴容,由於它不須要任何的數據遷移。可是,連續分片有個最大的缺點就是熱點問題。連續分片使得新插入的數據集中在同一個分片上,而每每新插入的數據讀寫頻率較高,所以,讀寫操做都會集中在最新的分片上,從而沒法體現數據分片的優點。
跨庫操做
在關係型數據庫中,多張表之間每每存在關聯,咱們在開發過程當中須要使用JOIN操做進行多表鏈接。可是當咱們使用了分庫分表模式後,因爲數據庫廠商處於安全考慮,不容許跨庫JOIN操做,從而若是須要鏈接的兩張表被分到不一樣的庫中後,就沒法使用SQL提供的JOIN關鍵字來實現錶鏈接,咱們可能須要在業務系統層面,經過屢次SQL查詢,完成數據的組裝和拼接。這一方面會增長業務系統的複雜度,另外一方面會增長業務系統的負載。 所以,當咱們使用分庫分表模式時,須要根據具體的業務場景,合理地設置分片策略、設置分片字段,這將會在本文的後續章節中介紹。
分佈式事務
咱們知道,數據庫提供了事務的功能,以保證數據一致性。然而,這種事務只是針對單數據庫而言的,數據庫廠商並未提供跨庫事務。所以,當咱們使用了分庫分表以後,就須要咱們在業務系統層面實現分佈式事務。關於分佈式事務的詳細內容,能夠參考筆者的另外一篇文章《經常使用的分佈式事務解決方案》。
Cobar實現數據庫的透明分庫,讓開發人員可以在無感知的狀況下操縱數據庫集羣,從而簡化數據庫的編程模型。然而Cobar僅實現了分庫功能,並未實現分表功能。分庫能夠解決單庫IO、CPU、內存的瓶頸,但沒法解決單表數據量過大的問題。此外,Cobar是一個獨立運行的系統,它處在應用系統與數據庫系統之間,所以增長了額外的部署複雜度,增長了運維成本。
爲了解決上述問題,Cobar還推出了一個Cobar-Client項目,它只是一個安裝在應用程序的Jar包,並非一個獨立運行的系統,必定程度上下降了系統的複雜度。但和Cobar同樣,仍然只支持分庫,並不支持分表,也不支持讀寫分離。
MyCat是基於Cobar二次開發的數據庫中間件,和Cobar相比,它增長了讀寫分離的功能,並修復了Cobar的一些bug。可是,MyCat和Cobar同樣,都是一套須要獨立部署的系統,所以會增長部署的複雜度,提升了後期系統運維的成本。
高喜商城已經上線了一段時間,用戶量超預期增加,業務層採用基於Dubbo的微服務架構,並結合了Docker+Jenkins實現了自動化部署,具有靈活的擴展能力,可以輕鬆支撐目前的業務量。然而,數據庫層面卻出現了瓶頸。因爲1.0版本採用單庫單表設計,雖然使用Mysql讀寫分離實現了一主多備架構,必定程度上分攤了數據庫的讀寫壓力。但按照目前的業務發展速度,不少業務表將會面臨單表過長的問題。目前Mysql數據庫在保證讀寫性能的前提下,單表最大支持1000W條數據。當單表超過1000W條數據後,雖然仍然能夠存儲數據,但讀寫性能大幅降低。所以,爲了知足極速增加的業務需求,須要使用數據庫中間件實現數據分庫分表存儲。分庫能將讀寫壓力分攤至不一樣節點,從而緩解讀寫壓力;而分表可以避免單表過長的問題。此外,大多數分庫分表中間件都會提供讀寫分離的功能,從而進一步緩解數據庫的讀寫壓力,提高讀寫性能。
綜上所述,對數據庫進行分庫分表迫在眉睫!
高喜商城1.0的架構以下圖所示:
該架構的業務層採用微服務架構,全部將整個應用分紅四個業務系統:用戶系統、產品系統、訂單系統和數據分析系統。關於微服務架構這裏不作過多介紹,詳細內容請閱讀《手把手0基礎項目實戰(一)——教你搭建一套可自動化構建的微服務框架(SpringBoot+Dubbo+Docker+Jenkins)》,這裏主要介紹數據庫架構。
在高喜商城1.0版本中,雖然業務層採用微服務架構,業務層被拆分紅多個相互獨立的子系統,但在數據庫層,整個系統的全部表均在同一個數據庫中存儲。此外,採用數據庫的主從複製實現了讀寫分離,數據庫有一個主庫和兩個從庫組成了一個數據庫集羣。它是一個對等集羣,每一個庫中存儲的數據是一致的。
在加入了讀寫分離後,一方面提高了數據庫的讀寫性能;另外一方面,實現了數據庫的高可用。當某一個節點發生故障時,仍然有其餘兩個節點提供服務。
這種架構存在以下幾個缺點:
針對上述問題,對數據庫進行分庫分表迫在眉睫。
高喜商城2.0數據庫架構以下圖所示:
在2.0架構中,首先對數據庫進行了垂直拆分,每一個子系統均擁有本身獨立的數據庫,不一樣系統的數據庫相互隔離,沒法互相訪問。這樣保證了各個業務系統的純粹性,不一樣業務系統之間若是須要數據交互,那麼就經過業務系統提供了RPC接口訪問,而非經過數據庫訪問,從而符合微服務的設計理念。
上圖對用戶系統的數據庫架構作了詳細介紹,其餘系統的數據庫架構和用戶系統相似,都採用了分庫分表+讀寫分離的架構。
在用戶系統中,數據庫一共被分紅N個主庫和N個從庫,每一個庫中的表又被拆分紅多張。以上圖爲例,用戶系統的數據庫一共被分紅兩個物理庫,分別是db_0和db_1。此外,爲了實現讀寫分離,每一個物理庫均擁有一個從庫,主從數據庫的數據保持一致。從而,用戶系統的物理庫一共被分紅四個,分別是:db_0_master、db_1_master、db_0_slave、db_1_slave。
每一個庫中的表table被水平拆分紅兩張,分別是table_0、table_1。從而,本來一張table表被水平拆分紅了四張,分別是:db_0_master_table_0、db_0_master_table_一、db_1_master_table_0、db_1_master_table_1。與此同時,從庫中也有四張這樣的table表,而且和主庫的數據保持一致,所以,通過水平拆分後,一共有8張table表。
上述table表只是舉一個例子,實際每一個系統均包含有多張表,每張表的拆分規則和拆分數量要根據該表具體的業務量來決定。具體的拆分過程將在下面介紹。
下面將會詳細介紹高喜商城數據表的設計。這些設計在在線商城系統中是通用的,具有必定的借鑑意義,所以下面將會詳細介紹。
用戶系統的數據表一共由如上六張表構成,下面對這六張表的做用以及相互之間的關係做簡單介紹。
到此爲止,用戶系統的每一張表及表於表之間的關係都已詳細介紹完畢。經過這些表以及表之間的關係咱們就能看出用戶系統的業務需求。
產品系統的數據表一共由如上四張表構成,下面對這四張表的做用以及相互之間的關係做簡單介紹。
訂單系統的數據表一共由如上三張表構成,下面對這三張表的做用以及相互之間的關係做簡單介紹。
到此爲止,一個在線商城中最核心的三大系統的數據表關係已經梳理清楚了,下面將會根據具體的業務指標,對這些數據庫和數據表進行合理的分庫分表。
在對高喜商城開始分庫分表以前,咱們先要搞清楚,究竟爲什麼要分庫?爲什麼要分表?爲什麼要讀寫分離?
系統的分庫分表策略必定是基於具體的業務指標和實際的業務需求,在正式進行分庫分表策略的設計以前,必定要作好這兩部分數據的採集。如今高喜商城的業務指標和業務需求以下面兩張表格所示:
高喜商城將來五年的業務指標:
表名 | 將來五年數據量 | 關鍵字段 |
---|---|---|
sys_user | 1000W | uid, username, password, email, phone, role_id |
location | 5000W | uid, location |
receipt | 5000W | uid, 發票相關字段 |
sys_role | 100 | role_id, role_name |
sys_permission | 1000 | pms_id, permission |
sys_role_permission | 100*1000 | role_id, pms_id |
sys_menu | 200 | menu_id, menu |
sys_role_menu | 200*1000 | role_id, menu_id |
高喜商城的業務需求:
表名 | 業務需求 | 涉及字段 |
---|---|---|
sys_user | 1.用戶登陸(用戶名登陸) | username, password |
2.用戶登陸(郵箱登陸) | email, password | |
3.用戶登陸(短信驗證碼登陸) | phone | |
4.根據uid查詢用戶信息 | uid | |
5.管理員按照某些條件分頁查詢用戶 | 任何字段都有可能使用 |
表名 | 業務需求 | 涉及字段 |
---|---|---|
location | 根據uid查詢收貨地址 | uid |
表名 | 業務需求 | 涉及字段 |
---|---|---|
receipt | 根據uid查詢發票信息 | uid |
高喜商城將來五年預計將會擁有1000萬用戶,從而用戶表將會有1000萬條數據。因爲目前Mysql單表支持最大長度爲1000萬,所以爲了保險起見,咱們須要將用戶表水平拆分紅兩張。此外,爲了防止用戶表讀寫壓力過大,咱們乾脆將這兩張用戶表放入兩個物理庫中。而且爲了保證用戶表的高可用,咱們對這兩個數據庫採用主從複製技術,一主一叢,其結構以下圖所示:
從高喜商城將來五年的業務量表中可知,系統的角色、權限、菜單數量較少,沒有必要分庫分表。在用戶查詢的過程當中須要鏈接用戶表、角色表、權限表和菜單表,若是將這些無需拆分的表存儲在某一個數據庫中,那麼用戶表將沒法和他們進行跨庫鏈接,從而須要在完成用戶信息查詢後,在業務層再次根據uid分別查詢角色信息、權限信息、菜單信息,這無心增長了業務層的實現複雜度。爲了解決這個問題,咱們能夠對角色表、權限表和菜單表進行冗餘,即將這些表冗餘地存儲在sys_user的全部物理庫中,從而任何一個物理庫的用戶查詢操做均可以直接經過錶鏈接的方式完成角色信息、權限信息和菜單信息的查詢。其結構以下圖所示:
此外,用戶和收穫地址、用戶和發票信息之間都是一對多的組合關係,若是每一個用戶平均擁有5個收貨地址和5種發票信息,那麼對於1000萬用戶而言,一共會建立5000萬條收穫信息和5000萬條發票信息。所以,收穫地址和發票信息各需6張表來存儲。而且,因爲這兩種信息都是經過uid來查詢,而且查詢條件只有uid這一項,所以uid毫無爭議地成爲分片字段,而且這6張表只能分佈在6個物理庫中。此外,爲了實現數據庫的高可用性,須要對這6個庫提供主從複製功能。最終,收貨地址表和發票信息表的結構以下圖所示:
高喜商城用戶系統的數據庫分庫分表方案就介紹到這,下面介紹產品系統的分庫分表方案。
和用戶系統的分庫分表方案設計過程同樣,在方案設計以前,首先要肯定系統的業務指標和業務需求。
高喜商城將來五年的業務指標:
表名 | 將來五年數據量 | 關鍵字段 |
---|---|---|
orders | 2000W | order_id, buyer_id, seller_id |
orders_product | 5*2000W | order_id, prodcut_id |
order_state_time | 10*2000W | order_id, state, time |
高喜商城的業務需求:
表名 | 業務需求 | 涉及字段 |
---|---|---|
orders | 1.根據buyer_id分頁查詢某一用戶的訂單 | buyer_id |
2.根據order_id查詢訂單 | order_id | |
3.根據seller_id分頁查詢某一商家的訂單 | seller_id |
表名 | 業務需求 | 涉及字段 |
---|---|---|
orders_product | 根據order_id查詢產品列表 | order_id |
表名 | 業務需求 | 涉及字段 |
---|---|---|
order_state_time | 1.根據order_id和state篩選某一狀態下的訂單 | order_id, state |
2.修改指定訂單的狀態 | order_id, state |
訂單系統的核心業務需求如上述三張表所示。orders表和orders_product表、order_state_time表之間都是一對多的組合關係,在查詢過程當中須要進行錶鏈接操做。所以,咱們必需要指定合理的分庫分表方案,可以使得同一訂單的產品信息、訂單狀態信息都落在同一個物理庫中,從而可以直接使用SQL語句進行鏈接操做。若是分庫分表方案不合理,那麼同一訂單的產品信息和訂單狀態信息會散落在不一樣的物理庫中,因爲Mysql並不支持跨庫鏈接,所以這三張表的鏈接須要拆分紅三次數據庫查詢,並在業務層完成數據的鏈接,這無心增長了業務層的複雜度。下面詳細介紹訂單系統的分庫分表方案。
經過分析上述三張業務需求表可知,訂單系統核心操做所涉及到的字段無非就是三個:order_id、buyer_id、seller_id。當查詢指定訂單的時候須要使用order_id做爲查詢條件,當查詢某一買家全部訂單的時候須要使用buyer_id做爲查詢條件,當查詢某一賣家全部訂單的時候須要使用seller_id做爲查詢條件。因而可知,分片字段須要從這三個字段中選擇。那麼究竟應該如何選擇呢?咱們分別來看以下三種方案:
將order_id做爲分片字段 若是將order_id做爲分片字段,那麼根據order_id查詢指定訂單的時候能夠直接定位到指定的物理表,然而在根據buyer_id和seller_id查詢訂單的時候,因爲沒法定位到具體的表,所以就須要全庫表查詢,這顯然是低效的。
將buyer_id做爲分片字段 此時,查詢指定買家的訂單信息能夠直接定位到指定的物理表,可是當須要根據order_id查詢具體訂單信息、查詢賣家訂單信息時就顯得提襟見肘了。
將seller_id做爲分片字段 此時,查詢指定賣家的全部訂單信息能夠定位到指定的物理表,但查詢買家訂單、根據訂單編號查詢訂單時就須要全庫表查詢了。
綜上所述,若是隻將這三個字段中的某一個做爲分片字段,顯然沒法知足全部的業務場景,一定會存在全庫表查詢,這就會致使查詢效率低下。那麼,有沒有什麼方案可以避免全庫表查詢呢?固然有!
首先,咱們來解決跨庫鏈接的問題。
解決跨庫鏈接問題的根本方法就是避免跨庫鏈接,讓須要鏈接的表存儲在同一個物理庫中。在訂單系統中,orders表要分別和orders_product表、order_state_time表產生鏈接,而且都是以order_id做爲鏈接字段。可是,若是咱們以order_id做爲這三張表的分片字段,那麼當根據buyer_id、seller_id查詢時,都須要全庫表操做。因此,咱們須要分別以buyer_id和seller_id做爲分片字段。聽上去很神奇,具體怎麼實施呢?
在訂單關係中,買家(buyer_id)和賣家(seller_id)是多對多的聚合關係,對於多對多關係,咱們可使用表冗餘來實現不一樣緯度的查詢。
此時,咱們須要將訂單表(orders)一分爲二,分別是買家訂單表(orders_buyer)和賣家訂單表(orders_seller),這兩張表的數據是徹底一致的。在買家訂單表中,以buyer_id做爲分片字段;在賣家訂單表中,以seller_id做爲分片字段。那麼當須要查詢指定買家的訂單時,根據買家id(buyer_id)就能夠肯定該買家訂單數據所在的物理表;當須要查詢指定賣家的訂單時,根據賣家id(seller_id)就能夠肯定該賣家訂單數據所在的物理表。
此時已經避免了上述兩個業務場景的全庫表查詢,那麼還有兩種業務場景的全庫表查詢問題如何解決呢?
此時,訂單系統的數據庫架構以下圖所示:
採用了上述方案後,全部的全庫表查詢問題都獲得瞭解決,但不要止步於此,還能夠進一步優化。
上述方案中,咱們使用了一張映射表來維護order_id和buyer_id之間的映射關係,當須要根據order_id查詢指定訂單的時候,先要查詢映射表,找到該訂單對應的buyer_id,而後再根據buyer_id計算分片,找到相應的物理表。
這個過程經歷了兩次地址查詢,還須要額外的策略存儲映射表。那麼,有沒有什麼方法可以解決這兩個問題呢?固然是有的,此時就要介紹個人黑科技了。
x%N的結果實際上是由x二進制的末尾logN位決定的
舉個例子,13534443 % 8,實際上是由13534443的二進制表示法的最後log8位決定的。
所以,13534443 % 8的結果由011決定。也就是說,只要末尾三位都是011的數字,對8取模的結果都是同樣的。
基於這個結論,咱們只要保證buyer_id和order_id的最後logN位一致,就無需再使用額外的映射表來存儲這二者的映射關係。order_id和buyer_id的生成方式以下:
此時同一個買家的buyer_id%N的結果和order_id%N的結果一致。在根據order_id查詢訂單的時候直接經過order_id%N計算出訂單所在的物理庫便可。
高喜商城將來五年的業務指標:
表名 | 將來五年數據量 | 關鍵字段 |
---|---|---|
product | 100W | product_id |
prod_image | 10*100W | product_id |
brand | 1000 | |
category | 100 |
整體而言,產品系統的數據量相對較小。運營同窗規劃,將來五年,高喜商城的產品數量最多爲100W,因爲每件產品最多容許擁有10張圖片,所以prod_image表的數量預計爲1000W,所以須要對prod_image表進行拆分;而產品的品牌、產品的類別數量較小,不須要考慮分庫分表。
產品系統的數據庫分庫分表方案以下圖所示:
因爲prod_image表的數據量將會達到1000W,所以爲了不單表數據超過1000W,將該表根據prod_id拆分紅兩張物理表。
此外,在產品系統中,product、brand、category數據量均不會超過1000W,所以無需分庫分表。