Kappa:比Lambda更好更靈活的實(shí)時(shí)處理架構(gòu)
本篇文章中分析Lambda三層結(jié)構(gòu)模型的適用場(chǎng)景,同時(shí)暴露出Lambda架構(gòu)一個(gè)最明顯的問(wèn)題:它需要維護(hù)兩套分別跑在批處理和實(shí)時(shí)計(jì)算系統(tǒng)上面的代碼,而且這兩套代碼需要產(chǎn)出一致的結(jié)果。根據(jù)對(duì)此缺點(diǎn)的分析,我們引出當(dāng)時(shí)還在LinkedIn的大神Jay Kreps提出的Kappa架構(gòu),本文會(huì)對(duì)Kappa架構(gòu)原理進(jìn)行介紹,并討論兩個(gè)架構(gòu)的優(yōu)缺點(diǎn),***給出一個(gè)Kappa架構(gòu)的案例分析。
對(duì)Lambda架構(gòu)不熟悉或者希望了解Lambda架構(gòu)應(yīng)用案例的讀者,請(qǐng)回顧歷史文章中的《深入淺出解析大數(shù)據(jù)Lambda架構(gòu)》一文。
Lambda架構(gòu)回顧Lambda架構(gòu)的核心思想是把大數(shù)據(jù)系統(tǒng)拆分成三層:Batch Layer,Speed Layer和Serving Layer。其中,Batch Layer負(fù)責(zé)數(shù)據(jù)集存儲(chǔ)以及全量數(shù)據(jù)集的預(yù)查詢。Speed Layer主要負(fù)責(zé)對(duì)增量數(shù)據(jù)進(jìn)行計(jì)算,生成Realtime Views。Serving Layer用于響應(yīng)用戶的查詢請(qǐng)求,它將Batch Views和Realtime Views的結(jié)果進(jìn)行合并,得到***的結(jié)果,返回給用戶。圖1給出了Lambda的整體架構(gòu)圖:
Kappa架構(gòu)上述提到,為了將批處理和實(shí)時(shí)處理相結(jié)合,Lambda設(shè)計(jì)了Batch Layer和Speed Layer兩層結(jié)構(gòu),分別用于批處理和實(shí)時(shí)計(jì)算,因此需要維護(hù)兩套分別跑在批處理和實(shí)時(shí)計(jì)算系統(tǒng)之上的代碼。面對(duì)這個(gè)問(wèn)題,有人會(huì)有這樣的疑問(wèn),為什么不用流計(jì)算系統(tǒng)來(lái)進(jìn)行全量數(shù)據(jù)處理從而去除Batch Layer這一層?
可能有這樣回答:流計(jì)算給人的印象是對(duì)一些流式的、臨時(shí)的數(shù)據(jù)進(jìn)行計(jì)算,將結(jié)果保存后就將原始數(shù)據(jù)丟棄了,因此它不適合用來(lái)處理歷史數(shù)據(jù)。其實(shí)這種答案并不完全正確,對(duì)于基于Lambda架構(gòu)實(shí)現(xiàn)的Storm框架確實(shí)是這樣的,但對(duì)于后來(lái)出現(xiàn)的Spark并不是。
Storm是在2011年7月開源的,Spark是在2012年之后逐漸為人們所知的,因此在Nathan Marz設(shè)計(jì)Lambda架構(gòu)的時(shí)候,當(dāng)時(shí)還并沒有一個(gè)框架既可以用于離線處理,又可以進(jìn)行實(shí)時(shí)計(jì)算。但隨著Spark技術(shù)的發(fā)展,這一想法成為了可能,Spark本身可以用于批處理,而構(gòu)建在Spark之上的Spark Streaming又可以用于實(shí)時(shí)計(jì)算,因此利用一套系統(tǒng)來(lái)應(yīng)對(duì)批處理和實(shí)時(shí)計(jì)算相結(jié)合的業(yè)務(wù)完全是可行的。
Kappa架構(gòu)的核心思想包括以下三點(diǎn):
- 用Kafka或者類似的分布式隊(duì)列系統(tǒng)保存數(shù)據(jù),你需要幾天的數(shù)據(jù)量就保存幾天。
- 當(dāng)需要全量重新計(jì)算時(shí),重新起一個(gè)流計(jì)算實(shí)例,從頭開始讀取數(shù)據(jù)進(jìn)行處理,并輸出到一個(gè)新的結(jié)果存儲(chǔ)中。
- 當(dāng)新的實(shí)例做完后,停止老的流計(jì)算實(shí)例,并把老的一些結(jié)果刪除。
Kappa的架構(gòu)圖如圖2所示:
和Lambda架構(gòu)相比,在Kappa架構(gòu)下,只有在有必要的時(shí)候才會(huì)對(duì)歷史數(shù)據(jù)進(jìn)行重復(fù)計(jì)算,并且實(shí)時(shí)計(jì)算和批處理過(guò)程使用的是同一份代碼。或許有些人會(huì)質(zhì)疑流式處理對(duì)于歷史數(shù)據(jù)的高吞吐量會(huì)力不從心,但是這可以通過(guò)控制新實(shí)例的并發(fā)數(shù)進(jìn)行改善。
上面架構(gòu)圖中,新老實(shí)例使用了各自的結(jié)果存儲(chǔ),這便于隨時(shí)進(jìn)行回滾,更進(jìn)一步,假如我們產(chǎn)出的是一些算法模型之類的數(shù)據(jù),用戶還可以同時(shí)對(duì)新老兩份數(shù)據(jù)進(jìn)行效果驗(yàn)證,做一些A/B test或者使用bandit算法來(lái)***限度的使用這些數(shù)據(jù)。
優(yōu)缺點(diǎn)對(duì)比
對(duì)比項(xiàng) |
Lambda架構(gòu) |
Kappa架構(gòu) |
數(shù)據(jù)處理能力 |
可以處理超大規(guī)模的歷史數(shù)據(jù) |
歷史數(shù)據(jù)處理的能力有限 |
機(jī)器開銷 |
批處理和實(shí)時(shí)計(jì)算需一直運(yùn)行,機(jī)器開銷大 |
必要時(shí)進(jìn)行全量計(jì)算,機(jī)器開銷相對(duì)較小 |
存儲(chǔ)開銷 |
只需要保存一份查詢結(jié)果,存儲(chǔ)開銷較小 |
需要存儲(chǔ)新老實(shí)例結(jié)果,存儲(chǔ)開銷相對(duì)較大 |
開發(fā)、測(cè)試難易 程度 |
實(shí)現(xiàn)兩套代碼,開發(fā)、測(cè)試難度較大 |
只需面對(duì)一個(gè)框架,開發(fā)、測(cè)試難度相對(duì)較小 |
運(yùn)維成本 |
維護(hù)兩套系統(tǒng),運(yùn)維成本大 |
只需維護(hù)一個(gè)框架,運(yùn)維成本小 |
表1 Lambda架構(gòu)和Kappa架構(gòu)優(yōu)缺點(diǎn)對(duì)比
如上表所示,Kappa架構(gòu)相對(duì)來(lái)說(shuō)有更多的優(yōu)點(diǎn),目前也被更多的廠商用于構(gòu)建商業(yè)項(xiàng)目。
***,Lambda架構(gòu)不僅需要維護(hù)兩套分別跑在批處理和實(shí)時(shí)計(jì)算系統(tǒng)上面的代碼,還需要批處理和全量計(jì)算長(zhǎng)時(shí)間保持運(yùn)行;而Kappa架構(gòu)只有在需要的時(shí)候才進(jìn)行全量計(jì)算。
第二,Kappa架構(gòu)下可以啟動(dòng)很多個(gè)實(shí)例進(jìn)行重復(fù)計(jì)算,因此在需要對(duì)一些算法模型進(jìn)行調(diào)優(yōu)時(shí),Kappa架構(gòu)下只需要更改一套系統(tǒng)的參數(shù)即可,并且允許對(duì)新老數(shù)據(jù)進(jìn)行效果比對(duì);但是在Lambda架構(gòu)下,需要同時(shí)更改流計(jì)算系統(tǒng)算法模型和批處理系統(tǒng)算法模型,調(diào)參過(guò)程相對(duì)比較復(fù)雜。
第三,從用戶開發(fā)、測(cè)試和運(yùn)維的角度來(lái)看,Kappa架構(gòu)下,開發(fā)人員只需要面對(duì)一個(gè)框架,開發(fā)、測(cè)試和運(yùn)維的難度都會(huì)相對(duì)較小,這是個(gè)非常重要的優(yōu)點(diǎn)。
如何選擇
從上述的優(yōu)缺點(diǎn)對(duì)比來(lái)看,業(yè)務(wù)需求、開發(fā)測(cè)試難易程度和運(yùn)維成本為三個(gè)主要的框架選擇考慮因素,而機(jī)器開銷和存儲(chǔ)開銷,雖然存在一定差別,但是差別不是很大,所以這里我們也主要從業(yè)務(wù)需求,開發(fā)測(cè)試難易程度和運(yùn)維成本三方面來(lái)考慮如何對(duì)上述兩個(gè)架構(gòu)做出選擇。
業(yè)務(wù)需求
用戶需要根據(jù)自己的業(yè)務(wù)需求來(lái)選擇架構(gòu),如果所需要處理的歷史數(shù)據(jù)規(guī)模較大,比如某省智慧交通系統(tǒng)幾年達(dá)TB級(jí)的數(shù)據(jù),那么選擇Lambda架構(gòu)可能較為合適;如果處理的數(shù)據(jù)量較小,比如分析某電商網(wǎng)站近30天的數(shù)據(jù),那么選擇Kappa架構(gòu)可能更為合適。
開發(fā)測(cè)試難易程度
如果項(xiàng)目中需要頻繁的對(duì)算法模型參數(shù)進(jìn)行調(diào)優(yōu),Kappa架構(gòu)要來(lái)的更為便捷;另外還有一個(gè)判定依據(jù)就是你設(shè)計(jì)的算法是否同時(shí)適合批處理和實(shí)時(shí)計(jì)算,如果同一份代碼可以很好地處理兩者,那么可以選擇Kappa架構(gòu);但是針對(duì)某些復(fù)雜的案例,其實(shí)時(shí)計(jì)算的結(jié)果和批處理的結(jié)果是不同的,比如某些機(jī)器學(xué)習(xí)的應(yīng)用,由批處理生成預(yù)測(cè)模型,再交由實(shí)時(shí)計(jì)算系統(tǒng)進(jìn)行實(shí)時(shí)分析,那么這種情況下,批處理層和實(shí)時(shí)計(jì)算層不能進(jìn)行合并,因此應(yīng)該選擇Lambda架構(gòu)。
運(yùn)維成本
Kappa架構(gòu)的運(yùn)維成本較低,比較適合技術(shù)人力資源有限的團(tuán)隊(duì)或企業(yè)。
StreamSQL與Lambda架構(gòu)Transwarp StreamSQL是星環(huán)科技專門為企業(yè)級(jí)用戶打造的流計(jì)算引擎,主要應(yīng)用于實(shí)時(shí)性較強(qiáng)的應(yīng)用場(chǎng)景。比如,金融行業(yè)需要對(duì)市場(chǎng)波動(dòng)進(jìn)行實(shí)時(shí)預(yù)警;銀行業(yè)務(wù)需要在線分析業(yè)務(wù)等。它對(duì)于SQL和PL/SQL的支持使得用戶可以通過(guò)SQL的方式實(shí)現(xiàn)復(fù)雜業(yè)務(wù)邏輯,大大降低了流應(yīng)用開發(fā)的門檻,也使得基于一套SQL程序開發(fā)離線和實(shí)時(shí)業(yè)務(wù)成為可能。
圖3為利用Kafka和StreamSQL搭建的一個(gè)Kappa架構(gòu)系統(tǒng),并且對(duì)原有的Kappa架構(gòu)的缺點(diǎn)做了改進(jìn)。
StreamSQL每隔100ms會(huì)從Kafka消息隊(duì)列中接收一批時(shí)序數(shù)據(jù),如t0-tn時(shí)刻的數(shù)據(jù),其中t0的數(shù)據(jù)為(0,1,2,3,4),t1的數(shù)據(jù)為(5,6,7,8,9)…。當(dāng)前批次的數(shù)據(jù)會(huì)被映射成一張二維關(guān)系表,通過(guò)SQL進(jìn)行變換并轉(zhuǎn)成內(nèi)存列式存儲(chǔ),變換后的數(shù)據(jù)會(huì)實(shí)時(shí)寫入Holodesk以持久化到SSD上,通過(guò)此方式***保留或者保留最近一個(gè)月的數(shù)據(jù)。應(yīng)用程序可以通過(guò)Inceptor SQL或者R語(yǔ)言對(duì)Holodesk中的列式數(shù)據(jù)進(jìn)行統(tǒng)計(jì)分析。
StreamSQL對(duì)Kappa架構(gòu)的改進(jìn)之處,包括如下:
上述提到,原本的Kappa架構(gòu)把歷史數(shù)據(jù)保存在Kafka或類似的分布式消息隊(duì)列,這樣的特性導(dǎo)致了一個(gè)缺點(diǎn)就是它只能保存幾天或幾個(gè)月的數(shù)據(jù),并且只能以流的形式保存,因此對(duì)于歷史數(shù)據(jù)的處理能力有限;而StreamSQL支持輸出到多種格式,既允許輸出到Kafka,也可以將結(jié)果以各類格式(TEXT表、ORC表、Holodesk表、HBase表)保存在Inceptor,實(shí)現(xiàn)更長(zhǎng)期的存儲(chǔ),因此它可以應(yīng)對(duì)更大數(shù)據(jù)規(guī)模的業(yè)務(wù)需求。
StreamSQL支持在實(shí)時(shí)計(jì)算時(shí)或歷史數(shù)據(jù)分析時(shí)將流數(shù)據(jù)和Inceptor表的數(shù)據(jù)做關(guān)聯(lián),大大增強(qiáng)了它的歷史數(shù)據(jù)處理能力。
StreamSQL另一特色功能就是它可以***兼容SQL標(biāo)準(zhǔn)和PL/SQL,使得用戶可以通過(guò)SQL的方式實(shí)現(xiàn)業(yè)務(wù)邏輯,極大降低了流應(yīng)用開發(fā)的門檻。
StreamSQL還增加了Application管理的功能,運(yùn)行時(shí)各個(gè)Application之間相互隔離并需要權(quán)限驗(yàn)證,很大程度上提高了系統(tǒng)的安全性和可用性。
Kappa架構(gòu)案例分析下面我們以StreamSQL作為流處理引擎來(lái)搭建一個(gè)基于Kappa架構(gòu)的智慧交通系統(tǒng),并對(duì)其中的套牌車輛實(shí)時(shí)預(yù)警業(yè)務(wù)場(chǎng)景進(jìn)行詳細(xì)的數(shù)據(jù)流分析,架構(gòu)圖如圖4所示:
當(dāng)前端卡口將監(jiān)控到的車輛信息接入Kafka分布式消息隊(duì)列后,總線會(huì)對(duì)這些數(shù)據(jù)進(jìn)行歸類分揀,分發(fā)給不同的服務(wù)集群,比如實(shí)時(shí)入庫(kù)服務(wù)集群、未年檢車監(jiān)控服務(wù)集群等。
假設(shè)部分?jǐn)?shù)據(jù)被送入到了違法車輛監(jiān)控服務(wù)集群中,該集群其中一個(gè)業(yè)務(wù)是對(duì)車輛進(jìn)行套牌分析。前面的章節(jié)提到Kappa架構(gòu)方便進(jìn)行算法模型的調(diào)優(yōu),下面我們來(lái)看一下具體是怎么做的。
首先,假如我們創(chuàng)建了一個(gè)UDF函數(shù)DectectCloneVehicle(param1, param2),用于檢查待檢測(cè)牌照是否為套牌車輛。該UDF接收兩個(gè)輸入?yún)?shù):當(dāng)兩輛相同牌照的車直線距離超過(guò)param1公里且出現(xiàn)時(shí)間低于param2分鐘時(shí),則被視為套牌車。該函數(shù)有兩種返回結(jié)果:如果是套牌車則輸出1,否則輸出0。
假設(shè)我們起初設(shè)定的套牌分析策略是,如果某兩輛相同牌照的車直線距離超過(guò)20公里,出現(xiàn)時(shí)間小于2分鐘, 那么判定該車牌被套牌。啟動(dòng)一個(gè)Stream Job實(shí)例,并按照該策略進(jìn)行分析的StreamSQL語(yǔ)句如下:
- CREATE STREAM vehicle_stream1(license STRING, location STRING, time TIMESTAMP)
- ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
- TBLPROPERTIES ("topic"=fakeLicense", kafka.zookeeper"="172.16.1.128:2181",
- "timefield"="time", "timeformat"="yyyy-MM-dd HH-mm-ss.SSS);
- CREATE TABLE clone_vehicle_result_app1(license STRING,location STRING, time TIMESTAMP);
- INSERT INTO clone_vehicle_result_app1
- SELECT DetectCloneVehicle(20, 2) as cloned
- FROM vehicle_stream1
- HAVING cloned>0;
但是通過(guò)實(shí)踐并且考慮到一些現(xiàn)實(shí)情況(如直線距離是否合理,當(dāng)前路段高速類路段多還是低速路段多等),我們發(fā)現(xiàn)如果按照此參數(shù)執(zhí)行檢測(cè),套牌排查效率會(huì)很低。假如把套牌車輛的判定標(biāo)準(zhǔn)調(diào)整為:直線距離超過(guò)10公里,出現(xiàn)時(shí)間小于5分鐘的兩輛相同牌照的車,效率就會(huì)有極大幅度的提升?,F(xiàn)在重新啟動(dòng)一個(gè)Stream Job實(shí)例,執(zhí)行如下的StreamSQL語(yǔ)句:
- CREATE STREAM vehicle_stream2(license STRING, location STRING, time TIMESTAMP)
- ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
- TBLPROPERTIES ("topic"=fakeLicense", kafka.zookeeper"="172.16.1.128:2181",
- "timefield"="time", "timeformat"="yyyy-MM-dd HH-mm-ss.SSS);
- CREATE TABLE clone_vehicle_result_app2(license STRING,location STRING, time TIMESTAMP);
- INSERT INTO clone_vehicle_result_app2
- SELECT DetectCloneVehicle(10, 5) as cloned
- FROM vehicle_stream2
- HAVING cloned>0;
該Stream Job的效率高于之前所選用的參數(shù),這樣我們就進(jìn)行了一步UDF模型參數(shù)的調(diào)優(yōu)。所以在做實(shí)際分析時(shí),業(yè)務(wù)執(zhí)行效率的提升不能單純的依靠系統(tǒng)提供的優(yōu)化幫助,用戶需要能夠根據(jù)所采用的架構(gòu)和所處理的問(wèn)題、應(yīng)用的模型方法,結(jié)合實(shí)際外部限制選擇最有效的模型參數(shù)。
結(jié)語(yǔ)Lambda架構(gòu)和Kappa架構(gòu)是常用的兩個(gè)大數(shù)據(jù)系統(tǒng)架構(gòu),它們都意在解決批處理和實(shí)時(shí)計(jì)算相結(jié)合的問(wèn)題。對(duì)于Lambda架構(gòu),如何簡(jiǎn)化其開發(fā)方式,降低運(yùn)維成本,是一件值得考慮和繼續(xù)研究的事情。Kappa架構(gòu)非常顯著的改進(jìn)了Lambda需要維護(hù)兩套系統(tǒng)的缺點(diǎn),但是在做服務(wù)選型的時(shí)候,僅僅使用開源Spark和Kafka接合還并不能設(shè)計(jì)出非常好的業(yè)務(wù)方案。
為此,星環(huán)科技基于Kappa的架構(gòu)設(shè)計(jì)了StreamSQL,通過(guò)高效的性能處理、HA保證、統(tǒng)一的SQL編程、允許流上數(shù)據(jù)和歷史數(shù)據(jù)關(guān)聯(lián)等創(chuàng)新技術(shù),有效的解決了Kappa對(duì)一些復(fù)雜場(chǎng)景處理能力不足的問(wèn)題,是一個(gè)理想的構(gòu)建Kappa系統(tǒng)的服務(wù)組件。