主頁 > 後端開發 > 這四種情況下,才是考慮分庫分表的時候!

這四種情況下,才是考慮分庫分表的時候!

2021-01-15 06:20:40 後端開發

資料庫瓶頸
不管是IO瓶頸還是CPU瓶頸,最終都會導致資料庫的活躍連接數增加,進而逼近甚至達到資料庫可承載的活躍連接數的閾值,在業務service來看,
就是可用資料庫連接少甚至無連接可用,接下來就可以想象了(并發量、吞吐量、崩潰),
IO瓶頸
第一種:磁盤讀IO瓶頸,熱點資料太多,資料庫快取放不下,每次查詢會產生大量的IO,降低查詢速度->分庫和垂直分表
第二種:網路IO瓶頸,請求的資料太多,網路帶寬不夠 ->分庫
CPU瓶頸
第一種:SQl問題:如SQL中包含join,group by, order by,非索引欄位條件查詢等,增加CPU運算的操作->SQL優化,建立合適的索引,在業務Service層進行業務計算,
第二種:單表資料量太大,查詢時掃描的行太多,SQl效率低,增加CPU運算的操作,->水平分表,
水平分庫

1、概念:以欄位為依據,按照一定策略(hash、range等),將一個庫中的資料拆分到多個庫中,
2、結果:
每個庫的結構都一樣
每個庫中的資料不一樣,沒有交集
所有庫的資料并集是全量資料
3、場景:系統絕對并發量上來了,分表難以根本上解決問題,并且還沒有明顯的業務歸屬來垂直分庫的情況下,
4、分析:庫多了,io和cpu的壓力自然可以成倍緩解
水平分表

1、概念:以欄位為依據,按照一定策略(hash、range等),講一個表中的資料拆分到多個表中,
2、結果:
每個表的結構都一樣
每個表的資料不一樣,沒有交集,所有表的并集是全量資料,
3、場景:系統絕對并發量沒有上來,只是單表的資料量太多,影響了SQL效率,加重了CPU負擔,以至于成為瓶頸,可以考慮水平分表,
4、分析:單表的資料量少了,單次執行SQL執行效率高了,自然減輕了CPU的負擔,
垂直分庫

1、概念:以表為依據,按照業務歸屬不同,將不同的表拆分到不同的庫中,
2、結果:
每個庫的結構都不一樣
每個庫的資料也不一樣,沒有交集
所有庫的并集是全量資料
3、場景:系統絕對并發量上來了,并且可以抽象出單獨的業務模塊的情況下,
4、分析:到這一步,基本上就可以服務化了,例如:隨著業務的發展,一些公用的配置表、字典表等越來越多,這時可以將這些表拆到單獨的庫中,甚至可以服務化,再者,隨著業務的發展范訓出了一套業務模式,這時可以將相關的表拆到單獨的庫中,甚至可以服務化,
垂直分表

1、概念:以欄位為依據,按照欄位的活躍性,將表中欄位拆到不同的表中(主表和擴展表),
2、結果:
每個表的結構不一樣,
每個表的資料也不一樣,一般來說,每個表的欄位至少有一列交集,一般是主鍵,用于關聯資料,
所有表的并集是全量資料,
3、場景:系統絕對并發量并沒有上來,表的記錄并不多,但是欄位多,并且熱點資料和非熱點資料在一起,單行資料所需的存盤空間較大,以至于資料庫快取的資料行減少,查詢時回去讀磁盤資料產生大量隨機讀IO,產生IO瓶頸,
4、分析:可以用串列頁和詳情頁來幫助理解,垂直分表的拆分原則是將熱點資料(可能經常會查詢的資料)放在一起作為主表,非熱點資料放在一起作為擴展表,這樣更多的熱點資料就能被快取下來,進而減少了隨機讀IO,拆了之后,要想獲取全部資料就需要關聯兩個表來取資料,
但記住千萬別用join,因為Join不僅會增加CPU負擔并且會將兩個表耦合在一起(必須在一個資料庫實體上),關聯資料應該在service層進行,分別獲取主表和擴展表的資料,然后用關聯欄位關聯得到全部資料,
分庫分表工具
sharding-jdbc(當當)
TSharding(蘑菇街)
Atlas(奇虎360)
Cobar(阿里巴巴)
MyCAT(基于Cobar)
Oceanus(58同城)
Vitess(谷歌) 各種工具的利弊自查
分庫分表帶來的問題
分庫分表能有效緩解單機和單表帶來的性能瓶頸和壓力,突破網路IO、硬體資源、連接數的瓶頸,同時也帶來一些問題,下面將描述這些問題和解決思路,
事務一致性問題
分布式事務
當更新內容同時存在于不同庫找那個,不可避免會帶來跨庫事務問題,跨分片事務也是分布式事務,沒有簡單的方案,一般可使用“XA協議”和“兩階段提交”處理,
分布式事務能最大限度保證了資料庫操作的原子性,但在提交事務時需要協調多個節點,推后了提交事務的時間點,延長了事務的執行時間,導致事務在訪問共享資源時發生沖突或死鎖的概率增高,隨著資料庫節點的增多,這種趨勢會越來越嚴重,從而成為系統在資料庫層面上水平擴展的枷鎖,
最終一致性
對于那些性能要求很高,但對一致性要求不高的系統,往往不苛求系統的實時一致性,只要在允許的時間段內達到最終一致性即可,可采用事務補償的方式,與事務在執行中發生錯誤立刻回滾的方式不同,事務補償是一種事后檢查補救的措施,一些常見的實作方法有:對資料進行對賬檢查,基于日志進行對比,定期同標準資料來源進行同步等,
跨節點關聯查詢join問題
切分之前,系統中很多串列和詳情表的資料可以通過join來完成,但是切分之后,資料可能分布在不同的節點上,此時join帶來的問題就比較麻煩了,考慮到性能,盡量避免使用Join查詢,解決的一些方法:
全域表
全域表,也可看做“資料字典表”,就是系統中所有模塊都可能依賴的一些表,為了避免庫join查詢,可以將這類表在每個資料庫中都保存一份,這些資料通常很少修改,所以不必擔心一致性的問題,
欄位冗余
一種典型的反范式設計,利用空間換時間,為了性能而避免join查詢,例如,訂單表在保存userId的時候,也將userName也冗余的保存一份,這樣查詢訂單詳情順表就可以查到用戶名userName,就不用查詢買家user表了,但這種方法適用場景也有限,比較適用依賴欄位比較少的情況,而冗余欄位的一致性也較難保證,
資料組裝
在系統service業務層面,分兩次查詢,第一次查詢的結果集找出關聯的資料id,然后根據id發起器二次請求得到關聯資料,最后將獲得的結果進行欄位組裝,這是比較常用的方法,
ER分片
關系型資料庫中,如果已經確定了表之間的關聯關系(如訂單表和訂單詳情表),并且將那些存在關聯關系的表記錄存放在同一個分片上,那么就能較好地避免跨分片join的問題,可以在一個分片內進行join,在1:1或1:n的情況下,通常按照主表的ID進行主鍵切分,
跨節點分頁、排序、函式問題
跨節點多庫進行查詢時,會出現limit分頁、order by排序等問題,分頁需要按照指定欄位進行排序,當排序欄位就是分頁欄位時,通過分片規則就比較容易定位到指定的分片;當排序欄位非分片欄位時,就變得比較復雜.
需要先在不同的分片節點中將資料進行排序并回傳,然后將不同分片回傳的結果集進行匯總和再次排序,最侄訓傳給用戶 如下圖:

上圖只是取第一頁的資料,對性能影響還不是很大,但是如果取得頁數很大,情況就變得復雜的多,因為各分片節點中的資料可能是隨機的,為了排序的準確性,需要將所有節點的前N頁資料都排序好做合并,最后再進行整體排序,這樣的操作很耗費CPU和記憶體資源,所以頁數越大,系統性能就會越差,
在使用Max、Min、Sum、Count之類的函式進行計算的時候,也需要先在每個分片上執行相應的函式,然后將各個分片的結果集進行匯總再次計算,
全域主鍵避重問題
在分庫分表環境中,由于表中資料同時存在不同資料庫中,主鍵值平時使用的自增長將無用武之地,某個磁區資料庫自生成ID無法保證全域唯一,因此需要單獨設計全域主鍵,避免跨庫主鍵重復問題,這里有一些策略:
UUID
UUID標準形式是32個16進制數字,分為5段,形式是8-4-4-4-12的36個字符,
UUID是最簡單的方案,本地生成,性能高,沒有網路耗時,但是缺點明顯,占用存盤空間多,另外作為主鍵建立索引和基于索引進行查詢都存在性能問題,尤其是InnoDb引擎下,UUID的無序性會導致索引位置頻繁變動,導致分頁,
結合資料庫維護主鍵ID表
在資料庫中建立sequence表:

    CREATE TABLE `sequence` (  
      `id` bigint(20) unsigned NOT NULL auto_increment,  
      `stub` char(1) NOT NULL default '',  
      PRIMARY KEY  (`id`),  
      UNIQUE KEY `stub` (`stub`)  
    ) ENGINE=MyISAM;

stub欄位設定為唯一索引,同一stub值在sequence表中只有一條記錄,可以同時為多張表生辰全域ID,使用MyISAM引擎而不是InnoDb,已獲得更高的性能,MyISAM使用的是表鎖,對表的讀寫是串行的,所以不用擔心并發時兩次讀取同一個ID,當需要全域唯一的ID時,執行:

  REPLACE INTO sequence (stub) VALUES ('a');  
   SELECT 1561439;  

此方案較為簡單,但缺點較為明顯:存在單點問題,強依賴DB,當DB例外時,整個系統不可用,配置主從可以增加可用性,另外性能瓶頸限制在單臺Mysql的讀寫性能,
另有一種主鍵生成策略,類似sequence表方案,更好的解決了單點和性能瓶頸問題,這一方案的整體思想是:建立2個以上的全域ID生成的服務器,每個服務器上只部署一個資料庫,每個庫有一張sequence表用于記錄當前全域ID,
表中增長的步長是庫的數量,起始值依次錯開,這樣就能將ID的生成散列到各個資料庫上

這種方案將生成ID的壓力均勻分布在兩臺機器上,同時提供了系統容錯,第一臺出現了錯誤,可以自動切換到第二臺獲取ID,但有幾個缺點:系統添加機器,水平擴展較復雜;每次獲取ID都要讀取一次DB,DB的壓力還是很大,只能通過堆機器來提升性能,
Snowflake分布式自增ID演算法

Twitter的snowfalke演算法解決了分布式系統生成全域ID的需求,生成64位Long型數字,組成部分:
第一位未使用
接下來的41位是毫秒級時間,41位的長度可以表示69年的時間
5位datacenterId,5位workerId,10位長度最多支持部署1024個節點
最后12位是毫秒內計數,12位的計數順序號支持每個節點每毫秒產生4096個ID序列,
資料遷移、擴容問題
當業務高速發展、面臨性能和存盤瓶頸時,才會考慮分片設計,此時就不可避免的需要考慮歷史資料的遷移問題,一般做法是先讀出歷史資料,然后按照指定的分片規則再將資料寫入到各分片節點中,此外還需要根據當前的資料量個QPS,以及業務發展速度,進行容量規劃,推算出大概需要多少分片(一般建議單個分片的單表資料量不超過1000W),
什么時候考慮分庫分表
能不分就不分
并不是所有表都需要切分,主要還是看資料的增長速度,切分后在某種程度上提升了業務的復雜程度,不到萬不得已不要輕易使用分庫分表這個“大招”,避免“過度設計”和“過早優化”,分庫分表之前,先盡力做力所能及的優化:升級硬體、升級網路、讀寫分離、索引優化等,當資料量達到單表瓶頸后,在考慮分庫分表,
資料量過大,正常運維影響業務訪問
這里的運維是指:對資料庫備份,如果單表太大,備份時需要大量的磁盤IO和網路IO,對一個很大的表做DDL,MYSQL會鎖住整個表,這個時間會很長,這段時間業務不能訪問此表,影響很大,
大表經常訪問和更新,就更有可能出現鎖等待,
隨著業務發展,需要對某些欄位垂直拆分
這里就不舉例了,在實際業務中都可能會碰到,有些不經常訪問或者更新頻率低的欄位應該從大表中分離出去,
資料量快速增長
隨著業務的快速發展,單表中的資料量會持續增長,當性能接近瓶頸時,就需要考慮水平切分,做分庫分表了

來源:https://juejin.im/post/6844903992909103117

總結了一些2020年的面試題,這份面試題的包含的模塊分為19個模塊,分別是: Java基礎、容器、多執行緒、反射、物件拷貝、JavaWeb例外、網路、設計模式、Spring/SpringMVC、SpringBoot/SpringCloud、Hibernate、MyBatis、RabbitMQ、Kafka、Zookeeper、MySQL、Redis、JVM,獲取資料:關注公眾號:【有故事的程式員】,獲取學習資料,
記得點個關注+評論哦~

記得點個關注+評論哦~

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/248849.html

標籤:Java

上一篇:FlatBuffers 使用小結

下一篇:Java微服務 vs Go微服務,究竟誰更強!?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more