您好,登錄后才能下訂單哦!
本篇內容主要講解“relocating對Elasticsearch集群的影響是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“relocating對Elasticsearch集群的影響是什么”吧!
分片移動結束后,target 節點會向 master 發起一個 shard-started PRC,該 RPC 具有次高優先級:URGENT, master 對該 RPC 的處理比較慢,尤其是在集群分片數量到幾萬的級別,從而可能導致一些較低優先級的 RPC 長時間來不及執行,例如 put-mapping,進而導致對業務的明顯影響。
由于 rebalance,allocation filtering,forced awareness等任意原因產生的 shard-started RPC 都會存在這個問題,例如擴容集群的時候,如果把 rebalance 并發開的比較大,對 master 的處理能力造成明顯影響。因此對于分片數較多的集群,當你想要加大 rebalance 和 recovery 并發的時候要考慮到對 master 的影響。
當一個主分片被 rebalance 或者手工 move 的時候,可以想象必然存在一個時間段該主分片無法寫入。
Elasticsearch 對主分片的 relocating 也是直接 move,不會先將主分片資格讓給其他副分片,再進行 move,即便如此,也會存在一個時間點進行切換,無法響應寫入。
這個時間段從 RPC 的時序來看的話,如下圖所示,紅色標記的區域為阻塞寫入流程的時間段。在該時間段內,客戶端的寫入請求會被阻塞無返回,直到這部分處理完成。
?
以手工 move 為例,當一個主分片從 node-idea move 到 node1時,主要有以下幾個階段完成:
首先會通過發布新的集群狀態,將該分片標記為 RELOCATING狀態,更新 routing_table 和 routing_nodes
數據節點收到集群狀態后,開始執行 recovery 流程,該流程自 target 節點發送 start_recovery開始,至 Source 階段返回 start_recovery response 結束。
recovery 完成后,target發送 shards-started RPC 給 master 節點,master 節點再次下發集群狀態,將該分片標記為 STARTED 狀態。
阻塞客戶端 bulk 寫入的階段,就在 source 節點執行 finalize 階段時,準備發送 handoff RPC 時開始,直到收到 master 新的集群狀態,將該分片標記為 STARTED,每個節點應用集群狀態的時間點略有差異,所以每個節點停止阻塞寫入的時間點也會有微小差異。
handoff 的 RPC的作用是告知 target 節點該分片可以切換主分片狀態,對 handoff RPC 的處理都是一些計算操作,其中涉及到幾個鎖,一般會很快完成。
整個主分片的 relocating 過程對寫入的影響是很復雜的處理過程,我將他們劃分為幾個階段,下面是詳細過程。
在分片的整個 relocating 過程中,對 target 節點的請求都會被轉發到 source 節點,直到 target 節點應用了 master 下發的分片變為 STARTED 的集群狀態。
起初,寫入請求到達 source 節點,像往常一樣正常寫入到主分片中,直到復制階段。
此階段將收到的寫請求復制給 target 節點。他從收到 prepare_translog 的 response之后開始,直到 handoff 階段開始之前。
1.將 target 分片加入到 replication group
收到 prepare_translog response之后,recovery 的 phase1階段已結束,segments 文件發送完畢,target 節點的 engine 已啟動。通過 shard.initiateTracking將 target 分片加入到復制組,后續的寫入操作都會復制給 target 節點。
prepareEngineStep.whenComplete(prepareEngineTime -> {
runUnderPrimaryPermit(() -> shard.initiateTracking(request.targetAllocationId()),
shardId + " initiating tracking of " + request.targetAllocationId(), shard, cancellableThreads, logger);
final Translog.Snapshot phase2Snapshot = shard.getHistoryOperations("peer-recovery", historySource, startingSeqNo);
});
復制組信息在 ReplicationTracker 的 replicationGroup成員中維護。
2.在寫入過程中,將寫請求復制給 target
在寫入流程的 performOnPrimary#doRun() 函數的 finishRequest方法中,最終調用 ReplicationOperation#handlePrimaryResult函數的 performOnReplicas方法將 index 發送給 target 節點。
handoff階段是為了完成主分片狀態的轉移,該階段對收到的寫入請求放到隊列中,待主分片狀態轉移完成后繼續執行,最多阻塞30分鐘。期間對 target 節點的寫入也會被轉發的 source 節點執行。此階段從 source 節點收到 finalize 的 response之后開始,直到下一階段。
1.recovery 過程設置阻塞標記
在 source 節點收到 finalize 的 response之后,通過 handoff RPC 交接主分片狀態,這個交接過程通過 indexShardOperationPermits.blockOperations 對此時收到的寫入請求進行阻塞,最多30分鐘。
public void relocated(final String targetAllocationId, final Consumer<ReplicationTracker.PrimaryContext> consumer){
try {
indexShardOperationPermits.blockOperations(30, TimeUnit.MINUTES, () -> {//block 的范圍就是這段括號里的代碼
final ReplicationTracker.PrimaryContext primaryContext = replicationTracker.startRelocationHandoff(targetAllocationId);
try {//下面調用 RemoteRecoveryTargetHandler.handoffPrimaryContext
consumer.accept(primaryContext);//執行這里之后發送和響應了 handoff_primary_context RPC
}
});
}
}
indexShardOperationPermits.blockOperations 中的阻塞操作只是 queuedBlockOperations 加1,后面寫入流程會檢查 queuedBlockOperations 的值是否為0
2.寫入流程的處理
產生在寫入鏈路的 acquire函數:
acquire:255, IndexShardOperationPermits (org.elasticsearch.index.shard)
acquirePrimaryOperationPermit:2764, IndexShard (org.elasticsearch.index.shard)
handlePrimaryRequest:256, TransportReplicationAction
該函數判斷 queuedBlockOperations 大于0,于是將他添加到 delayedOperations,寫入流程到此結束。delayedOperations中的操作會在本階段的阻塞過程結束后處理。
失敗重試階段自source 節點處理完 handoff response之后開始,直到 master 下發了將分片標記為 STARTED 的集群狀態,數據節點應用了集群狀態之后結束,在應用這個集群狀態之前,分片處于 relocating 狀態,期間的寫入操作由 source 節點執行,并且會寫入失敗,拋出 ShardNotInPrimaryModeException 異常,并捕獲該異常,等待1分鐘后重試寫入,再次失敗則退出;如果1分鐘內收到了新的集群狀態,也會重試寫入,然后寫入成功。
寫入流程中,執行 acquire 函數時,發現 queuedBlockOperations為0,執行onAcquired.onResponse(releasable),調用到 wrapPrimaryOperationPermitListener函數時,發現分片已經不是主分片狀態,拋出 ShardNotInPrimaryModeException 異常。
if (replicationTracker.isPrimaryMode()) {
l.onResponse(r);
} else {
r.close();
l.onFailure(new ShardNotInPrimaryModeException(shardId, state));
}
對于上者返回的異常,寫入流程 acquirePrimaryOperationPermit 設置的 Listener會區分異常類型,如果是 ShardNotInPrimaryModeException 異常,則等待1分鐘后進行重試。
副分片的 move 過程與主分片的 move 過程相似,也是下發兩次集群狀態,通過 recovery 復制到 target 節點。
需要注意的是,recovery 復制分片到 target 節點,并非從副分片當前所在節點復制到 target,而是從主分片復制到 target。例如,主分片在節點 node-idea 上,副分片在 node-1,當我們從 node-1 move 到 node-2時,recovery 是從 node-idea 復制到 node-2。當 node-1應用主節點發布的分片狀態變為 STARTED 的集群狀態時,發現分片已經屬于自己,于是刪除本節點的分片。
與主分片的 relocating 類似的是,在復制階段,會將正在 recovery 的分片添加到 replication group,這樣 replication group 中就有了三個分片,主分片,原副分片,以及 move 到 target 節點的新的副分片。在復制階段,寫入操作會寫入到這三個分片。
以手工 move 一個副分片為例,從 node-1 move 到 node-2時,當收到第一個第一個集群狀態,分片被標記為 relocating,于是數據從 node-idea recovery 到 node-2。在此期間,新的 index 操作會由主分片節點復制到另外兩個節點。如下圖所示。
這個過程相當于先增加了一個副分片,執行副分片的 recovery 流程復制到新的 target。
當 recovery 執行完畢,master 下發第二個集群狀態,分片被標記為 STARTED,node-1原來持有的分片被刪除,如下圖所示。
副分片的 relocating 過程不會有 handoff 階段,整個 relocating 過程如同副分片的 recovery 過程一樣,沒有對寫入進行阻塞的階段。
到此,相信大家對“relocating對Elasticsearch集群的影響是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。