垂直拆分、讀寫分離、水平拆分(分庫分表)詳解


互聯網當下,數據庫的拆分過程基本遵循的順序是:垂直拆分、讀寫分離、水平拆分(也稱之為分庫分表)。

一、垂直拆分

1、什么是垂直拆分?

指的是將一個包含了很多表的數據庫,根據表的功能的不同,拆分為多個小的數據庫,每個庫中包含部分表。

比如:電商系統采用的庫為db_eshop,根據用戶功能和產品功能,可以拆分為用戶庫db_user和產品庫db_product。

 

2、什么時候使用垂直拆分?

剛開始,可能公司的技術團隊規模比較小,所有的數據都存放在一個庫中。

隨着公司業務的發展,技術團隊人員擴張,划分為不同的技術小組,不同的小組負責不同的業務模塊。

如:A小組負責用戶模塊,B小組負責產品模塊。此時可以將數據庫進行垂直拆分。

 

3、垂直拆分的好處?

垂直拆分會使得單個用戶請求的響應時間變長,但是會使得整個服務的吞吐量大大的增加。(服務吞吐量即系統在單位時間內處理請求的數量)

使得單個用戶請求的響應時間變長的原因在於:在單體應用場景下,所有的業務都在一個節點內部完成,而垂直拆分后,通常會需要進行rpc調用,rpc的調用會加長單個用戶請求的響應時間。

 

4、垂直拆分的另外2種用途?

1)、將一個包含了很多字段的大表拆分為多個小表,每個表中包含部分字段(基本很少遇到)

2)、進行服務化(SOA)的改造,除了業務上需要進行拆分,底層的存儲也需要進行隔離

二、讀寫分離

1、什么是讀寫分離?

將數據庫分為主庫和從庫,一個主庫用於寫數據,多個從庫完成讀數據的操作。

主從庫通過某種機制進行數據的同步。

2、為什么需要使用讀寫分離?

隨着業務的不斷發展,用戶數量和並發量不斷上升,此時如果僅靠單個數據庫實例來支撐所有的訪問壓力,數據庫將難以支撐。

比如:產品庫中,包含了幾萬種產品數據,並且每天新增幾十條產品數據,而產品庫每天的訪問可能有幾億甚至幾十億次,數據庫讀的壓力太大,單台mysql實例扛不住。此時可以將數據庫進行讀寫分離,主庫負責數據寫的操作,多個從庫負責數據讀的操作。

注:說白了,讀寫分離是為了解決數據庫讀的操作。

3、數據庫進行了讀寫分離配置后,開發人員需要做哪些事情?

DBA將mysql配置成主從復制,開發人員需要做如下事情:

1)、更新數據庫數據時,應用將數據寫入到master主庫

2)、主庫將數據同步給多個slave從庫

3)、當查詢數據時,應用選擇某一個slave節點讀取數據。

4、讀寫分離的優點?

通過配置多個從庫,可以有效的避免過大的訪問量對單個庫造成的壓力。

5、讀寫分離技術所面臨的問題有哪些?

讀寫分離的基本操作,是對sql類型進行判斷,如果是select等讀的請求,就走從庫.

如果是insert、update、delete等寫的請求,就走主庫。

1)、主從數據同步延遲的問題

因為數據是從主節點通過網絡同步給多個從 節點的,因此必然存在延遲問題。

因此可能出現如下問題:我們在主節點中插入了數據,但是從節點卻讀取不到數據的問題。

對於一些強一致性的業務場景,要求插入數據后必須能讀取到,對於這種情況,我們需要提供一種方式,讓讀的請求也可以走主庫,而主庫上的數據必然是最新的。

2)、事務問題

如果一個事務中同時包含了讀的請求和寫的請求,如果讀的請求走從庫,寫的請求走主庫。由於跨了多個庫,那么本地事務已經無法控制。

而分布式事務非常復雜且效率較低,因此讀寫分離,目前主流的做法是:將事務中所有sql統一走主庫,由於只涉及到一個庫,本地事務可以解決。

 

綜上所述:垂直拆分可以解決服務吞吐量即提高系統在單位時間內處理請求的數量

          讀寫分離可以緩解單庫的壓力,增強用戶並發訪問量

即經過垂直拆分和主從同步的數據庫完全可以承受住難以想象的高並發訪問操作。

三、水平拆分

1、什么是水平拆分(分表分庫)?

通過一種算法,將數據庫進行分割的架構。每個分片中的數據沒有重合,所有分片中的數據並集組成全部數據。

水平分表實際又可以分為如下三種:只分表、只分庫、分庫分表

1)、只分表:將db庫中的user表拆分為2個分表,即uer_0和user_1

2)、只分庫:將db庫差費為db_0和db_1這2個庫,同時在db_0和db_1庫中各自新建一個user表,db_0.user表和db_1.user表中各自只存放原來的db.user表中的部分數據

3)分庫分表:將db庫拆分為db_0和db_1這2個庫,db_0中包含user_0、user_1這2個分表,db_1中包含user_2、user_3這2個分表。

2、為什么需要進行分表分庫?

一旦業務表中的數據量比較大,從維護和性能的角度來看,仍然無法掩蓋因為數據量過大從而導致數據庫性能下降的事實。因此,這個時候mysql DBA就該對數據庫進行水平分區,經過水平分區設置后的業務表,必然能夠將原本一張表維護的海量數據分配給N個子表進行存儲和維護。

即:單庫容量最容易成為性能瓶頸,當單庫容量成為瓶頸,我們希望提高數據庫的寫的性能,降低單庫容量的話,就可以使用水平切分。

3、分表分庫的使用場景?

如果庫中的多個表中只有某張表或者少量表數據量過大,那么只需要針對這些表進行拆分,其它表保持不變。

4、分庫分表的好處?

如果說讀寫分離實現數據庫讀能力的水平提升

那么,分庫分表是是吸納數據庫寫能力的水平提升

1)、存儲能力的水平擴展

在讀寫分離的情況下,每個集群中的主從庫基本上數據時完全一致的,從存儲能力上講

在存儲海量數據的情況下,可能由於磁盤空間的限制,無法存儲所有的數據。

而分庫分表的情況下,我們可以搭建多個mysql主從復制集群,每個集群只存儲部分分片的額數據,實現了存儲能力的水平擴展。

2)、寫能力的水平擴展

在讀寫分離的情況下,由於每個集群只有一個master,所有的寫操作的壓力都集中在這一個節點上,在寫入並發非常高的情況下,這將會成為整個系統的瓶頸。

而在分表分庫的情況下,每個分片所屬的集群都有一個master節點,都可以執行寫入的操作,實現寫能力的水平擴展,此外減小建立索引開銷,降低寫操作的鎖操作耗時等,都會帶來很多顯著的好處。

5、分庫分表的問題

主要體現在如下4個方面:基本數據的增刪改功能、分布式id、分布式事務、動態擴容

1)、基本的數據庫增刪改功能

對於開發人員而言,雖然分庫分表的,但是其還是希望能和單庫單表那樣去操作數據庫。

如:我們要批量插入4條記錄,並且希望根據用戶的id字段,確定這條記錄插入哪個庫的那張表中。如:1號記錄插入user1表….4號記錄插入user4表

那么之前的單庫作如下:

insert into user(id,name) values (1,”tianshouzhi”),(2,”huhuamin”), (3,”wanghanao”),(4,”luyang”)

這顯然無法實現,因為我們已經對庫和表進行了拆分,這種sql語法只能操作mysql的單個庫和單個表,所以必須將sql改為4條,然后分表到每個庫上去執行,如下:

insert into user0(id,name) values  (4,”luyang”)

insert into user1(id,name) values (1,”tianshouzhi”)

insert into user2(id,name) values (2,”huhuamin”)

insert into user3(id,name) values (3,”wanghanao”)

2)、分布式id

在分庫分表后,我們不能再使用mysql的自增主鍵。

因為在插入記錄的時候,不同的庫生成的記錄的自增id可能會出現沖突

因此,需要一個全局的id生成器,目前分布式id有很多種方案,其中一個比較輕量級的方案是twitter的snowflake算法。

3)、分布式事務

分布式事務是分庫分表的繞不過去的一個坎,因為涉及到了同時更新多個分片數據。

如:批量插入記錄到四個不同的庫,如何保證要么同時成功,要么同時失敗。

關於分布式事務,mysql支持XA事務,但是效率較低。

柔性事務是目前比較主流的方案,柔性事務包括:最大努力通知型、可靠消息最終一致性方案以及TCC兩個階段提交。

但是無論XA事務還是柔性事務,實現起來都是非常復雜的。

4)、動態擴容

動態擴容是指只增加分庫分表的數量

如:將原來user表拆分到2個庫的四張表上。

現在我們希望將分庫的數量變為4個,分表的數量變為8個。

這種情況一般要伴隨着數據遷移,如在4張表的情況下,id為7的記錄,7%4=3

因此這條記錄位於user3這張表上,但是現在分表的數量變為8個,而7%8=0

而user0這張表根本沒有id=7這條記錄,因此如果不進行數據遷移的話,就會出現記錄找不到的情況。
————————————————
版權聲明:本文為CSDN博主「吒哇」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/fuqianming/article/details/99646063


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM