大規模資料儲存叢集資料存放的設計,分散式shardid的生成-如何指定範圍隨機數,分組隨機數
標籤
PostgreSQL , 分組ID生成 , 生成雜湊對映 , sharding , shard
背景
在一些分散式資料庫系統中,通常會有多個資料節點,使用者的資料分佈策略通常有一致性雜湊、按列雜湊、隨機分佈等。
除了隨機分佈,其他的分佈方法資料和資料節點是一對一的關係。
上當節點數變得特別特別多的時候,資料如果依舊按照全域性進行雜湊分佈,可能會帶來一個問題,例如節點數到達1萬個,一張1億的表,會分佈到1萬個節點中,那麼多個表進行JOIN時,會涉及到1萬個節點的運算,這裡面可能還涉及節點和節點之間的互動,網路會話也會特別的多。
實際上並不是每張表都需要分佈到1萬個(所有節點)的。如何解決節點數過多的問題呢?如何讓資料落到某些節點,而不是所有節點。這樣可以使得叢集更加龐大。
例如HDFS,通過NAME NODE來記錄每個BLOCK在什麼機器上。
NAME NODE的問題是,當叢集特別大的時候,NAME NODE會成為瓶頸,不利於擴充套件。
還有一些方法可以解決大叢集的問題,例如多級資料節點、分組資料節點。
大叢集的分組設計舉例
計算節點分組
例如有1萬臺主機,對應一萬個資料庫單元,劃分為一些分組,例如每100個主機(資料庫例項),一共100個分組。
當然,不一定要求每個分組的主機數一致。
給每個資料庫例項一個唯一編號。
1、例子1,如果每個分組的主機數固定,通過這種方法,可以得到某個分組內的一個隨機ID。
(適合這樣的場景,我已經知道某個表應該在哪個分組內,然後這個表在這個分組內是隨機存放的,那麼通過這種方法,可以得到一個組內隨機的主機ID)
create or replace function get_gp_rid1(gid int, gsz int) returns int as $$
select gsz*gid + (ceil(random()*gsz))::int;
$$ language sql strict;
隨機概率如下
postgres=# select id, count(*) from (select get_gp_rid1(0,10) id from generate_series(1,10000) ) t group by 1 order by 1;
id | count
----+-------
1 | 949
2 | 965
3 | 1012
4 | 1064
5 | 1029
6 | 970
7 | 964
8 | 1035
9 | 1018
10 | 994
(10 rows)
postgres=# select id, count(*) from (select get_gp_rid1(1,10) id from generate_series(1,10000) ) t group by 1 order by 1;
id | count
----+-------
11 | 993
12 | 1023
13 | 986
14 | 981
15 | 978
16 | 994
17 | 1002
18 | 1019
19 | 976
20 | 1048
(10 rows)
postgres=# select id, count(*) from (select get_gp_rid1(2,10) id from generate_series(1,10000) ) t group by 1 order by 1;
id | count
----+-------
21 | 1009
22 | 985
23 | 988
24 | 1040
25 | 988
26 | 1065
27 | 986
28 | 957
29 | 993
30 | 989
(10 rows)
postgres=# select id, count(*) from (select get_gp_rid1(2,10) id from generate_series(1,10000000) ) t group by 1 order by 1;
id | count
----+---------
21 | 999704
22 | 999015
23 | 1001106
24 | 999979
25 | 999599
26 | 999417
27 | 1000242
28 | 1000675
29 | 999423
30 | 1000840
(10 rows)
Time: 4629.229 ms
2、例子2,對於組的機器數不一致,但是主機ID連續的場景,可以使用這種方法得到一個組內的隨機ID。
create or replace function get_gp_rid2(f int, c int) returns int as $$
select f - 1 + (ceil(random()*(c-f+1)))::int;
$$ language sql strict;
隨機分佈均勻
postgres=# select id, count(*) from (select get_gp_rid2(2,10) id from generate_series(1,10000000) ) t group by 1 order by 1;
id | count
----+---------
2 | 1111981
3 | 1112798
4 | 1110522
5 | 1111070
6 | 1111159
7 | 1109720
8 | 1109822
9 | 1111450
10 | 1111478
(9 rows)
Time: 4631.884 ms
3、例子3,組的機器數不一致,同時主機ID不連續,可以通過這種方法得到一個組內的隨機ID。
create or replace function get_gp_rid3(id int[]) returns int as $$
select id[ceil(array_length(id,1)*random())];
$$ language sql strict;
資料分佈均勻
postgres=# select id,count(*) from (select get_gp_rid3(array[1,2,3,4,5,7,8,9,100,199]) id from generate_series(1,1000000)) t group by 1 order by 1;
id | count
-----+--------
1 | 100898
2 | 99818
3 | 99434
4 | 100085
5 | 100461
7 | 100361
8 | 99725
9 | 100002
100 | 99646
199 | 99570
(10 rows)
表和分組的對映關係
表和分組的對映關係,可以使用類似name node的方法。
因為分組數可能發生變化,不推薦使用一致性演算法類的MAPPING方法,確保表不需要隨著分組的變化而變化。
分組內資料分佈設計
1 完全隨機分佈
如果資料在分組內完全隨機分佈,那麼就可以像前面寫的幾個函式那樣,獲得分組內主機的隨機ID。
2 虛擬BLOCK分佈
首先需要將資料存放規劃為虛擬BLOCK聚集的方式(例如100000條記錄一個BLOCK,舉例而已)。每個BLOCK有對應的編號。
每個BLOCK落在不同的資料庫例項(主機)中,這個對映關係依舊建議使用類似name node的方法。
因為分組內的主機(資料庫例項)數可能發生變化,不推薦使用一致性演算法類的MAPPING方法,確保表不需要隨著分組內主機(資料庫例項)數的變化而變化。
資料記錄和虛擬BLOCK的關係
1、雜湊,例如按某列進行雜湊,根據雜湊值決定記錄寫入哪個BLOCK。
建議使用一致性雜湊分佈,確保在擴充套件或收縮BLOCK數量時,資料的移動最小。
2、範圍,適合自增、時間、序列等型別,例如每100000一個block,等等。
3、固定雜湊,這種方式比較暴力,例如一開始就設計好一個固定的雜湊數,如65536。
固定雜湊的擴容不太方便,擴容時移動的資料可能較多。建議按2的N或者N的N次方雜湊和擴容。這樣的話,擴充套件只是分裂BLOCK,也蠻簡單的。
虛擬BLOCK的遷移
採用NAME NODE記錄了BLOCK和分組內主機的對映關係,因此MOVE block也變得很簡單,只要移動,並更新NAME NODE。
小結
要管理特別大的叢集,資料分佈只是其中很小的一個部分。
但是資料分佈是一個非常重要的緩解,分佈規則沒有涉及好,可能導致將來擴充套件、遷移、效能、穩定性等帶來不便。
分組是一個將大化小的方法,因為往往一個業務、或者一個表,不需要離散到所有主機。離散到過多的主機上可能會導致連線、資料重分佈,資料JOIN等一些問題。
通常的做法是將需要JOIN,或者同類業務的資料,儘量分佈到同樣的主機分組中。確保在進行資料分析時,資料的移動較小。
相關文章
- java生成指定範圍的隨機數Java隨機
- 在指定範圍內生成隨機數隨機
- [隨機數詳解]生成一個隨機數,生成指定範圍的隨機數及隨機陣列去重隨機陣列
- 如何產生指定範圍的隨機數隨機
- MATLAB中如何生成指定範圍的隨機整數向量Matlab隨機
- 如何生成指定分佈的隨機數隨機
- jquery簡單生成指定範圍隨機數效果jQuery隨機
- 生成某個範圍的隨機數隨機
- 隨機範圍小數和隨機範圍整數隨機
- C語言程式生成指定範圍的不重複的隨機數C語言隨機
- MATLAB中如何產生指定範圍的隨機數Matlab隨機
- 生成總和固定 可變範圍的隨機數隨機
- 崑崙分散式資料庫儲存叢集 Fullsync 機制分散式資料庫
- 如何隨機生成一個大表的資料隨機
- js生成一定範圍內的隨機整數JS隨機
- 生成指定區間的隨機小數隨機
- SQL Server當中生成一定範圍的隨機數SQLServer隨機
- MySQL取得某一範圍隨機數MySql隨機
- 生成隨機數隨機
- Django Models隨機獲取指定數量資料方法Django隨機
- mysql迴圈插入資料、生成隨機數及CONCAT函式MySql隨機函式
- java 生成一個隨機整數,範圍從 1 到 10Java隨機
- Python如何隨機生成1到100的隨機數?Python隨機
- python生成隨機數、隨機字串Python隨機字串
- 資料倉儲(7)數倉規範設計
- 隨機變數函式的分佈隨機變數函式
- javascript生成指定位數隨機數程式碼例項JavaScript隨機
- JavaScript 生成隨機數JavaScript隨機
- mysql生成隨機數MySql隨機
- 更安全的隨機數生成隨機
- PHP 生成更好的隨機數PHP隨機
- Matlab 隨機生成兩個數值之間的隨機數Matlab隨機
- Matlab產生特定範圍的隨機數矩陣Matlab隨機矩陣
- (轉)Oracle的隨機數、隨機日期和時間、隨機字串及造資料匿名過程Oracle隨機字串
- MySQL建立隨機生成電話的儲存函式MySql隨機儲存函式
- 機器學習演算法的隨機資料生成機器學習演算法隨機
- python 隨機生成字串資料Python隨機字串
- 從資料集中隨機抽取一定數量的資料隨機