分佈式數據分佈及數據庫分庫分表

分佈式需求:

1、流量需求:
隨着數量的變大,要求系統的性能和內存也會變高,最簡單的方法就是需要一臺性能超級強悍能抗上千萬併發,能存儲千億級別的數據,但是這是不可能的,就算可能也是需要昂貴的成本,所謂一個諸葛亮錘不過三個臭皮匠,分佈式就應運而生了。主從複製分離讀寫、負載均衡分散流量、垂直擴容縱向擴容、消息隊列緩衝流量、緩存、限流削峯等手段實現大流量的承載
2、分佈式一致性需求:
針對以上的需求,所以最簡單的方法就水平擴展機器,利用增加機器的方式,集羣處理。一匹馬拉不動就一羣馬拉,這個就是分佈式要達到的目的,但是分佈式就要涉及數據的分佈,事務的一致性等諸多問題,就如同如何訓練好馬羣的方向和整體方向一致,避免馬羣不能同心協力馬都向不一樣的方向跑的尷尬局面。

分佈式一致性主要有:2PC、3PC、基於XA的事務、ZAB協議、基於消息性事務、TCC事務補償等
數據分佈式主要有:哈希取模、一致性哈希、虛擬節點、順序分佈等


分佈式的數據分佈方法

分佈式分佈主要方法有兩個:哈希分佈和順序分佈

一、哈希分佈

哈希分佈就是將數據計算哈希值之後,按照哈希值分配到不同的節點上。例如有 N 個節點,數據的主鍵爲 key,則將該數據分配的節點序號爲:hash(key)%N

哈希分佈算法存在一個問題:當節點數量變化時,也就是 N 值變化,那麼幾乎所有的數據都需要重新分佈,將導致大量的數據遷移。

解決方案:

1、節點翻倍擴展

翻倍擴展節點,差不多隻需要50%的數據需要遷移,減少遷移的數據量
缺點:但是這個方案的遷移的數據量50%,如果是數據規模特別大的應用,這個方案也就不適合了

2、一致性哈希算法

  • 1.將整個哈希值空間組織成一個虛擬的圓環,如假設某哈希函數H的值空間爲0-2^32-1,整個哈希空間環就是下圖中的黑色圓環

  • 2.對每個服務器的唯一識別標誌(IP或者主機名)求hash值,將得到的值放入第一步的圓環中對應的位置。如下圖的node1 node2 node3 node4

  • 3.對要保存的數據的key求hash值,將得到的值落入圓環中,就是下圖的黃色圓圈,然後在圓環中順時針找到最近的node(服務器的唯一識別標誌(IP或者主機名)求hash值落在圓環中所在的點),該數據就存儲在該node中

這時增加了一個節點node5,通過hash後落在瞭如圖的位置,這時我要遷移的數據就只是,由於這個環要符合順時針的順序,所以需要遷移的數據只是node1節點和node5節點之間的數據,而不會影響其他的節點的數據

缺點:
1、一致性哈希解決了數據遷移量大的問題,但只是減輕了插入節點順時針開始遇到的第一個機器負擔,對於其他的節點並未起到減輕負載的作用。
2、服務節點太少時,數據分佈不夠均勻,容易因爲節點分部不均勻而造成數據傾斜問題。

3、虛擬節點算法

這個主要是解決了一致性哈希的負載性差,數據分佈不夠均勻的問題,是一致性哈希的改進

假設我們部署了cache A 節點和 cache C節點 。現在我們將cache A 節點虛擬成如圖的cache A1和cache A2,將cache C節點虛擬成如圖的cache C1和cache C2,一共存在 4 個虛擬節點, hash(objec1)=key1->cache C2 ;hash(objec2)=key2->cache A1 ; hash(objec3)=key3->cache C1 ; hash(objec4)=key4->cache A2 ;因此對象 object4 和 object2 都被映射到了 cache A 上,而 object3 和 object1 映射到了 cache C 上。由於節點虛擬後節點相對分散,因此負載性和數據分佈均勻性得到了提升

二、順序分佈:

順序分佈的數據劃分爲多個連續的部分,按一定順序分佈到不同節點上,可支持順序訪問。

缺點:數據的分佈均勻性,容易造成節點的數據傾斜。例如:按照上面的例子,順序分佈假設每個節點最多存33個數字,那麼此時需要4個節點,節點1存數字1~ 33,節點2存數字34 ~ 66,節點3存數字67 ~ 99,節點4存數字100.

哈希分佈與順序分佈的區別特點

數據庫的分庫分表

主從數據庫主要是分擔了數據庫的讀壓力,分庫分表主要解決數據庫寫的壓力,基於分佈的橫行擴展對數據庫進行架構的拆分包括:垂直分庫、水平分庫、垂直分表、水平分表。

一、分庫:

使用MyCat其實會更有效率,並且能解決分庫後的路由問題,下面的分庫的原理

垂直分庫:

可以把多個表按業務耦合度歸類,分別存放在不同的庫,這些庫可以分佈在不同服務器,從而使訪問壓力被多服務器負載,大大提升性能,同時能提高整體架構的業務清晰度,不同的業務庫可根據自身情況定製優化方案。但是它需要解決跨庫帶來的所有複雜問題(一般使用MyCat)。

如圖主要講一個數據庫的表分散到不同的節點上

水平分庫:

可以把一個表的數據(按數據行)分到多個不同的庫,每個庫只有這個表的部分數據,這些庫可以分佈在不同服務器,從而使訪問壓力被多服務器負載,大大提升性能。它不僅需要解決跨庫帶來的所有複雜問題,還要解決數據路由的問題(一般使用MyCat)

水平分庫全局還要解決的就是全局的自增id,全局自增id就是需要被hash計算的那個值,這個值需要保證不重複,可以使用redis生成,也可以使用MyCat解決

水平分庫是把同一個表的數據按一定規則拆到不同的數據庫中,每個庫可以放在不同的服務器上。

二、分表

當表的數據量達到一定量級後需要對錶進行垂直拆分和水平拆分

垂直分表:

垂直拆分是指數據表列的拆分,把一張列比較多的表拆分爲多張表。表的記錄並不多,但是字段卻很長,表佔用空間很大,檢索表的時候需要執行大量的IO,嚴重降低了性能。這時需要把大的字段拆分到另一個表,並且該表與原表是一對一的關係。

通常我們按以下原則進行垂直拆分原則:

  • 1、把不常用的字段單獨放在一張表;
  • 2、把text,blob等大字段拆分出來放在一張表中;
  • 3、把經常組合查詢的字段放在一張表中;
  • 4、拆分的表要一對一關係

水平分表:

水平拆分是爲了解決單表數據量過大的問題,表的行數超過百萬行時,再完美的優化也是無濟於事,這時可以把一張的表的數據拆成多張表來存放。
方法:hash(id)%N
通常是對錶中的id進行hash運算,然後進行取模,拆成多少個表就取多少模,例如將表拆成5個,就是hash(id)%5

MyCat垂直分庫演示

條件有限,下面是截取慕課教程視頻的圖,需求就是把node1的imooc_db這個庫進行垂直分庫,將其分散到下面到下面的node2的order_db庫,node3的product_db庫,node4的customer_db庫去,分庫後數據庫的邏輯庫名依舊是imooc_db,這裏Mycat服務器和node1同一個服務器
  • 1、下面先配置各個節點的邏輯庫和邏輯表,在schema.xml文件配置

    進入MyCat的conf文件夾修改schema.xml,先配置物理節點的地址<dataHost>和<dataNode>數據庫節點的名稱,及各個庫的用戶名密碼邏輯庫名稱可以和數據庫名稱不一樣(一般和原來的那個一樣,這樣代碼中的sql就不用修改),配置邏輯表,邏輯表的名字要和節點上的數據庫的表名一樣
  • 2、配置MyCat的端口、用戶、密碼加密、邏輯數據庫名稱,在server.xml中配置

    在server.xml中配置
  • 3、啓動MyCat

    利用mysql登錄MyCat查看邏輯庫
    查詢時都是通過MyCat,用起來和沒分庫之前是沒什麼區別的
  • 4、全局表創建:但是MyCat的跨分區能力很差,通常像字典表這樣關聯查,跨分區非常不友好,我們需要建立全局表,在原來的schema.xml中加上這個配置

MyCat水平分庫演示

需求是把MyCat服務器設置在node1中,需要對訂單表order_master水平分庫到node2的order01和order02,node3的order03和order04
  • 1、schema.xml中配置物理節點的地址<dataHost>和用戶名密碼,這裏爲什麼要把MyCat所在的節點也配進去呢,主要是用於後面用MyCat提供的數據庫方式的全局自增id功能

    配置要分片的庫填寫邏輯表及分片規則的名稱,這個一般和垂直分庫混合配
  • 2、水平分片時才需要配置算法。配置分片算法,根據在schema.xml配置的算法名稱,配置rule.xml文件,算法是MyCat提供的類<class>,<count>分多少個庫就配多
  • 3、server.xml和垂直分庫的時候一樣的,先對MyCat的密碼進行加密,然後填寫MyCat啓動端口、用戶名密碼,邏輯庫名稱等,但是sequnceHandlerType需要改,

    sequnceHandlerType有四值如下:

0 爲本地文件方式,1 爲數據庫方式,2 爲時間戳序列方式,3 爲分佈式ZK ID 生成器,4 爲 zk 遞增 id 生成。

現在通過數據庫方式生成全局id,創建一個數據庫mycat

一般在MyCat所在的節點數據庫創建,然後在conf中找到dbseq.sql文件,將其導入mycat數據庫dbseq.sql文件是創建了MYCAT_SEQUENCE表和4個函數mycat_seq_setval、mycat_seq_nextvals、mycat_seq_nextval、mycat_seq_currval,這個表是用於全局自增id的在schema.xml中增加一個節點配置

然後修改配置文件sequence_db_conf.properties,這裏是我們剛剛配置的節點名稱叫mycat:執行sql插入要自增的字段的配置,並且是從1開始將schema.xml中的分片表標籤添加autoIncrement="true":
  • 4、重啓mycat,利用mysql登錄MyCat,插入數據,然後查詢用起來是和沒分片是沒有什麼區別的,插入兩條數據然後對id 2808驗證,利用函數對2808進行hash取模發現得0,意思是這個數據是實際插入到了order01的庫中
  • 5、

    又是跨分片的關聯需要解決,分片表一般比較大,使用全局表一般會插入比較頻繁,所以需要建立er分片,需要在所有的節點上創建關聯的表,這裏我們關聯的是order_detail表各個分片都創建一次這個order_detail表修改schema.xml中的配置,將之前order_detail節點的信息去除,在order_master節點中添加子節點order_detail節點:再次修改配置文件sequence_db_conf.properties添加order_detail節點

    執行SQL插入要自增的字段配置,剛剛我們配置了ORDER_DETAIL
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章