MySQL之分庫分表

1. 爲什麼要分庫分表?

       倘若我們沒有進行分庫分表,那麼整個架構圖如下所示:

在這裏插入圖片描述

       可以看到,多個系統的實例都在訪問同一個MySQL實例,隨着業務量的增加,我們可以在增加系統的實例,但是始終訪問的都是同一個實例。並且,如果每一個系統實例的讀寫請求都特別高,一個MySQL實例也是頂不住過多的請求,便造成數據庫的宕機,整個系統無法服務。

       而如果進行分庫分表之後,架構圖如下所示:

在這裏插入圖片描述

       可以看到,原本的讀寫請求由一臺MySQL實例,現在由三臺MySQL實例承擔。不僅提高了讀寫請求的承擔能力,同時,數據也可以被接近於平均分配到每臺MySQL實例中,這樣數據查詢速度也提高了。

2. 分庫分表

       首先需要知道的是,分庫、分表是兩個不同的概念。

       分庫指的是將一個庫的數據拆分到多個庫中,訪問的時候就訪問一個庫好了。多臺MySQL的實例中,每個實例中都有一摸一樣的表,除了表中的數據。

       分表指的是把一個表的數據放到多個表中,然後查詢的時候你就查一個表。同時,分表又分爲水平切分和垂直切分。

       水平拆分的意思,就是把一個表的數據給弄到多個庫的多個表裏去,但是每個庫的表結構都一樣,只不過每個庫表放的數據是不同的,所有庫表的數據加起來就是全部數據。水平拆分的意義,就是將數據均勻放更多的庫裏,然後用多個庫來抗更高的併發,還有就是用多個庫的存儲容量來進行擴容。

在這裏插入圖片描述

       垂直拆分的意思,就是把一個有很多字段的表給拆分成多個表,或者是多個庫上去。每個庫表的結構都不一樣,每個庫表都包含部分字段。一般來說,會將較少的訪問頻率很高的字段放到一個表裏去,然後將較多的訪問頻率很低的字段放到另外一個表裏去。因爲數據庫是有緩存的,你訪問頻率高的行字段越少,就可以在緩存裏緩存更多的行,性能就越好。這個一般在表層面做的較多一些。

在這裏插入圖片描述

3. 如何把系統遷移到分庫分表

       倘若我們的系統之前採用單臺MySQL實例的方案,現在要將其進行分庫分表,那麼表中的數據應該如何進行遷移,同時不能對用戶造成干擾。

在這裏插入圖片描述
       遷移過程如上圖所示,後臺將數據遷移完成後,替換掉之前讀寫舊數據庫的代碼即可。

4. 分庫分表後全局 id 如何生成

       在單實例的情況下,我們通常都是採用自增主鍵的方式進行 id 的生成,這樣做到好處是,數據 id 向增大的方向生成,可以避免隨機生成帶來數據頁的頻繁裂化,降低MySQL的效率。

       如果我們根據id對數據進行分庫分表,如果每張表依然開啓主鍵自增,顯然是不夠合適的。每張表中可能會出現id相同的數據,這樣情況顯然是不被允許的。

       之前在實習的過程中,是這樣做到,調用一個RPC的方法,專門用於生成全局唯id

       現在讓我們研究一下全局id應如何生成。

4.1 數據庫自增 id

       這裏的數據庫自增 id ,並不是指開啓分庫分表的自增。而是單獨搞一張表,用於生成id。每次有新的數據插入,都訪問這張表,獲取自增後的id,作爲分庫分表後的數據id,如此便一定能保證全局唯一id

create table t_generateId(
	id bigint primary key auto_increment 
);

在這裏插入圖片描述

       該方案適用於併發量很低的情況,我們做分庫分表,就表明併發量較高了。如果生成id的這臺MySQL實例不能頂得住過多的寫請求,很容易造成整個系統的宕機。

4.2 uuid

       前面說了,選擇主鍵時,通常會讓其向一個方向進行增長,這樣可以避免數據頁的頻繁裂化及合併。

       而uuid增完全是隨機的,很容易造成上述情況,所以並不推薦使用。

       其主要用於設置文件名,如我們QQ截圖時,可以用uuid作爲截圖後的文件名。

4.3 系統當前時間戳

       時間戳比uuid的好處時,其數據是朝一個方向進行增長的。到那時如果併發量很高的時候,同一時刻有多個請求,顯然是不合適的。

       適合的場景:一般如果用這個方案,是將當前時間跟很多其他的業務字段拼接起來,作爲一個id,如果業務上你覺得可以接受,那麼也是可以的。你可以將別的業務字段值跟當前時間拼接起來,組成一個全局唯一的編號,訂單編號,時間戳 + 用戶id + 業務含義編碼。

4.4 SnowFlask

       SnowFlask

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章