本發(fā)明屬于計(jì)算機(jī)應(yīng)用技術(shù)領(lǐng)域,涉及一種流式數(shù)據(jù)處理自適應(yīng)速率控制方法。
背景技術(shù):
當(dāng)前,隨著技術(shù)的發(fā)展,數(shù)據(jù)量日益增加,“大數(shù)據(jù)”技術(shù)已經(jīng)滲透到各行各業(yè)。目前,許多設(shè)備都會(huì)收集大量的數(shù)據(jù),并希望對(duì)數(shù)據(jù)及時(shí)處理從而發(fā)掘其中的價(jià)值。例如智能手機(jī)、傳感器、物聯(lián)網(wǎng)設(shè)備、社交網(wǎng)絡(luò)和在線事務(wù)系統(tǒng)產(chǎn)生的數(shù)據(jù)都需要不斷的收集,通過(guò)實(shí)時(shí)的對(duì)數(shù)據(jù)進(jìn)行分析,從而實(shí)現(xiàn)快速響應(yīng)。因此,如何提升數(shù)據(jù)實(shí)時(shí)分析處理的能力也成為一個(gè)十分重要的問(wèn)題。
當(dāng)前一些主流的大數(shù)據(jù)實(shí)時(shí)處理框架有Spark,Storm,F(xiàn)link等。Spark Streaming是對(duì)Spark核心API的擴(kuò)展,它是按照一定的時(shí)間間隔將任務(wù)分成一系列短小的批處理作業(yè)進(jìn)行處理。Storm是以單條記錄為粒度進(jìn)行處理的流式處理系統(tǒng),擁有良好的實(shí)時(shí)性。Flink和Spark類(lèi)似,其核心是流式數(shù)據(jù)流引擎,為數(shù)據(jù)流上的分布式計(jì)算提供了數(shù)據(jù)分發(fā)、通信和容錯(cuò)。但是和Spark Streaming相比,Storm的吞吐量較低,且實(shí)現(xiàn)復(fù)雜的統(tǒng)計(jì)需求較為困難。Flink的批處理和流式處理是兩個(gè)獨(dú)立的模塊,無(wú)法進(jìn)行結(jié)合。Spark Streaming因?yàn)槭褂肕icro-batch處理數(shù)據(jù),可以達(dá)到較高的吞吐率,在滿足秒級(jí)的實(shí)時(shí)性要求同時(shí)可以達(dá)到較高的效率。
流式處理系統(tǒng)需要良好的實(shí)時(shí)性,并且在處理突發(fā)任務(wù)時(shí)能保證系統(tǒng)的穩(wěn)定。通常,流式處理架構(gòu)通過(guò)以下幾種方式保證系統(tǒng)的實(shí)時(shí)性和穩(wěn)定性:1.當(dāng)處理的負(fù)載超過(guò)系統(tǒng)處理能力上限時(shí),通過(guò)丟棄部分?jǐn)?shù)據(jù)降低工作負(fù)載;2.動(dòng)態(tài)資源管理;3.動(dòng)態(tài)批次大小。但是丟棄數(shù)據(jù)通常會(huì)造成計(jì)算結(jié)果不準(zhǔn)確,動(dòng)態(tài)資源 管理為了針對(duì)數(shù)據(jù)處理洪峰需要更多的硬件資源,動(dòng)態(tài)批次大小使得運(yùn)行延遲變得不確定。
集群的狀態(tài)不是一成不變的,因而人為設(shè)置的靜態(tài)數(shù)據(jù)處理速率上限可能是不準(zhǔn)確的,太小可能造成在處理突發(fā)的速率增加時(shí)無(wú)法充分利用計(jì)算資源,太大則可能導(dǎo)致系統(tǒng)接收過(guò)多的數(shù)據(jù),造成計(jì)算集群的高延遲,從而導(dǎo)致系統(tǒng)不穩(wěn)定。
技術(shù)實(shí)現(xiàn)要素:
針對(duì)現(xiàn)有技術(shù)中存在的問(wèn)題,本發(fā)明提供了一種海量數(shù)據(jù)的流式處理自適速率控制方法。該方法基于常用的數(shù)據(jù)匯總消息隊(duì)列和流式數(shù)據(jù)分布式計(jì)算框架,根據(jù)當(dāng)前計(jì)算集群的情況,通過(guò)預(yù)分片的方式調(diào)整數(shù)據(jù)處理的并行度,并通過(guò)自適應(yīng)實(shí)時(shí)速率控制方法動(dòng)態(tài)調(diào)整集群當(dāng)前處理數(shù)據(jù)的數(shù)量,使得每一批輸入數(shù)據(jù)的處理時(shí)間和批次間隔保持一致,保證計(jì)算集群的穩(wěn)定性,降低數(shù)據(jù)流式處理的延遲。
用戶可以利用本技術(shù)提供的方法實(shí)現(xiàn)如下功能:海量數(shù)據(jù)的實(shí)時(shí)接收和預(yù)處理;數(shù)據(jù)的實(shí)時(shí)處理;數(shù)據(jù)預(yù)分片及數(shù)據(jù)處理的并行化調(diào)整;實(shí)時(shí)處理數(shù)據(jù)數(shù)量的動(dòng)態(tài)調(diào)整;處理結(jié)果輸出到數(shù)據(jù)庫(kù)中。
本發(fā)明的技術(shù)方案:
一種流式數(shù)據(jù)處理自適應(yīng)速率控制方法,步驟如下:
第一步,數(shù)據(jù)接收和分區(qū)緩存
流式數(shù)據(jù)處理系統(tǒng)接收的數(shù)據(jù),其格式由用戶定義。要求一條完整的數(shù)據(jù)為一行,或者使用無(wú)歧義的特殊分隔符對(duì)數(shù)據(jù)進(jìn)行分割。使用通用的消息隊(duì)列作為數(shù)據(jù)源對(duì)數(shù)據(jù)進(jìn)行匯總,并對(duì)數(shù)據(jù)按照分區(qū)規(guī)則將數(shù)據(jù)保存到消息隊(duì)列中的某個(gè)分區(qū)中。本步驟使得消息隊(duì)列中各個(gè)分片中的數(shù)據(jù)數(shù)量較為均勻,消息 隊(duì)列中的數(shù)據(jù)供之后的步驟讀取計(jì)算。
第二步,數(shù)據(jù)預(yù)分片
從消息隊(duì)列中讀取數(shù)據(jù)前,將消息隊(duì)列中單個(gè)數(shù)據(jù)分片映射到多個(gè)流式數(shù)據(jù)處理集群的分片中,映射的數(shù)量根據(jù)集群虛擬核心數(shù)量進(jìn)行設(shè)置;避免了之后在計(jì)算集群中對(duì)數(shù)據(jù)進(jìn)行重新分片以及task發(fā)送到工作節(jié)點(diǎn)的消耗。預(yù)分片方式在將數(shù)據(jù)獲取推遲到計(jì)算時(shí)進(jìn)行,從而將原來(lái)的數(shù)據(jù)讀取、重新分片、task連同分片發(fā)送到工作節(jié)點(diǎn)進(jìn)行計(jì)算,這三個(gè)步驟整合為在計(jì)算時(shí)對(duì)按照分片規(guī)則分片的數(shù)據(jù)進(jìn)行讀取并計(jì)算。
分片的數(shù)量決定了系統(tǒng)能達(dá)到的最大的并行度,從而影響端到端延遲。方法在任務(wù)開(kāi)始時(shí)確定了分片的數(shù)量,當(dāng)集群的各個(gè)工作節(jié)點(diǎn)的性能差距不大時(shí),可以設(shè)置分片數(shù)量為集群可用虛擬核心的整數(shù)倍,這樣可以保證任務(wù)可以平均分配到每一個(gè)CPU核心上,避免正常運(yùn)行過(guò)程中出現(xiàn)某個(gè)節(jié)點(diǎn)空閑的情況,從而充分利用硬件資源。
通過(guò)本步驟,系統(tǒng)得到了消息隊(duì)列和流式數(shù)據(jù)處理集群之間分片的映射關(guān)系,之后數(shù)據(jù)讀取按照該映射關(guān)系確定每一條數(shù)據(jù)的流向。
第三步,處理速率實(shí)時(shí)反饋控制
從消息隊(duì)列中讀取數(shù)據(jù),并根據(jù)當(dāng)前的數(shù)據(jù)處理速率上限確定最多可以從消息隊(duì)列中讀取的數(shù)據(jù)數(shù)量,避免讀取的數(shù)據(jù)數(shù)量超過(guò)計(jì)算集群的最大處理能力;實(shí)時(shí)速率控制器的處理速率上限計(jì)算方法如下:
3.1)通過(guò)慢啟動(dòng)的方式開(kāi)始進(jìn)行調(diào)整,初始的數(shù)據(jù)處理速率上限設(shè)置為消息隊(duì)列的每個(gè)分片每秒獲取n條數(shù)據(jù),50<n<1000;
3.2)第一批完成后,對(duì)以后每一批按照以下的步驟對(duì)數(shù)據(jù)處理速率上限進(jìn)行計(jì)算;
3.2.1)在批次開(kāi)始時(shí),提交當(dāng)前批次的開(kāi)始時(shí)間t_batchst給速率控制器;
3.2.2)在批次完成時(shí),提交當(dāng)前批次的處理結(jié)束時(shí)間t_batched,處理該批次用時(shí)t_proclast,,該批次在批次隊(duì)列中的等待時(shí)間t_waitlast,該批次處理數(shù)據(jù)的數(shù)量elemnumlast;
3.2.3)在當(dāng)前批次提交時(shí),對(duì)當(dāng)前批次的數(shù)據(jù)處理速率上限進(jìn)行計(jì)算,分為以下三種情況:第一種情況,在當(dāng)前批次提交時(shí),上一批次執(zhí)行完成,且上一批次數(shù)據(jù)的處理時(shí)間與流式數(shù)據(jù)批處理集群的批次間隔t_interval相差大于松弛參數(shù)prelx;第二種情況,當(dāng)前批次提交時(shí),上一批次執(zhí)行完成,且上一批次數(shù)據(jù)的處理時(shí)間位于t_interval-prelx和t_interval之間,prelx=min(50,t_interval×0.05);第三種情況,當(dāng)前批次提交時(shí),上一批次尚未完成。
第一種情況和第三種情況都基于PID控制算法對(duì)數(shù)據(jù)處理速率上限計(jì)算:
newRate=latesRate-Kp×error-Ki×historicaiError-Kd×dError (1)
其中,latestRate為最新處理完成批次的數(shù)據(jù)處理速率上限;Kp為比例系數(shù),取值為1;error為數(shù)據(jù)處理速率的估計(jì)誤差;Ki為積分系數(shù),取值為0.2;historicalError為數(shù)據(jù)處理速率的累積誤差;Kd為微分系數(shù),為了減小噪聲數(shù)據(jù)對(duì)系統(tǒng)的影響,取值為0;dError為偏差速率變化率;
數(shù)據(jù)處理速率的估計(jì)誤差error為:
其中,elemnumlast為最新處理完成的批次處理數(shù)據(jù)的數(shù)量;t_proclast為最新處理完成的批次處理的時(shí)間;Kblock為阻塞系數(shù),阻塞系數(shù)取值0.3;blockTime為估計(jì)的處理時(shí)間增加值;當(dāng)為第一種情況時(shí),blockTime取值為0,此時(shí)由公 式(2)計(jì)算得到的結(jié)果為數(shù)據(jù)處理速率的估計(jì)誤差;當(dāng)為第三種情況時(shí),blockTime計(jì)算如公式(3)所示:
blockTime=max(t_interval-(submit_time-t_batchst),brelx) (3)
其中,t_interval為批次提交的間隔;submit_time為任務(wù)的提交時(shí)間;在批次間隔大于1000ms時(shí),brelx=50ms,當(dāng)批次間隔小于1000ms時(shí),brelx=t_interval×0.05;
數(shù)據(jù)處理速率的累積誤差historicalError的計(jì)算如公式(4)所示:
其中,t_waitlast為最新處理完成的批次在批次隊(duì)列中等待的時(shí)間;當(dāng)為第一種情況時(shí),blockTime取值為0;當(dāng)為第三種情況時(shí),blockTime計(jì)算如公式(3)所示;processingRate表示最新處理完成批次的數(shù)據(jù)處理速率,其計(jì)算如公式(5)所示:
偏差速率變化率dError的計(jì)算如公式(6)所示:
其中,latestError表示前一個(gè)處理完成批次的速率估計(jì)誤差,delaySinceUpdate表示前一個(gè)處理完成批次和最近完成批次之間經(jīng)過(guò)的時(shí)間,其計(jì)算方式如公式(7)所示:
delaySinceUpdate=lastProcessingEndTime-latestTime (7)
第二種情況,使用最新處理完成批次的數(shù)據(jù)處理速率上限latestRate作為當(dāng)前批次的數(shù)據(jù)處理速率上限newRate;
進(jìn)一步地,如果最新完成的三個(gè)批次的處理時(shí)間都位于t_interval-prelx和t_interval之間時(shí),則使用公式(8)對(duì)速率上限進(jìn)行計(jì)算:
其中rlast表示最新完成批次的處理速率,r2nd-last表示倒數(shù)第二個(gè)完成批次的處理速率,r3rd-last表示倒數(shù)第三個(gè)完成批次的處理速率。
第四步,數(shù)據(jù)的讀取和實(shí)時(shí)處理。流式數(shù)據(jù)批處理集群按照計(jì)算好的數(shù)據(jù)處理速率上限和預(yù)分片規(guī)則對(duì)數(shù)據(jù)進(jìn)行讀取。在預(yù)分片的過(guò)程中,只是獲取了當(dāng)前批次需要從消息隊(duì)列各個(gè)分片中獲取數(shù)據(jù)的partition ID、起始偏移量和終止偏移量。數(shù)據(jù)只有在流式數(shù)據(jù)批處理集群開(kāi)始處理時(shí)才進(jìn)行讀取。在本批次數(shù)據(jù)處理完成之后,將結(jié)果實(shí)時(shí)輸出到數(shù)據(jù)庫(kù)中。
進(jìn)一步地,所述的第一步的數(shù)據(jù)接收和分區(qū)緩存的具體方法為:
消息隊(duì)列中包含多個(gè)主題的信息,一個(gè)主題為一類(lèi)消息,每個(gè)主題將被分成多個(gè)分區(qū)。為了避免數(shù)據(jù)傾斜,消息隊(duì)列在接收到數(shù)據(jù)后,按照分片規(guī)則將數(shù)據(jù)緩存到消息隊(duì)列的某個(gè)分區(qū)中。數(shù)據(jù)分區(qū)的流程如圖3所示。
消息隊(duì)列從數(shù)據(jù)源中接收數(shù)據(jù)。在接收到數(shù)據(jù)后,按照以下方法對(duì)數(shù)據(jù)發(fā)送到哪個(gè)消息隊(duì)列的分區(qū)進(jìn)行計(jì)算:
partNum=MD5(key)mod numPartition
其中key表示數(shù)據(jù)的ID,如果數(shù)據(jù)沒(méi)有ID,則以隨機(jī)數(shù)來(lái)替代,MD5(key)表示數(shù)據(jù)key的MD5值,numPartition表示消息隊(duì)列分區(qū)的數(shù)量。消息隊(duì)列將數(shù)據(jù)按照partNum指示的ID保存在消息隊(duì)列指定的分區(qū)中,等待消費(fèi)者對(duì)數(shù)據(jù)進(jìn)行讀取。
進(jìn)一步地,所述的第二步的預(yù)分片的具體方法為:
1)流式數(shù)據(jù)處理集群以批次的時(shí)間間隔為周期,獲取消息隊(duì)列的分片信息; 對(duì)于每一個(gè)批次,計(jì)算集群都需要獲取消息隊(duì)列中的n個(gè)數(shù)據(jù)分片,則消息隊(duì)列中數(shù)據(jù)分片信息表示為s_partition=(s_partitioni|i=1...n);對(duì)于當(dāng)前批次,消息隊(duì)列每一個(gè)分片s_partitioni的信息包括:分片所屬的主題topic、消息隊(duì)列分片的唯一ID、當(dāng)前批次需要獲取的數(shù)據(jù)在消息隊(duì)列指定分片中的起始位置start_offset、當(dāng)前批次需要獲取的數(shù)據(jù)在消息隊(duì)列指定分片中的終止位置end_offset。
2)流式數(shù)據(jù)處理集群將批次信息提交到批次消息隊(duì)列中;在集群沒(méi)有開(kāi)始對(duì)數(shù)據(jù)進(jìn)行處理之前,即前一批次的數(shù)據(jù)尚未處理完成時(shí),數(shù)據(jù)并未真正讀到計(jì)算集群中,提交的只有消息隊(duì)列的分片的信息。
3)根據(jù)當(dāng)前批次的消息隊(duì)列分片信息計(jì)算流式數(shù)據(jù)處理集群的分片對(duì)應(yīng)消息隊(duì)列中哪一個(gè)分片的哪一部分?jǐn)?shù)據(jù)。
3.1)計(jì)算消息隊(duì)列中分片的數(shù)量source_num和流式數(shù)據(jù)處理集群中空閑虛擬核心的數(shù)量core_num的最小公倍數(shù)為spark_num,并由此得到每一個(gè)消息隊(duì)列分片需要映射到的流式數(shù)據(jù)批處理集群的分片數(shù)量為map_num=spark_num/source_num。
3.2)計(jì)算消息隊(duì)列和流式數(shù)據(jù)處理集群分片的映射關(guān)系;對(duì)消息隊(duì)列中當(dāng)前批次的每一個(gè)分片的信息s_partition=(s_partitioni|i=1...n)進(jìn)行處理;獲取當(dāng)前分片s_partitioni中數(shù)據(jù)的數(shù)量elem_num=end_offset-start_offset+1,將當(dāng)前批次消息隊(duì)列一個(gè)分片中的數(shù)據(jù)平均分配到map_num個(gè)流式數(shù)據(jù)處理集群的分片中,每一個(gè)流式數(shù)據(jù)處理集群分片中的數(shù)據(jù)量為each_num=elem_num/map_num;若當(dāng)前批次數(shù)據(jù)源分片中的數(shù)據(jù)無(wú)法被map_num整除,則先計(jì)算多余出來(lái)的數(shù)據(jù)的條數(shù)為left_num=elem_num%map_num,在每一個(gè)消息隊(duì)列分片對(duì)應(yīng)的map_num個(gè)流式 數(shù)據(jù)處理集群分片中前l(fā)eft_num個(gè)數(shù)據(jù)分片中的數(shù)據(jù)數(shù)量為eachnum+1,其余map_num-left_num個(gè)分片中數(shù)據(jù)量為eachnum。
進(jìn)一步地,所述的第四步的數(shù)據(jù)讀取和實(shí)時(shí)處理的具體方法為:
1)對(duì)消息隊(duì)列中每一個(gè)分片中進(jìn)行處理,若分片中未處理的數(shù)據(jù)量小于newRate×tinterval÷s_partition,則直接讀取該分片的所有剩余未處理數(shù)據(jù),否則,該分片讀取數(shù)據(jù)數(shù)量為newRate×tinterval÷s_partition。
2)消息隊(duì)列的單個(gè)分片對(duì)應(yīng)流式數(shù)據(jù)處理集群的多個(gè)分片,由于預(yù)分片已經(jīng)實(shí)現(xiàn)了這種一對(duì)多的映射,因此流式數(shù)據(jù)處理集群在將數(shù)據(jù)讀取到集群的工作節(jié)點(diǎn)之后,每一個(gè)流式數(shù)據(jù)處理集群的分片生成一個(gè)任務(wù),并且在工作節(jié)點(diǎn)本地執(zhí)行,執(zhí)行結(jié)束后將結(jié)果保存到下游數(shù)據(jù)庫(kù)中。
進(jìn)一步地,所述的消息隊(duì)列為Kafka、Flume、Kinesis或者其他適用于流式數(shù)據(jù)處理的消息隊(duì)列。
進(jìn)一步地,所述的流式批處理計(jì)算框架為Spark、Flink或者其他適用于流式數(shù)據(jù)計(jì)算的框架。
本系統(tǒng)由消息隊(duì)列,海量流式數(shù)據(jù),流式數(shù)據(jù)計(jì)算框架,數(shù)據(jù)分區(qū),數(shù)據(jù)預(yù)分片算法,自適應(yīng)實(shí)時(shí)速率控制算法組成。其中消息隊(duì)列用于對(duì)多個(gè)數(shù)據(jù)源的數(shù)據(jù)進(jìn)行匯總收集,用于支持海量數(shù)據(jù)的實(shí)時(shí)匯總分發(fā)以及數(shù)據(jù)暫存。其上游可以是多個(gè)數(shù)據(jù)服務(wù)器,下游為數(shù)據(jù)實(shí)時(shí)計(jì)算框架。流式數(shù)據(jù)計(jì)算框架從上游數(shù)據(jù)隊(duì)列接收數(shù)據(jù),并按照一定的時(shí)間間隔將任務(wù)分成若干個(gè)小的批處理作業(yè),從而實(shí)現(xiàn)準(zhǔn)實(shí)時(shí)的數(shù)據(jù)處理。
系統(tǒng)實(shí)時(shí)接收數(shù)據(jù)進(jìn)行處理,數(shù)據(jù)分區(qū)在消息隊(duì)列的數(shù)據(jù)生產(chǎn)者端實(shí)現(xiàn),方法以每一條數(shù)據(jù)的ID為依據(jù)對(duì)分區(qū)進(jìn)行計(jì)算;數(shù)據(jù)預(yù)分片算法根據(jù)消息隊(duì)列的分區(qū)數(shù)和流式數(shù)據(jù)處理集群的虛擬核心數(shù)量確定分片關(guān)系;自適應(yīng)實(shí)時(shí)速率 控制算法由Scala實(shí)現(xiàn),通過(guò)控制器實(shí)時(shí)跟蹤當(dāng)前計(jì)算集群任務(wù)處理狀態(tài),確定數(shù)據(jù)處理速率上限值。
本發(fā)明的有益成果:本發(fā)明通過(guò)將數(shù)據(jù)分區(qū)、預(yù)分片、自適應(yīng)實(shí)時(shí)速率控制和流式數(shù)據(jù)處理框架結(jié)合,對(duì)海量數(shù)據(jù)進(jìn)行實(shí)時(shí)處理。本發(fā)明有如下優(yōu)點(diǎn):1)低延遲:通過(guò)對(duì)數(shù)據(jù)預(yù)分片提升數(shù)據(jù)處理的并行度,每條數(shù)據(jù)直接由計(jì)算該條數(shù)據(jù)的節(jié)點(diǎn)進(jìn)行讀取,避免了計(jì)算集群先接收數(shù)據(jù)之后再進(jìn)行重新分片造成的網(wǎng)絡(luò)帶寬消耗、磁盤(pán)讀寫(xiě)消耗以及任務(wù)分發(fā)的延遲。2)高穩(wěn)定性:根據(jù)計(jì)算集群實(shí)時(shí)的處理狀態(tài),動(dòng)態(tài)調(diào)整流入計(jì)算集群的數(shù)據(jù)量,使得數(shù)據(jù)處理時(shí)間和批次間隔保持一致,從而保證計(jì)算集群任務(wù)隊(duì)列中的任務(wù)能按時(shí)完成,避免突發(fā)數(shù)據(jù)量增加導(dǎo)致的隊(duì)列阻塞。3)應(yīng)用:大數(shù)據(jù)技術(shù)逐步深入到各個(gè)行業(yè)中,面對(duì)持續(xù)大量的數(shù)據(jù)流,實(shí)時(shí)數(shù)據(jù)處理系統(tǒng)需要快速響應(yīng)處理。本發(fā)明適用于多種基于批次的流式數(shù)據(jù)處理系統(tǒng),應(yīng)用范圍廣泛。
附圖說(shuō)明
圖1是本方法采用的系統(tǒng)架構(gòu)圖。
圖2是本方法的整體處理流程圖。
圖3是本方法的數(shù)據(jù)分區(qū)示意圖。
圖4是流式批處理系統(tǒng)的數(shù)據(jù)處理流程。
圖5(a)是重新分片的數(shù)據(jù)流向示意圖。
圖5(b)是預(yù)分片方法的數(shù)據(jù)流向示意圖。
圖6展示了批次隊(duì)列的詳細(xì)結(jié)構(gòu)和不同階段所執(zhí)行的操作。
圖7展示了自適應(yīng)速率控制器的整體結(jié)構(gòu)。
圖8是repartition方式和預(yù)分片方式的處理延遲示意圖。
圖9是流式數(shù)據(jù)的生成速率。
圖10是本方法的排隊(duì)延遲圖。
具體實(shí)施方式
以下結(jié)合附圖和技術(shù)方案,進(jìn)一步說(shuō)明本發(fā)明的具體實(shí)施方式。
系統(tǒng)架構(gòu)如圖1所示。系統(tǒng)可以使用多種數(shù)據(jù)源,發(fā)送的字節(jié)數(shù)據(jù)流通過(guò)解析器進(jìn)行解析,系統(tǒng)使用Kafka作為消息隊(duì)列對(duì)數(shù)據(jù)進(jìn)行匯總緩存。數(shù)據(jù)源中解析得到的數(shù)據(jù)通過(guò)Kafka的producer發(fā)送到Kafka集群。系統(tǒng)使用Spark Streaming對(duì)數(shù)據(jù)進(jìn)行流式處理。Kafka集群作為Spark Streaming的上游數(shù)據(jù)源,Spark Streaming持續(xù)拉取數(shù)據(jù)進(jìn)行計(jì)算。Zookeeper對(duì)當(dāng)前處理數(shù)據(jù)的偏移量進(jìn)行記錄,數(shù)據(jù)庫(kù)和下游Kafka集群用于輸出結(jié)果的管理。
本方法的處理流程如圖2所示。數(shù)據(jù)源持續(xù)產(chǎn)生大量的數(shù)據(jù),首先解析數(shù)據(jù)并通過(guò)數(shù)據(jù)分區(qū)規(guī)則將數(shù)據(jù)匯總到Kafka消息隊(duì)列集群中,提供給后續(xù)計(jì)算集群讀取。讀取數(shù)據(jù)時(shí)根據(jù)預(yù)分片算法得到的分片結(jié)果對(duì)數(shù)據(jù)進(jìn)行讀取。讀取數(shù)據(jù)的數(shù)量由當(dāng)前消息隊(duì)列中擁有的數(shù)據(jù)量和數(shù)據(jù)處理速率上限共同決定。數(shù)據(jù)處理速率上限由基于PID的自適應(yīng)實(shí)時(shí)速率控制算法計(jì)算,通過(guò)周期讀取集群的當(dāng)前狀態(tài)和批次計(jì)算的信息來(lái)保證計(jì)算的準(zhǔn)確性。在數(shù)據(jù)處理結(jié)束后將數(shù)據(jù)輸出存儲(chǔ)到下游數(shù)據(jù)庫(kù)。
首先數(shù)據(jù)源持續(xù)大量的產(chǎn)生數(shù)據(jù),Kafka消息隊(duì)列接收數(shù)據(jù)后對(duì)數(shù)據(jù)進(jìn)行解析,并按照給定的數(shù)據(jù)分區(qū)方法計(jì)算數(shù)據(jù)的分區(qū),并提交到Kafka集群中指定的partition中,數(shù)據(jù)分區(qū)的過(guò)程如圖3所示。數(shù)據(jù)分區(qū)之后,數(shù)據(jù)源中的數(shù)據(jù)緩存到Kafka集群的多個(gè)partition中,用于下游計(jì)算集群拉取處理。
接下來(lái)Spark Streaming從Kafka消息隊(duì)列中拉取數(shù)據(jù)并將數(shù)據(jù)組織為批次提交到批次隊(duì)列。圖4為流式批處理系統(tǒng)的創(chuàng)建處理流程。批次生成器從Kafka消息隊(duì)列接收數(shù)據(jù),并按照一定的時(shí)間間隔將數(shù)據(jù)組織為批次,一個(gè)批次有多個(gè)分片,批次生成之后放在批次隊(duì)列中。Streaming processor按先后順序從批次隊(duì)列中獲得一個(gè)批次進(jìn)行處理,之后將處理結(jié)果輸出。
方法在將數(shù)據(jù)組織為批次并提交到批次隊(duì)列時(shí),提交的實(shí)際上為批次的信息,而數(shù)據(jù)在批次隊(duì)列中之前的批次都處理完之后才進(jìn)行讀取并處理。批次中每一個(gè)分片的信息通過(guò)預(yù)分片的方式來(lái)進(jìn)行計(jì)算。圖5(a)為傳統(tǒng)的數(shù)據(jù)接收架構(gòu),沒(méi)有采用預(yù)分片的方式。使用Direct方式接收數(shù)據(jù),Kafka的分片和Spark的分片數(shù)量是一一對(duì)應(yīng)的。因此在數(shù)據(jù)接收之后為了增加并行性,需要重新分片。圖5(b)是預(yù)分片方式的數(shù)據(jù)接收架構(gòu)。Spark集群按照預(yù)分片規(guī)則對(duì)數(shù)據(jù)進(jìn)行接收,一個(gè)Kafka分片中的數(shù)據(jù)被平均分配到了多個(gè)Spark Streaming的分片中。
流式批處理系統(tǒng)由于是一種準(zhǔn)實(shí)時(shí)的數(shù)據(jù)處理系統(tǒng),數(shù)據(jù)不會(huì)在提交之后立刻被執(zhí)行,而是一小段時(shí)間內(nèi)的多條數(shù)據(jù)組成一個(gè)批次,按照批次對(duì)數(shù)據(jù)進(jìn)行處理。因此數(shù)據(jù)處理的過(guò)程分為三個(gè)階段,分別為批次提交、批次開(kāi)始處理、批次處理完成。圖6解釋了在批次處理的不同階段,分別需要進(jìn)行的操作。以batch1到batch3的提交為例進(jìn)行分析。首先批次按照固定的時(shí)間間隔進(jìn)行提交,因此首先執(zhí)行第一步:batch2提交時(shí)根據(jù)上一批次的執(zhí)行情況計(jì)算速率上限,但是batch2在提交之后并未立刻開(kāi)始執(zhí)行,而是等到batch1完成之后,才開(kāi)始執(zhí)行第二步:batch1完成,接收并處理批次2。在第一步開(kāi)始經(jīng)過(guò)了batch interval之后,執(zhí)行第三步:batch3提交時(shí)根據(jù)上一批次的執(zhí)行情況計(jì)算速率上限。從batch2提交到batch3提交經(jīng)過(guò)的時(shí)間就是batch interval。之后當(dāng)batch2完成時(shí),batch3開(kāi)始接收并處理。
在每次批次提交時(shí),該批次的數(shù)據(jù)處理速率上限已經(jīng)由速率控制模塊計(jì)算確定。圖7解釋了自適應(yīng)速率控制模塊的設(shè)計(jì)結(jié)構(gòu)。速率控制器仍然基于Spark Streaming設(shè)計(jì)實(shí)現(xiàn)。Spark的Job生成器從數(shù)據(jù)源接收數(shù)據(jù),生成Spark Streaming需要處理的Job。Job生成器在生成Job時(shí)獲取速率控制器計(jì)算的速率上限,并將Job發(fā)送給Job處理器。Job處理器按順序處理Job,并且將batch的信息發(fā)送給速率控制器。速率控制器使用批次的統(tǒng)計(jì)信息,利用自適應(yīng)速率控制算法計(jì)算數(shù)據(jù)處理速率上限,并將信息反饋給Spark的Job生成器。用于控制下一批的數(shù)據(jù)數(shù)量。在執(zhí)行期間,速率控制器一直監(jiān)聽(tīng)Job的處理情況,在batch 提交時(shí)、batch開(kāi)始時(shí)、batch完成時(shí)分別獲取控制器需要的不同階段的batch統(tǒng)計(jì)數(shù)據(jù)。
對(duì)于本發(fā)明對(duì)性能的提升,該部分說(shuō)明預(yù)分片方法和重新分片方法處理相同數(shù)量數(shù)據(jù)所需的時(shí)間對(duì)比。圖8展示了預(yù)分片方式和重新分片repartition方式的處理延遲。集群限定每個(gè)partition每秒讀取數(shù)據(jù)量上限為40000條數(shù)據(jù),提交batch的時(shí)間間隔限定為4秒,不進(jìn)行速率反饋控制使得每一批接收的數(shù)據(jù)量始終保持最大值。限定數(shù)據(jù)locality優(yōu)先級(jí)改變的時(shí)間間隔為100毫秒。采用原始的Spark Streaming數(shù)據(jù)接收方法,每個(gè)批次執(zhí)行的時(shí)間平均為7秒,其中數(shù)據(jù)接收的時(shí)間約為3秒,數(shù)據(jù)處理的時(shí)間約為4秒。預(yù)分片的方法接收并處理數(shù)據(jù),每個(gè)批次執(zhí)行的時(shí)間平均為5秒,包括數(shù)據(jù)接收和數(shù)據(jù)處理的時(shí)間。
圖9表示了數(shù)據(jù)源生成模擬數(shù)據(jù)的速率。數(shù)據(jù)源生成數(shù)據(jù)的速率以10秒為周期,每個(gè)周期前半部分生成60萬(wàn)條數(shù)據(jù)。這個(gè)數(shù)據(jù)量超過(guò)了Spark Streaming的平均處理速率,用于模擬數(shù)據(jù)量突然增加的情形。
圖10用于評(píng)估本方法對(duì)性能的提升。Spark Streaming計(jì)算的批次間隔為1秒,每一條數(shù)據(jù)計(jì)算的時(shí)間復(fù)雜度為線性時(shí)間復(fù)雜度。對(duì)于原始的控制算法和自適應(yīng)實(shí)時(shí)速率控制算法進(jìn)行對(duì)比,對(duì)比主要為排隊(duì)延遲scheduling delay,表示每個(gè)batch在隊(duì)列中等待前一個(gè)batch完成處理所等待的時(shí)間;
sdelay=t_batchst-submit_time
其中sdelay表示scheduling delay,t_batchst表示批次開(kāi)始時(shí)間,
submit_time表示批次提交時(shí)間。
Scheduling delay由平均106.18毫秒降低到62.89毫秒。