Sharded table中的每條記錄通過 Hash(row) % #shardmap entry 來決定記錄存儲到哪個shardid,通過查詢shardmap的存儲的DN。
每個DN上存儲分配到本節(jié)點shardid信息,進而進行可見性的判斷。
通過上面的方案,在擴容新加節(jié)點時,就只需要把一些shardmap中的shardid映射到新加的節(jié)點,并把對應的數(shù)據(jù)搬遷過去就可以了。擴容也僅僅需要切換shardmap中映射關系的,時間從幾天縮短到幾秒。

圖5
四.數(shù)據(jù)傾斜解決方案
數(shù)據(jù)傾斜是指,在分布式數(shù)據(jù)庫系統(tǒng)中會因為物理節(jié)點、hash或shard分布原因,導致某些DN物理空間不足,而另外的物理空間剩余較大。例如,如果以商戶作為分布key,京東每天的數(shù)據(jù)量和一個普通電商的數(shù)據(jù)量肯定是天地差別??赡苣硞€大商戶一個月的數(shù)據(jù)就會把一個DN的物理空間塞滿,這時系統(tǒng)只有停機擴容一條路。因此我們必須要有一個有效的手段來解決數(shù)據(jù)傾斜,保證在表數(shù)據(jù)分布不均勻時系統(tǒng)仍然能夠高效穩(wěn)定的運行。
首先我們把系統(tǒng)的DN分為group(如下圖6),每個group里面:
包含一個或者多個DN
每個group有一個shardmap
在建sharded表時,可以指定存儲的group,也就是要么存儲在group1,要么group2
CN可以訪問所有的group,而且CN上也存儲所有表的訪問方式信息

圖6
對于系統(tǒng)中數(shù)據(jù)量較大用戶進行特別的識別,并為他們創(chuàng)建白名單,使用不同的數(shù)據(jù)分布邏輯(如下圖7):普通用戶使用默認的數(shù)據(jù)分布邏輯,也就是:
Shardid = Hash(merchantid) % #shardmap
大商戶使用定制的數(shù)據(jù)分布邏輯,也就是:
Shardid = Hash(merchantid) % #shardmap + fcreate_timedayoffset from 1970-01-01

圖7
通過在大商戶group分布邏輯中加入日期偏移,來實現(xiàn)同一個用戶的數(shù)據(jù)在group內(nèi)部多個節(jié)點間均勻分布。從而有效的解決數(shù)據(jù)分布不均勻問題。
下面是一個例子(如下圖8):

圖8
五.9000W記錄高效排序解決方案
業(yè)務在列表查詢場景下會收到如下的查詢SQL:

在微信支付的場景中,某個商戶每天的數(shù)據(jù)有300W,一個月數(shù)據(jù)超過9000W條,也就是說PostgreSQL需要面向一個9000W數(shù)據(jù)級數(shù)據(jù)進行快速排序,而且業(yè)務邏輯要求需要秒級輸出,快速獲取排序結(jié)果。

為此,我們提供表定義方案,即建立集群分區(qū)表。根據(jù)上述需求,可以采用按月分表,即每個月一張表,并對排序字段ffinish_time建立索引,這樣每個分區(qū)進行掃描是可以使用索引。

我們再通過一系列執(zhí)行計劃的優(yōu)化,CN下推order by和limit offset子句到DN;DN上在執(zhí)行對應的sql使用使用Merge Append算子對各個子表執(zhí)行的結(jié)果進行匯總輸出,這個算子本身會保證輸出是有序的,也就是說對子表進行索引掃描,同時Merge Append又對各個子表的結(jié)果進行歸并,進而保證節(jié)點本身的結(jié)果是排序的。CN對多個DN的結(jié)果同樣使用Merge Append進行歸并,保證整個輸出結(jié)果是有序的,從而完成整個排序過程。

下面是我們對排序進行的性能測試結(jié)果:

