Kylin RT OLAP reassign流程即重新分配replica_set 流程

本文將通過頁面操作入口和程序代碼進行reassign流程分析。reassign的大致流程爲頁面操作觸發coordinator調用相應的receiver進行處理:reassign分爲3個部分,preAssignment(只存在與之前,新的assignment中不存在)、newAssignment(只存在與新的,之前的assignment中沒有此replica set)、commonAssignment(即存在與之前assignment也在新的assignment中)。其中commonAssignment不做任何處理;preAssignment將會通知各個replica set消費到當前receiver消費到的各partition的最晚offset,然後停止消費並將這些receiver上的segment由active變爲immutable;newAssignment和正常流程一樣進行assign分配消費,只是各partition消費的offset爲preAssignment各partition消費的最晚offset。

一、頁面操作

選擇需要reassign的cube:Action——AssignMent——edit——save
在這裏插入圖片描述

二、源碼分析

2.1 代碼執行流程:

用戶提交reassignment,會觸發Coordinator.reAssignCube方法(調用Coordinator的reAssignCube方法時,coordinator的leader爲本機則直接調用,非本機則通過http調用。),reAssignCube方法中主要分兩種Case處理此次reassign:
Case1:之前此cube沒有assignment,此種情況只會存在於之前整個集羣沒有可用的replica_set或手動將cube中的assignment刪除了,則不存在處理之前的assignment的情況,直接走assign流程即調用coordinator.doAssignCube方法;
Case2:如果之前有assignment則需要涉及到處理之前assignment並切換到新的(大多數爲這種情況),主要在coordinator.reassignCubeImpl方法中實現。
下面主要對Case2進行分析即對coordinator.reassignCubeImpl方法進行追蹤分析。

2.2.1 Case1: 此cube之前沒有assignment

StreamingV2Controller(master).reAssignStreamingCube——》StreamingV2Service.reAssignCube——》Coordinator.reAssignCube——》doAssignCube()——後續繼續走正常的的分配消費流程 ,代碼比較清晰易懂,本文不多做分析;

2.2.2 Case2: 此cube之前有assignment,此次爲調整。

StreamingV2Controller(master).reAssignStreamingCube——》StreamingV2Service.reAssignCub——》reassignCubeImpl——》分兩種情況,調整前後是否完全一樣,如果完全一樣則不做任何處理(newAssignments=preAssignments);如果調整前後有差別,則繼續——》 doReassign,接下來分三大步:

2.2.2.1 第一步是處理preAssignments即調用syncAndStopConsumersInRs:

通知此cube之前所有的replicasets(此replica set且不再新的replica sets中)下的receiver停止消費並返回offset;得到每個partition當前已經消費的最晚offset;通知負責消費相應partition的receiver均消費到此partition的最晚offset然後停止消費。當然如果preAssignments中某個replicaset包含在新的裏面,不做任何處理的.

  • 暫停此replicatSet下所有receiver消費此topic且返回每個receiver消費的offset:
    暫停本次要去掉的replicat_set下所有節點對此cube的消費:Coordinator.doReassign——》syncAndStopConsumersInRs——》pauseConsumersInReplicaSet(pause暫停消費)——》pauseConsumersForReceiver——》HttpReceiverAdminClient.pauseConsumers(http call receiver)——》AdminController.pauseConsumers——》StreamingServer.pauseConsumer(暫停消費並返回每個receiver當前消費的consumePosition,receiver每消費一條記錄會通過StreamingSegmentManager.addEvent記錄consumePosition)——》StreamingConsumerChannel.pause(true)暫停消費;
  • 根據上一步返回的offset並計算各replica
    set當前已經消費的最晚offset,然後通知所有相關的receiver均消費到此offset後停止:

    Coordinator.doReassign——》Coordinator.syncAndStopConsumersInRs——》KafkaPositionHandler.mergePositions(得到所有receiver消費此partition的最晚offset)——》Coordinator.resumeConsumersInReplicaSet——》resumeConsumersForReceiver——》AdminController.resumeConsumers——》AdminController.resumeConsumers(http 通知此replicaSet的所有receiver均消費到最後的offset)——》StreamingServer.resumeConsumer——》StreamingConsumerChannel.resumeToStopCondition——》setStopCondition——》run(會進行判斷,消費到最晚的offset後自動停止),並返回每個的最新信息
2.2.2.2 第二步是處理所有的newAssignments:**

通知newAssignments的每個replicaset下的receiver進行assign並從指定的partition的offset(offset來源於第一步各個partition消費的最晚offset)開始消費start
consumer。當然如果newAssignments中的某個replicaset在preAssignments也不做任何處理,保持不變:

  • assign(僅assign不start),調用assignCubeToReplicaSet
    Coordinator.doReassign——》assignCubeToReplicaSet(assign所有replicaset下的receiver)——》assignCubeToReplicaSet——》assignToReceiver——》HttpReceiverAdminClient.assign——》AdminController.assign(http receiver)——》StreamingServer.assign(String cubeName, List partitions)(將此cube及partition放入內存StreamingServer.assignments中,等待後續start);

  • start consumer(通知receiver從指定的offset開始消費)即調用startConsumersInReplicaSet
    Coordinator.doReassign——》startConsumersInReplicaSet(觸發消費start consumer)——》startConsumersForReceiver——》HttpReceiverAdminClient.startConsumers(http receiver)——》AdminController.startConsumers——》StreamingServer.startConsumer(String cubeName, ConsumerStartProtocol startProtocol) startProtocol來源於第一步中返回的各receiver關於此topic各partition的最新消費信息——》Coordinator.createNewConsumer ——》KafkaSource.createStreamingConnector(創建連接kafka的coonector設定topic、partition、offset集合等)——》createNewConsumer——》Coordinator.createNewConsumer——》new StreamingConsumerChannel——》StreamingConsumerChannel.start()——》kafkaConnect.open(爲kafka的topic綁定本次消費的partition、以及offset)——》StreamingConsumerChannel.run(啓動topic消費)

2.2.2.3 第三步是理removedAssignments,將preAssignments的相應receiver下的本地segment由active 變更爲immutable:

將只在preAssignments中不在newAssignments中的replica_set,需要將這些replica_set下的receiver中的數據變更爲Immutable,並上傳build等後續處理。

  • removedAssignments相應receiver下的本地segment由active 變更爲immutable:
    Coordinator.doReassign——》makeCubeImmutableInReplicaSet——》makeCubeImmutableForReceiver——》HttpReceiverAdminClient.makeCubeImmutable——》AdminController.immuteCube(http receiver)——》StreamingServer.makeCubeImmutable (1、停用此cube消費;2、從內存cubeConsumerMap中移除此cube)——》StreamingSegmentManager.makeAllSegmentsImmutable(狀態變更,將此cube在此receiver上的所有active segments爲immutable)——》convertImmutable(1、從內存activeSegments中移除,2、此segment的狀態變爲immutable【持久化此segment到磁盤、修改內存狀態爲immutable、修改磁盤此segment狀態爲immutable】;3、此segment放入內存immutableSegments;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章