分庫分表之第一篇

来源:https://www.cnblogs.com/haizai/archive/2019/12/18/12063875.html
-Advertisement-
Play Games

分庫分表之第一篇 1.概述 1.1.分庫分表是什麼 1.2.分庫分表的方式 1.2.1.垂直分表 1.2.2.垂直分庫 1.2.3.水平分庫 1.2.4.水平分表 1.2.5 小結 1.3.分庫分錶帶來的問題 1.3.1.事務一致性問題 1.3.2.跨節點關聯查詢 1.3.3.跨節點分頁、排序函數 ...


分庫分表之第一篇

 

1.概述

1.1.分庫分表是什麼

小明是一家初創電商平臺的開發人員,他負責賣家模塊的功能開發,其中涉及了店鋪、商品的相關業務,設計如下資料庫 :
在這裡插入圖片描述
通過以下SQL能夠獲取到商品相關的店鋪信息、地理區域信息 :

SELECT p.*,r.[地理區功能變數名稱稱],s.[店鋪名稱],s.[信譽] FROM [商品信息] p
LEFT JOIN [地理區域] r ON p.[產地] = r.[地理區域編碼] LEFT JOIN [店鋪信息] s ON p.id = s.[所屬店鋪]
WHERE p.id = ?

形成類似以下列表展示 :
在這裡插入圖片描述
隨著公司業務快速發展,資料庫中的數據量猛增,訪問性能也變慢了,優化迫在眉睫。分析一下問題出現在哪兒 呢? 關係型資料庫本身比較容易成為系統瓶頸,單機存儲容量、連接數、處理能力都有限。當單表的數據量達到 1000W或100G以後,由於查詢維度較多,即使添加從庫、優化索引,做很多操作時性能仍下降嚴重。
方案1:
通過提升伺服器硬體能力來提高數據處理能力,比如增加存儲容量 、CPU等,這種方案成本很高,並且如果瓶頸在
MySQL本身那麼提高硬體也是有很的。
方案2:
把數據分散在不同的資料庫中,使得單一資料庫的數據量變小來緩解單一資料庫的性能問題,從而達到提升資料庫 性能的目的,如下圖:將電商資料庫拆分為若幹獨立的資料庫,並且對於大表也拆分為若幹小表,通過這種資料庫 拆分的方法來解決資料庫的性能問題。
在這裡插入圖片描述
分庫分表就是為瞭解決由於數據量過大而導致資料庫性能降低的問題,將原來獨立的資料庫拆分成若幹資料庫組成,將數據大表分成若幹數據表組成,使得單一資料庫、單一數據表的數據量變小,從而達到提升資料庫性能的目的。

1.2.分庫分表的方式

分庫分表包括分庫和分表兩個部分,在生產中通常包括 :垂直分庫、水平分庫、垂直分表、水平分表四種方式。

1.2.1.垂直分表

下邊通過一個商品查詢的案例來垂直分表 :
通常在商品列表中是不是顯示商品詳情信息的,如下圖 :
在這裡插入圖片描述
用戶在瀏覽商品列表時,只有對某商品感興趣時才會查看商品的詳細描述。因此,商品信息中商品描述欄位訪問頻次較低,且該欄位存儲占用空間較大,訪問單個數據IO時間較長;商品信息中商品名稱、商品圖片、商品價格等其他欄位數據訪問頻次較高。
由於這兩種數據的特性不一樣,因此他考慮將商品信息表拆分如下 :
將訪問頻次低的商品描述信息單獨存放在一張表中,訪問頻次較高的商品基本信息單獨放在一張表中。
在這裡插入圖片描述
商品列表可採用以下sql :

SELECT p.*,r.[地理區功能變數名稱稱],s.[店鋪名稱],s.[信譽] FROM [商品信息] p
LEFT JOIN [地理區域] r ON p.[產地] = r.[地理區域編碼] LEFT JOIN [店鋪信息] s ON p.id = s.[所屬店鋪] WHERE...ORDER BY...LIMIT...

需要獲取商品描述時,再通過以下sql獲取 :

SELECT *
FROM [商品描述] WHERE [商品ID] = ?

小明進行的這一步優化,就叫垂直分表。
垂直分表定義 :將一個表按照欄位分成多表,每個表存儲其中一部分欄位。
它帶來的提升是 :
1.為了避免IO爭搶並減少鎖表的幾率,查看詳情的用戶與商品信息瀏覽互不影響。
2.充分發揮熱門數據的操作效率,商品信息的操作的高效率不會被商品描述的低效率所拖累。
註意 :
為什麼大欄位IO效率低 :
第一是由於數據量本身大,需要更長的讀取時間;
第二是跨頁,頁是資料庫存儲單位,很多查找及定位操作都是以頁為單位,單頁內的數據行越多資料庫整體性能越好,而大欄位占用空間大,單頁記憶體儲行數少,因此IO效率較低。
第三,資料庫以行為單位將數據載入到記憶體中,這樣表中欄位長度較短且訪問頻率較高,記憶體能載入更多的數據,命中率更高,減少來磁碟IO,從而提升來資料庫性能。
一般來說,某業務實體中的各個數據項的訪問頻次是不一樣的,部分數據項可能是占用存儲空間比較大的BLOB或是TEXT。例如上例中的商品描述。所以,當表數據量很大時,可以將表按欄位切開,將熱門欄位、冷門欄位分開放置在不同庫中,這些庫可以放在不同的存儲設置上,避免IO爭搶。垂直切分帶來的性能提升主要集中在熱門數據的操作效率上,而且磁碟爭用情況減少。
通常我們按以下原則進行垂直拆分 :
1、把不常用的欄位單獨放在一張表;
2、把text,blob等大欄位拆分出來放在附表中;
3、經常組合查詢的列放在一張表中;

1.2.2.垂直分庫

通過垂直分表能得到來一定程度的提升,但是還沒有達到要求,並且磁碟空間也快不夠來,因為數據還是始終限制在一臺伺服器,庫內垂直分表只解決來單一表數據量過大的問題,但沒有將表分佈到不同的伺服器上,因此每個表還是競爭同一個物理機的CPU、記憶體、網路IO
、磁碟。
經過思考,他把原來的SELLER_DB(賣家庫),分為來PRODUCT_DB (商品庫)和STORE_DB(店鋪庫),並把這兩個庫分散到不同伺服器,如下圖 :
在這裡插入圖片描述
由於商品信息與商品描述業務耦合度較高,因此一起被存放在PRODUCT_DB(商品庫);而店鋪信息相對獨立,因此單獨被存放在STORE_DB(店鋪庫)。
小明進行的這一步優化,就叫垂直分庫。
垂直分庫是指按照業務將表進行分類,分佈到不同的資料庫上面,每個庫可以放不同的伺服器上,它的核心理念是專庫專用。
它帶來的提升是 :

  • 解決業務層面的耦合,業務清晰
  • 能對不同業務的數據進行分級管理、維護、監控、擴展等
  • 高併發場景下,垂直分庫一定程度的提升IO、資料庫連接數、降低單機硬體資源的瓶頸
    垂直分庫通過將表按業務分類,然後分庫在不同資料庫,並且可以將這些資料庫部署在不同伺服器上,從而達到多個伺服器共同分攤壓力的效果,但是依然沒有解決單表數據量過大的問題。

1.2.3.水平分庫

經過垂直分庫後,資料庫性能問題得到一定程度的解決,但是隨著業務量的增長,PRODUCT_DB(商品庫)單庫存儲數據已經超出預估。粗糧統計,目前有8W店鋪,每個店鋪平均150個不同規格的商品,再算增長,那商品數量的往1500w+上預估,並且PRODUCT_DB(商品庫)屬於訪問非常頻繁的資源,單台伺服器已經無法支撐。此時該如何優化?
再次分庫?但是從業務角度分析,目前情況已經無法再次垂直分庫。可以嘗試水平分庫,將店鋪ID為單數的和店鋪ID為雙數的商品信息分別放在兩個庫中。
在這裡插入圖片描述
也就是說,要操作其某條數據,先分析這條數據所屬的店鋪ID。如果店鋪ID為雙數,將此操作映射至PRODUCT_DB1(商品庫1);如果ID為單數,將操作映射至RRODUCT_DB2(商品庫2)。此操作要訪問資料庫名稱的表達式為RRODUCT_DB【店鋪ID%2 + 1】.
小明進行的這一步優化,就叫水平分庫。
水平分庫是把同一個表的數據按一定規則拆分到不同的資料庫中,每個庫可以放不同的伺服器上。
對比 :垂直分庫是把不同表拆到不同資料庫中,它是對數據行的拆分,不影響表結構。
它帶來的提升是 :

  • 解決來單庫大數據,高併發的性能瓶頸。
  • 提高來系統的穩定性及可用性。
    穩定性體現在IO衝突減少,鎖定減少,可用性指某個庫出問題,部分可用。
    當一個應用難以再細粒度的垂直切分,或切分後數據量行巨大,存在單庫讀寫、存儲性能瓶頸,這時候就需要進行水平分庫了,經過水平切分的優化,往往能解決單庫存儲量及性能瓶頸。但由於同一個表被分配在不同的資料庫,需要額外進行數據操作的路由工作,因此大大提升了系統複雜度。

1.2.4.水平分表

按照水平分庫的思路對他把PRODUCT_DB_X(商品庫)內的表也可以進行水平拆分,其目的也是為解決單表數據量大的問題,如下圖 :
在這裡插入圖片描述
與水平分庫的思路類似,不過這次操作的目標是表,商品信息及商品描述被分成了兩套表。如果商品ID為雙數,將此操作映射至商品信息1表;如果商品ID為單數,將操作映射至商品信息2表。此操作要訪問表名稱的表達式為商品信息【商品ID%2 + 1】。
小明進行的這一步優化,就叫水平分表。
水平分表是在同一個資料庫內,把同一個表的數據按一定規則拆到多個表中。
它帶來的提升是 :

  • 優化單一表數據量過大而產生的性能問題
  • 避免IO爭搶並減少鎖表的幾率
    庫內的水平分表,解決來單一表數據量過大的問題,分出來的小表中只包含一部分數據,從而使得單個表的數據量變小,提高檢索性能。

1.2.5 小結

介紹來分庫分表的幾種方式,它們分別是垂直分表、垂直分庫、水平分庫和水平分表 :
垂直分表 :可以把一個寬表的欄位按訪問頻次,是否是大欄位的原則拆分為多個表,這樣既能使業務清晰,還能提升部分性能。拆分後,儘量從業務角度避免聯查,否則性能方面將得不償失。
垂直分庫 :可以把多個表按業務耦合鬆緊歸類,分別存放在不同的庫,這些庫可以分佈在不同伺服器,從而使訪問壓力被能伺服器負載,大大提升性能,同時能提高整體架構的業務清晰度,不同的業務庫可根據自身情況定製優化方案。但是它需要解決跨庫帶來的所有複雜問題。
水平分庫 :可以把一個表的數據(按數據行)分到多個不同的庫,每個庫只有這個表的部分數據,這些庫可以分佈在不同伺服器,從而使訪問壓力被多伺服器負載,大大提升性能。它不僅需要解決跨庫帶來的所有複雜問題,還要解決數據路由的問題(數據路由問題後邊介紹)。
水平分表 :可以把一個表的數據(按數據行)分到多個同一個資料庫的多張表中,每個表只有這個表的部分數據,這樣做能小幅提升性能,它僅僅作為水平分庫的一個補充優化。
一般來說,在系統設計階段就應該根據業務耦合鬆緊來確定垂直分庫,垂直分表方案,在數據量及訪問壓力不是特別大的情況,首先考慮緩衝、讀寫分離、索引技術等方案。若數據量極大,且持續增長,再考慮水平分庫水平分表方案。

1.3.分庫分錶帶來的問題

分庫分表能有效的緩解來單機和單庫帶來的性能瓶頸和壓力,突破網路IO、硬體資源、連接數的瓶頸,同時也帶來了一些問題。

1.3.1.事務一致性問題

由於分庫分表把數據分佈在不同庫甚至不同伺服器,不可避免會帶來分散式事務問題。

1.3.2.跨節點關聯查詢

在沒有分庫前,我們檢索商品時可以通過以下SQL對店鋪信息進行關聯查詢 :

SELECT p.*,r.[地理區功能變數名稱稱],s.[店鋪名稱],s.[信譽] FROM [商品信息] p
LEFT JOIN [地理區域] r ON p.[產地] = r.[地理區域編碼] LEFT JOIN [店鋪信息] s ON p.id = s.[所屬店鋪] WHERE...ORDER BY...LIMIT...

但垂直分庫後【商品信息】和【店鋪信息】不在一個資料庫,甚至不在一臺伺服器,無法進行關聯查詢。
可將原關聯查詢分為兩次查詢,第一次查詢的結果集中找出關聯數據id,然後根據id發起第二次請求得到關聯數據,最後將獲得到的數據進行拼裝。

1.3.3.跨節點分頁、排序函數

跨節點多庫進行查詢時,limit分頁、order by排序等問題,就變得比較複雜了。需要先在不同的分片節點中將數據進行排序並返回,然後將不同分片返回的結果集進行彙總和再次排序。
如,進行水平分庫後的商品庫,按ID倒序排序分頁,取第一頁 :
在這裡插入圖片描述
以上流程是取第一頁的數據,性能影響不大,但由於商品信息的分佈在各資料庫的數據可能是隨機的,如果是取第N頁,需要將所有節點前N頁數據都取出來合併,再進行整體的排序,操作效率可想而知。所以請求頁數越大,系統的性能也會越差。在使用Max、Min、Sum、Count之類的函數進行計算的時候,與排序分頁同理,也需要先在每個分片上執行相應的函數,然後將各個分片的結果集進行彙總和再次計算,最終將結果返回。

1.3.4.主鍵避重

在分庫分表環境中,由於表中數據同時存在不同資料庫中,主鍵值平時使用的自增長將無用武之地,某個分區資料庫生成的ID無法保證全局唯一。因此需要單獨設計全局主鍵,比避免跨庫主鍵重覆問題。
在這裡插入圖片描述

1.3.5.公共表

實際的應用場景中,參數表、數據字典表等都是數據量較小,變動少,而且屬於高頻聯合查詢的依賴表。例子中地理區域表也屬於此類型。
可以將這類表在每個資料庫都保存一份,所有對公共表的更新操作都同時發送到分庫執行。
由於分庫分表之後,數據被分散在不同的資料庫、伺服器。因此,對數據的操作也就無法通過常規方式完成,並且它還帶來了一系列的問題。好在,這些問題不是所有都需要我們在應用層面上解決,其中Sharding-JDBC中間件可供選擇。

1.4 Sharding-JDBC介紹

1.4.1 Sharding-JDBC介紹

Sharding-JDBC是噹噹網研發的開源分散式資料庫中間件,從 3.0 開始Sharding-JDBC被包含在 Sharding-Sphere 中,之後該項目進入進入Apache孵化器,4.0版本之後的版本為Apache版本。
ShardingSphere是一套開源的分散式資料庫中間件解決方案組成的生態圈,它由Sharding-JDBC、Sharding- Proxy和Sharding-Sidecar(計劃中)這3款相互獨立的產品組成。 他們均提供標準化的數據分片、分散式事務和 資料庫治理功能,可適用於如Java同構、異構語言、容器、雲原生等各種多樣化的應用場景。
官方地址:https://shardingsphere.apache.org/document/current/cn/overview/
咱們目前只需關註Sharding-JDBC,它定位為輕量級Java框架,在Java的JDBC層提供的額外服務。 它使用客戶端 直連資料庫,以jar包形式提供服務,無需額外部署和依賴,可理解為增強版的JDBC驅動,完全相容JDBC和各種 ORM框架。
Sharding-JDBC的核心功能為數據分片和讀寫分離,通過Sharding-JDBC,應用可以透明的使用jdbc訪問已經分庫 分表、讀寫分離的多個數據源,而不用關心數據源的數量以及數據如何分佈。

  • 適用於任何基於Java的ORM框架,如: Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 基於任何第三方的資料庫連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意實現JDBC規範的資料庫。目前支持MySQL,Oracle,SQLServer和PostgreSQL。
    在這裡插入圖片描述
    上圖展示了Sharding-Jdbc的工作方式,使用Sharding-Jdbc前需要人工對資料庫進行分庫分表,在應用程式中加入 Sharding-Jdbc的Jar包,應用程式通過Sharding-Jdbc操作分庫分表後的資料庫和數據表,由於Sharding-Jdbc是對 Jdbc驅動的增強,使用Sharding-Jdbc就像使用Jdbc驅動一樣,在應用程式中是無需指定具體要操作的分庫和分表 的。

1.4.2 與jdbc性能對比

    1. 性能損耗測試 :伺服器資源充足、併發數相同,比較JDBC和Sharding-JDBC性能損耗,Sharding-JDBC相對JDBC損耗不超過7%。
      基準測試性能對比
      在這裡插入圖片描述
    2. 性能對比測試:伺服器資源使用到極限,相同的場景JDBC與Sharding-JDBC的吞吐量相當。
    3. 性能對比測試:伺服器資源使用到極限,Sharding-JDBC採用分庫分表後,Sharding-JDBC吞吐量較JDBC不分表有接近2倍的提升。
      在這裡插入圖片描述

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 案例:筋斗雲 滑鼠進入,一朵雲的樣式跟隨滑鼠移動,滑鼠點擊後離開,雲樣式回到上次點擊的位置 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; pa ...
  • 一、如何優化 用戶在訪問網頁時, 最直觀的感受就是頁面內容出來的速度,我們要做的優化工作, 也主要是為了這個目標。那麼為了提高頁面載入(或者渲染)速度呢?一般來說有三個方面: 1、代碼邏輯:優秀的代碼邏輯結構可以有效減少渲染頁面使用的記憶體和速度(比如虛擬DOM),此方面不在本文討論範圍內。 2、SS ...
  • 變速動畫函數封裝 勻速動畫:每次步數都是10 (var step=10;) 變速(緩動)動畫:每次的步數是用當前位置和目標位置相減 var step=(target-current)/10; 代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
  • [1]調試工具 [2]插件 [3]快捷鍵 [4]小功能 ...
  • 目前國產報表工具大部分都是Java版本,例如潤乾和帆軟,而C#寫的報表工具國內還沒有,介紹一款VS2010(C#)寫的國產報表工具(highreport),採用類Excel設計,零代碼實現複雜報表展示、複雜表單填報、圖表展示、參數面板、系統管理、大屏可視化、導出、列印等。 報表功能:1.報表採用類似 ...
  • JSP是一種運行在伺服器端的腳本語言,是用來開發動態網頁的技術,它是JAVA Web 程式開發的重要技術。本章介紹JSP技術的相關概念以及如何開發JSP程式,主要內容包括JSP技術簡介、JSP的處理過程、JSP語法、JSP的內置對象、每種對象的使用方法和使用技巧,以及簡單web應用程式的開發設計。 ...
  • 實例 this 是什麼? JavaScript this 關鍵詞指的是它所屬的對象。 它擁有不同的值,具體取決於它的使用位置: 在方法中,this 指的是所有者對象。 單獨的情況下,this 指的是全局對象。 在函數中,this 指的是全局對象。 在函數中,嚴格模式下,this 是 undefine ...
  • 封裝getScroll函數 1. 獲取頁面向上或者向左卷曲出去的距離的值 2. 瀏覽器的滾動事件 function getScroll() { return { left: window.pageXOffset || document.documentElement.scrollLeft || do ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...