Gpexpand是Greenplum數據庫的擴容工具,可以為集群增加新節點從而可以存儲更多的數據,提供更高的計算能力。Greenplum 5及之前,集群擴容需要停機增加新節點,然后對表數據做重分布。因為集群大小已經改變,所以重分布之前要先將所有哈希分布表改成隨機分布,然后再按照新的集群大小重新計算哈希值並重新分布。
所以,舊的擴容技術存在如下幾個問題:
1. 需要停機,集群無法在擴容期間提供服務。
2. 數據重分布過程集群性能差。隨機分布表因為不能確定數據分布規律,無法對查詢做優化。
3. 雖然表的重分布可以並行進行,但是擴容過程中因為額外記錄了每個表的更新狀態,在對表做完重分布后要更新狀態表。Greenplum 6版本之前表的更新操作只能串行。所以對大量小表做並行重分布的時候會因為狀態表更新的串行化產生瓶頸。
全新設計的gpexpand支持在線擴容,同時對數據重分布過程做了優化,提高了並發度。整個擴容分為兩個階段:
1. 在線增加新節點
2. 數據重分布
如何在線增加新節點
Greenplum通過catalog表gp_segment_configuration維護集群節點信息。所以在線增加節點並不復雜,只要更新這個系統表即可:首先以master數據庫目錄為模板創建新的子節點,然后更新gp_segment_configuration表。新節點沒有用戶數據,只有catalog數據,這些數據在master節點上都有。
因為是在線擴容,這里有幾個問題:
1. 新節點加入后,哈希分布的數據表還是按照舊集群的大小進行哈希分布。對這樣的表怎么處理
·正在運行的事務
·新事務
2. 擴容過程中,catalog更改操作(建表,刪表,改表)如何處理
問題 1
為了解決這個問題,我們在catalog表gp_distribution_policy里引入了一個新的屬性,numsegments。它描述了該表分布在哪些節點上,n表示分布在前n個節點上。同時優化了執行查詢的工作進程的數量管理策略,可以指定在哪些節點上啟動執行查詢工作進程。所以,即使集群添加了新節點,但是未數據重分布的表仍然只分布數據在集群的舊節點上,並且分布策略不變。所以,無論是正在運行的事務,還是新事務,如果numsegments沒有改變,則查詢執行進程依然只運行在集群的舊節點上,新節點上沒有工作進程。
對於新創建的表,則會獲取最新集群大小,應用到所有節點上,numsegments值與最新集群大小相同。對該表執行的DML操作,也會應用到所有節點上。
問題 2
擴容期間如果catalog發生變化,則會導致不一致:catalog的變化只應用到了老節點,和新節點上的catalog數據不一致。
為了保證擴容期間catalog的一致性,Greenplum 6引入了catalog鎖,在增加新節點階段,防止對catalog執行修改操作。新節點加入到集群后,該catalog鎖被釋放。通常添加新節點操作比較快,所以對catalog操作的影響不大。
對於只存在於master上catalog表,如gp_segment_configuration、pg_statistic等,新加入的數據節點會做適當的清理。
數據重分布
表的重分布過程就是將表的數據從舊的集群節點,重新分布到新的集群節點上。重分布后更新numsegments,之后的所有事務會按照新的分布來處理了。在重分布過程中會對表加ACCESS_EXCLUSIVE_LOCK鎖,所有對表的操作都會被阻塞。完成某張表的數據重分布后,操作該表的SQL將被調度到集群的所有新舊節點上執行。
重分布的優化
哈希分布計算方法雖然簡單,但是在重分布的過程中,由於集群大小發生了變化,需要按照新的集群節點數目重新計算哈希,數據幾乎要完全重新分布,移動數據量巨大,導致重分布過程效率較低。假設原來有N個節點,每個節點上分布1/N的數據,擴容后M個節點,每個節點上分布1/M的數據。理想的情況是,每個舊節點移動出1/N - 1/M的數據到新節點上,從而整體移動量是N(1/N - 1/M) = 1 - N/M。
Greenplum 6采用了一種叫做Jump Consistent Hash的一致性哈希算法。
該算法有如下特點:
1. 均勻性:通過概率做到均勻分布。
2. 穩定性:在相同集群大小下,同一個Tuple每次計算結果相同。
3. 單調性:擴容過程中,舊節點之間沒有數據遷移。
4. 高效性:對於集群大小為N的時候,時間復雜度為Log(N)。
更多算法細節請參考鏈接。https://arxiv.org/pdf/1406.2294.pdf
重分布的並行化
在Greenplum 5上,HEAP表的更新刪除操作是最高級別的鎖,相當於完全是串行化。做數據重分布的過程中,要在一張HEAP表中記錄數據庫中每個表的重分布狀態,所以在做數據重分布的過程中,雖然做了並行化,但是更新狀態表的時候仍然是串行的。即使更新狀態表的操作很短暫,對於大量小表的並行重分布依然會成為瓶頸。在Greenplum 6里,因為增加了分布式死鎖檢測,所以更新刪除表的鎖級別已降低,支持並發更新刪除操作。對於大量小表做並行重分布性能提升明顯。
重分布期間對查詢性能的影響
重分布過程中,不可避免的會存在某些表已經重分布完畢、某些表還未做重分布。對於處於相同分布狀態的表,在分布列上做JOIN查詢,不需要做數據重分布;否則,需要進行數據重分布。
FAQ
1. 如何控制哈希分布算法
通過GUC gp_use_legacy_hashops 可以控制,默認是Jump Hash算法。
2. 擴容過程中新舊節點的catalog是一致的嗎
catalog始終是一致的,新節點上即使還沒有數據,但是catalog也是存在的。
3. 擴容過程中對於其他查詢的影響
因為是在線擴容,期間不會中斷正在運行的所有查詢,只是在增加新節點的時候因為要鎖catalog,所以在此期間不支持DDL,加完新節點立即釋放catalog鎖。
在數據重分布的時候因為加了最高級別的鎖,對正在重分布的表的訪問會阻塞。