首先簡(jiǎn)單來(lái)說(shuō)一下,flink2.0做存算分離,最最主要的一點(diǎn)是解決,大狀態(tài)的問(wèn)題,例如一個(gè)超過(guò)50T的物流數(shù)據(jù),大狀態(tài)恢復(fù)可能就要1天,所以才有存算分離這么一個(gè)設(shè)計(jì)初衷。
下面先來(lái)看一下 任務(wù)是怎么執(zhí)行提交的,看一下state在整個(gè)流程里 處于一個(gè)什么位置
)
像為了解決算子checkpoint對(duì)齊 推出了unaligned CP + Buffer Debloating,阿里內(nèi)一般叫online checkpoint ,保存兩端channel數(shù)據(jù) 增速checkpoint的速度,測(cè)試后發(fā)現(xiàn) channel里的數(shù)據(jù)導(dǎo)致的checkpoint增加大小,對(duì)備份和恢復(fù)幾乎是沒(méi)有影響的,所以很值得(這部分不了解的可以看我的flink其他帖子,有一個(gè)checkpoint的,專門講了unaligned cp)
通用增量快照,是解耦了 flink本身做cp的流程和 state本身做快照的流程。這樣的話可以做雙寫,狀態(tài)做快照可以在backend后臺(tái)慢慢做,平時(shí)把狀態(tài)的增量快照持續(xù)上傳,真正需要做cp的時(shí)候,只需要上傳很少的數(shù)據(jù)。
下面右圖,尖峰減少了很多,是因?yàn)闋顟B(tài)后端做快照的時(shí)候,要做campation (忘了怎么拼),這個(gè)非常消耗cpu,并且狀態(tài)快照如果都集中在cp時(shí)上傳的話,網(wǎng)絡(luò)消耗峰值也會(huì)飆升。
1 引言
我們?cè)谶@個(gè)時(shí)間點(diǎn)重新聊狀態(tài)存儲(chǔ)這個(gè)話題是因?yàn)闋顟B(tài)存儲(chǔ)是流計(jì)算的核心。Flink 從 2017 年 VLDB 發(fā)表奠基之作介紹狀態(tài)存儲(chǔ)[1] 發(fā)展至今,F(xiàn)link 在狀態(tài)這部分的架構(gòu)基本并沒(méi)有太大的變化。但時(shí)代是在不斷演進(jìn)和變化的,無(wú)論部署模式、存儲(chǔ)模式,還是作業(yè)負(fù)載,都已經(jīng)發(fā)生了翻天覆地的變化。
從部署模式看,我們經(jīng)歷了 map-reduce 時(shí)代 Cluster 上沒(méi)有資源隔離的部署,到云原生時(shí)代 K8S 容器為粒度隔離部署。
與此同時(shí),硬件的提升也帶來(lái)的存儲(chǔ)模式的變化,最顯著的是網(wǎng)絡(luò)帶寬從 10 年前幾百 Mbps,到現(xiàn)在 25Gbps 起步,基本上可以和本地 SSD 的寬度比肩,且內(nèi)網(wǎng)傳輸?shù)脑捤俣瓤?、成本低,這使得存儲(chǔ)模式從本地存儲(chǔ),到分布式存儲(chǔ),再向云存儲(chǔ)的轉(zhuǎn)變。云存儲(chǔ)雖然延遲高,但具有容量大、成本低的優(yōu)勢(shì),非常契合現(xiàn)在降本增效的大背景。
另外作業(yè)負(fù)載方面也發(fā)生了很大變化,F(xiàn)link 剛誕生時(shí),幾百 MB 的狀態(tài)就算大狀態(tài)場(chǎng)景了,而現(xiàn)在物流等一些場(chǎng)景下,幾百 TB 的狀態(tài)也是很常見(jiàn)的。技術(shù)的進(jìn)步、用戶需求的變化帶給我們對(duì)狀態(tài)存儲(chǔ)這個(gè)部分的一些新的思考,這就有了本文要探討的話題。
本文內(nèi)容主要分為三個(gè)方面探討一下 Flink 存算分離架構(gòu)的演進(jìn)方向。
第一部分,先講為什么狀態(tài)對(duì) Flink 的重要性,因?yàn)闋顟B(tài)訪問(wèn)在單條數(shù)據(jù)處理路徑上,處理延遲對(duì)整體性能影響很大;
第二部分,會(huì)講一講近期狀態(tài)存儲(chǔ)這個(gè)部分社區(qū)以及我們?cè)诎⒗飪?nèi)部所做的一些工作和探索;
第三部分,聊一聊基于這些探索工作,F(xiàn)link 存算分離架構(gòu)應(yīng)該是什么樣的。
2 為什么狀態(tài)對(duì) Flink 如此重要
2.1 狀態(tài)的角色
在 Flink 流處理中,如果后續(xù)計(jì)算需要依賴前面輸入的時(shí)候,需要用狀態(tài)表(State Table)來(lái)保存中間數(shù)據(jù)。在 Task Manager 中,通過(guò)一個(gè)稱為 StateBackend 的服務(wù)組件為算子層提供狀態(tài)讀寫服務(wù)。如果狀態(tài)太大,內(nèi)存無(wú)法承載時(shí),StateBackend 會(huì)把狀態(tài)數(shù)據(jù)以文件的形式組織并存儲(chǔ)在本地磁盤上。但是通常本地盤不具備數(shù)據(jù)可靠性,所以 Flink 需要對(duì)狀態(tài)進(jìn)行定期的快照,把本地文件上傳到分布式文件系統(tǒng)(OSS/HDFS/S3 等)。另外,一個(gè) Flink 作業(yè)中往往有多個(gè)Task 包含有狀態(tài)算子,因此 Flink 需要確保這些不同的 Task 上的狀態(tài)快照是全局一致的,也就是說(shuō)是對(duì)齊輸入的,這個(gè)過(guò)程就是 Flink Checkpointing 過(guò)程。
2.2 Flink狀態(tài)管理的需求以及現(xiàn)存的問(wèn)題
這一部分我們主要探討一下目前 Flink 狀態(tài)存儲(chǔ)的需求以及現(xiàn)存的問(wèn)題,有了這個(gè)前提我們才能“對(duì)癥下藥”。
首先,狀態(tài)處理是流計(jì)算的關(guān)鍵路徑。目前 Flink State 接口都是單線程、單 KV 訪問(wèn)模式的,因此 State 讀寫的延遲會(huì)極大地影響 Flink 作業(yè)的處理性能(TPS)。而大多數(shù) Flink 線上作業(yè)都會(huì)掛載本地盤,其訪問(wèn)延遲基本在 us 級(jí)別。如果將狀態(tài)本地存儲(chǔ)直接替換成 DFS 存儲(chǔ)后,訪問(wèn)延遲部分會(huì)遇到很大的瓶頸,這也是之前很多人嘗試 Flink 遠(yuǎn)端狀態(tài)存儲(chǔ)遇到性能問(wèn)題的原因。另外,對(duì)狀態(tài)做快照的過(guò)程也需要盡量輕量穩(wěn)定,不能影響正常的數(shù)據(jù)處理。
在云原生的大背景下,對(duì)狀態(tài)提出了更高的要求。
首先是本地盤大小的限制。容器化技術(shù)可以做到很好的資源隔離,這也就意味著資源需要預(yù)分配。在 Flink 場(chǎng)景中,作業(yè)在啟動(dòng)時(shí) Task Manager 本地盤大小就已經(jīng)固定了;在作業(yè)運(yùn)行期間進(jìn)行磁盤重新掛載(remount)又十分麻煩,一般各大云廠商的全托管服務(wù)也不支持這種高級(jí)功能。因此,如果在作業(yè)運(yùn)行期間本地磁盤滿了,通常只能通過(guò)擴(kuò)并發(fā)解決。但對(duì)于公有云用戶來(lái)說(shuō),往往是不太愿意因?yàn)闋顟B(tài)寫滿磁盤去多付費(fèi)的。
除了本地盤資源,對(duì)于其他資源(比如 CPU 和 Network IO 等)也是一樣的,容器化架構(gòu)希望這些資源使用可以盡量平滑,避免出現(xiàn)尖峰,才能更好地實(shí)現(xiàn)資源隔離。最后是高效的彈性伸縮(Elasticity),社區(qū)現(xiàn)在結(jié)合 K8S Operator 可以做到原地 rescale, 以及利用 1.19 將要做的 Local Rescale 可以部分解決彈性伸縮的問(wèn)題,但是狀態(tài)稍微大點(diǎn)之后還是會(huì)有狀態(tài)下載慢的問(wèn)題。
此外還有一些用戶視角來(lái)講的需求,比如說(shuō)狀態(tài)可查詢和狀態(tài)可復(fù)用。關(guān)于狀態(tài)可查詢,社區(qū)經(jīng)常有用戶詢問(wèn) Queryable State, 但 Queryable State 其自身架構(gòu)存在缺陷,開啟時(shí)會(huì)影響 Task Manager 正常的數(shù)據(jù)處理,目前在社區(qū)已經(jīng)處于 Deprecate 狀態(tài)。我們后續(xù)在存算分離架構(gòu)設(shè)計(jì)的時(shí)候也是需要全面考慮這類需求的。
3 狀態(tài)存儲(chǔ)提升 —— 社區(qū)和商業(yè)版狀態(tài)存儲(chǔ)
基于上述的這些需求和挑戰(zhàn),我們接下來(lái)看一下,在社區(qū)和我們的商業(yè)版本里面,圍繞狀態(tài)存儲(chǔ)優(yōu)化我們都做了哪些嘗試以及還存在什么問(wèn)題。
3.1 分布式快照架構(gòu)升級(jí)
分布式快照這個(gè)部分,從 Flink 1.11 版本開始,歷經(jīng)社區(qū) 6 個(gè)版本,我們?cè)?Checkpoint 的穩(wěn)定性和完成速度方面做了一些工作,主要包含三個(gè)功能:動(dòng)態(tài)調(diào)節(jié)緩存數(shù)據(jù)(Buffer Debloating)、非對(duì)齊快照(Unaligned Checkpoint)、通用增量 checkpoint。這三個(gè)功能在各大公司都有大規(guī)模實(shí)際落地,發(fā)揮其應(yīng)有的價(jià)值。
Unaligned Checkpoint 和 Buffer Debloating 主要是為了防止或者減少反壓時(shí) Checkpoint Barrier 被算子間管道中數(shù)據(jù)阻塞的情況發(fā)生。從實(shí)驗(yàn)結(jié)果來(lái)看 Unaligned Checkpoint 在反壓的時(shí)能把快照完成時(shí)間縮短 90%(這個(gè)前提是 state size 不能太大,barrier 對(duì)齊時(shí)間是主要因素)。另外,因?yàn)?Unaligned Checkpoint 存儲(chǔ)了算子管道中的數(shù)據(jù),所以我們也測(cè)試了其對(duì)全量 Checkpoint 大小和狀態(tài)恢復(fù)時(shí)間的影響,測(cè)試結(jié)果顯示全量 Checkpoint 大小的增加和狀態(tài)恢復(fù)的額外時(shí)間基本上可以忽略不計(jì)。
當(dāng)作業(yè)狀態(tài)比較大的時(shí)候,狀態(tài)上傳時(shí)間就會(huì)成為 Checkpoint 完成耗時(shí)的主導(dǎo)因素,這時(shí)我們可以用通用增量快照來(lái)加速 Checkpoint。通用增量快照解耦了 Checkpointing 過(guò)程和狀態(tài)快照過(guò)程,可以把增量的狀態(tài) changelog 持續(xù)上傳到 DFS,使得在做 Checkpoint 時(shí)只需要上傳很少的數(shù)據(jù)量,因此可以做到無(wú)論狀態(tài)多大, Checkpoint 基本都可以在 10s 內(nèi)完成(Nexmark 上所有狀態(tài) Query 的測(cè)試結(jié)果均符合)。
通用增量 Checkpoint 最開始是為加速 Checkpoint 設(shè)計(jì)的,后來(lái)發(fā)現(xiàn)還有一些額外的收益,如上圖所示,CPU 和網(wǎng)絡(luò)流量的尖峰使用減少了 70%,這對(duì)于整體 Cluster 的穩(wěn)定性和資源節(jié)省都是非常關(guān)鍵的。該優(yōu)化的原因是原來(lái) Flink 周期性快照會(huì)讓作業(yè)中所有 Rocksdb 狀態(tài)后端周期性觸發(fā) Compaction 和上傳文件,導(dǎo)致 Checkpoint 期間消耗大量 CPU 和 Network IO,容易形成 CPU 和 Network IO 尖峰。通用增量快照把 Checkpointing 和狀態(tài)快照過(guò)程解耦后,狀態(tài)快照觸發(fā)的時(shí)間可以隨機(jī)化,避免 CPU 和網(wǎng)絡(luò)使用尖峰的形成。
另外,因?yàn)橥ㄓ迷隽靠煺账俣群芸?,在容錯(cuò)時(shí)數(shù)據(jù)回放量可以大大減少,這對(duì)于重復(fù)數(shù)據(jù)比較敏感的作業(yè)是非常關(guān)鍵的。事物都有兩面性,通用增量快照的額外開銷是需要雙寫數(shù)據(jù),我們也利用 Nexmark Stateful Query 測(cè)試了其對(duì) TPS 的影響,結(jié)果顯示在網(wǎng)絡(luò)帶寬不是瓶頸的情況下,通用增量快照對(duì)壓測(cè) TPS 影響小于 5%。
3.2 面向云原生:高效彈性擴(kuò)縮容
除了 Checkpoint 這個(gè)部分,社區(qū)從 1.17 開始也在嘗試更高效的彈性擴(kuò)縮容。
首先 Flink 1.18 中 Adaptive Scheduler 支持了 Rest API,K8S auto scaler 可以調(diào)用這個(gè) API 進(jìn)行原地?cái)U(kuò)縮容,也就是說(shuō)在更新作業(yè)之后 Task Manager 和 Job Manager 不用被重啟,可以最大限度的復(fù)用現(xiàn)有資源。
其次,對(duì)于文件下載這個(gè)部分,F(xiàn)link-1.18 開始支持并行下載,平均耗時(shí)減少 30%;在 1.19 預(yù)計(jì)會(huì)支持 Local Rescale,擴(kuò)縮容的時(shí)候可以免除重復(fù)下載,配合上述的 K8S 原地?cái)U(kuò)縮容,這個(gè)部分提升應(yīng)該是會(huì)很大的。
最后在狀態(tài)重建這個(gè)方面,F(xiàn)link 1.18 中恢復(fù)狀態(tài)時(shí)禁用 WAL,可以減少恢復(fù)時(shí)的額外開銷;Flink 1.19 之后,狀態(tài)重建可以支持文件粒度的合并裁剪,重建狀態(tài)后端耗時(shí)減少 50% - 80%。
3.3 Gemini:面向流計(jì)算場(chǎng)景的分層狀態(tài)存儲(chǔ)
這一章節(jié)分享我們?cè)诎⒗飪?nèi)部做的關(guān)于狀態(tài)云原生部分的一些探索:Gemini,阿里自研的一款面向流計(jì)算場(chǎng)景的分層狀態(tài)存儲(chǔ)。
Gemini 在阿里內(nèi)部全量上線,服務(wù)于不同狀態(tài)大小的作業(yè)(從幾百M(fèi)B到上百TB),也成功度過(guò)了 2021 — 2023 雙十一的洗禮,取得了非常好的降本增效效果。另外,我們基于 Flink1.15 利用 Nexmark Benchmark,對(duì) Gemini 和 Rocksdb 做了純狀態(tài)后端層面的性能對(duì)比,從測(cè)試結(jié)果可以看出 Gemini 對(duì)作業(yè)性能(單核吞吐能力)提升效果十分顯著,平均 50%+。
Gemini 可以看成是一個(gè)分層的狀態(tài)存儲(chǔ),內(nèi)存數(shù)據(jù)存放在 Mem Table(讀寫) 和 Cache(只讀)中,熱數(shù)據(jù)被寫在 Local Disk,本地盤寫滿后將部分冷數(shù)據(jù)寫到 DFS 上。拋開 DB 其他功能,我們重點(diǎn)分享一下 Gemini 存算分離方面的探索。首先,云上全托管服務(wù)都是有磁盤容量限制的,大部分用戶是不愿意為狀態(tài)把本地盤寫滿這件事情額外付費(fèi)去增加并發(fā)的,所以 Gemini 實(shí)現(xiàn)了本地和遠(yuǎn)端統(tǒng)一的文件管理,把本地盤作為主存,DFS 作為再下一級(jí)存儲(chǔ),在 DFS 上數(shù)據(jù)量不大的情況下,性能是可以接受的,但是如果頻繁訪問(wèn) DFS,性能還是會(huì)有較大的影響。
在快速擴(kuò)縮容方面,Gemini 主要有兩方面優(yōu)化:文件粒度合并剪裁以及狀態(tài)文件懶加載。其中,文件粒度合并剪裁和社區(qū)現(xiàn)在的做法稍有不同,Gemini 的文件裁剪是異步的,可以讓作業(yè)更快地恢復(fù);狀態(tài)文件懶加載是指遠(yuǎn)端文件異步下載,按需加載,F(xiàn)link 作業(yè)在恢復(fù)元數(shù)據(jù)后, 就可以開始半速運(yùn)行。從我們的測(cè)試結(jié)果中可以看到,熱更新+狀態(tài)懶加載可以讓作業(yè)停止處理的時(shí)間從 200s 下降到 20s。
4 狀態(tài)管理存算分離架構(gòu) —— 架構(gòu)演進(jìn)和挑戰(zhàn)
在狀態(tài)管理分層架構(gòu)下,狀態(tài)使用的難題目前都有一些解決方案,但是這些方法并不是很完美,我們?cè)趯?shí)現(xiàn)過(guò)程中也遇到了一些困難,在最后一節(jié)和大家分享一下我們的經(jīng)驗(yàn),以及存算分離架構(gòu)演進(jìn)的可能方案。
4.1 云原生架構(gòu)演進(jìn)
在 Gemini 的統(tǒng)一文件管理架構(gòu)中,狀態(tài)文件會(huì)在本地盤滿了以后刷到 DFS,但仍然以本地存儲(chǔ)作為 Primary Storage。這種形式的弊端是讓文件管理比較復(fù)雜而且不太好擴(kuò)展,比如說(shuō)我們有更多層的存儲(chǔ)時(shí)需要架構(gòu)有較大改動(dòng)。這種形式相對(duì)于把本地存儲(chǔ)當(dāng)成 Cache 的情況會(huì)更復(fù)雜,特別是對(duì)于文件寫失敗等異常情況的處理。其次,以本地 state 為主存的模型中,每個(gè) Task 缺少算子完整狀態(tài)的 Global View,這會(huì)讓狀態(tài)的共享化比較難以實(shí)現(xiàn),對(duì)于一些狀態(tài)特別大且有共享需求的作業(yè)來(lái)說(shuō),實(shí)現(xiàn)成本就會(huì)成倍增加。更關(guān)鍵的是現(xiàn)在這種模式下,很多 DB 設(shè)計(jì)都是基于本地存儲(chǔ)為主存的前提做的,這讓狀態(tài) DB Compaction 和冷熱分離策略都變得相對(duì)復(fù)雜,計(jì)算節(jié)點(diǎn)和存儲(chǔ)節(jié)點(diǎn)的捆綁實(shí)際還是比較緊密的。
為此我們可以考慮換個(gè)思路來(lái)做這個(gè)事情,把 DFS 作為 Primary Storage,而把本地磁盤作為 Cache 并且是不強(qiáng)制需要的(Optional),DFS 的數(shù)據(jù)是 Source of truth。在這種形式下,狀態(tài)數(shù)據(jù)直接持續(xù)寫入 DFS,內(nèi)存和本地盤作為 Cache,服務(wù)于上層的算子狀態(tài)訪問(wèn)。這種架構(gòu)的好處是:
-
Checkpoint 被觸發(fā)的時(shí)候,大部分狀態(tài)文件已經(jīng)在 DFS 上了, Checkpoint 可以速度很快;
-
狀態(tài)文件在算子之間是可以共享的,一些場(chǎng)景下通過(guò)共享狀態(tài)計(jì)算,存儲(chǔ)資源可以大大減少;
-
狀態(tài)查詢可以基于遠(yuǎn)端 Checkpoint 文件實(shí)現(xiàn),并提供文件級(jí)別 API;
-
Compaction 和狀態(tài)清理不再和 Task Manager 綁定,我們可以通過(guò) remote compaction、load balancing 等手段來(lái)均衡 Cluster 整體資源的使用。
然而僅僅將狀態(tài)主存從本地磁盤切換到遠(yuǎn)端文件系統(tǒng),就可以完美實(shí)現(xiàn)存算分離架構(gòu)了嗎?答案是 No。僅僅如此的話,作業(yè)性能會(huì)特別差,因?yàn)橄啾扔诒镜貭顟B(tài)架構(gòu),State 寫到遠(yuǎn)端后訪問(wèn)性能會(huì)出現(xiàn)很大回退。
4.2 Flink 現(xiàn)有狀態(tài)訪問(wèn)線程模型
性能回退的原因是受限于目前的 Flink 線程訪問(wèn)模型,數(shù)據(jù)處理必須以單線程單條 Record 處理的模式進(jìn)行,對(duì) State 訪問(wèn)的延遲極其敏感。其中,狀態(tài)訪問(wèn)以單 KV 為粒度;算子數(shù)據(jù)處理會(huì)封裝成 Mail,在 task 線程中順序執(zhí)行,因此單 record 的延遲對(duì)性能影響很明顯。從讀寫鏈路上具體分析的話,對(duì)狀態(tài)的寫路徑是 non-blocking 的,writes 追加寫到 writeBuffer 中,writeBuffer 寫滿后異步刷到磁盤上,所以 write 流程對(duì)于整體的 TPS 影響不大。但是讀路徑是非常影響整體性能的,讀數(shù)據(jù)時(shí)如果在 Block Cache 中 Cache miss,需要從磁盤上讀取數(shù)據(jù),讀取過(guò)程會(huì)阻塞數(shù)據(jù)處理,影響作業(yè)總體的性能。
更近一步,我們可以看到 Task 線程執(zhí)行一次計(jì)算時(shí),時(shí)間主要消耗在以下幾個(gè)部分:
-
Operator CPU:用于執(zhí)行算子邏輯;
-
State CPU:讀寫 access 以及序列化反序列化等;
-
State IO:狀態(tài)讀盤的時(shí)間。正因?yàn)樽x盤操作是 Blocking IO,而 DFS 的訪問(wèn)延遲相比于本地盤很大很多,所以單線程模型直讀 DFS 速度會(huì)比本地盤慢很多。
為了解決這個(gè)問(wèn)題,我們可以考慮把 Task 線程的 Blocking IO 改造成 Non-Blocking IO,這樣才能更高效地充分利用 CPU 和 IO 資源。在 state 文件多線程并發(fā)訪問(wèn)的初步實(shí)驗(yàn)中,當(dāng)我們把 thread pool size 調(diào)到足夠大的時(shí)候,性能有明顯的提升(約有 6 倍)。實(shí)際上,Non-Blocking IO 架構(gòu)要考慮的問(wèn)題肯定要比現(xiàn)在的 state 多線程訪問(wèn)實(shí)驗(yàn)要復(fù)雜很多,比如說(shuō)同一個(gè) Key 的執(zhí)行順序如何保證等等,我們也做了一些 POC 并得到一些初步結(jié)論,敬請(qǐng)期待后續(xù)文章分享。
5 總結(jié)
最后是本次分享的一些總結(jié) 。
第一是狀態(tài)訪問(wèn)在流計(jì)算中起到了非常關(guān)鍵的作用。在單條 record 的訪問(wèn)路徑上,狀態(tài)訪問(wèn)的處理速度會(huì)嚴(yán)重影響到 TPS ,這也是之前很多嘗試 Flink 遠(yuǎn)端狀態(tài)存儲(chǔ)訪問(wèn)會(huì)非常慢的原因。
第二,云原生時(shí)代對(duì)狀態(tài)存儲(chǔ)提出了更高的要求,比如受限的本地盤、快速擴(kuò)縮容以及平滑的資源使用等等。基于這個(gè),我們做了大量的優(yōu)化工作,但是還不太足夠,因此我們提出 State 的存儲(chǔ)訪問(wèn)架構(gòu)需要進(jìn)一步的演化。
第三,社區(qū)已經(jīng)推出的 Unaligned checkpoint 和通用增量 checkpoint 這兩個(gè)功能 ,逐步在各大公司和廠商里廣泛的實(shí)踐和使用,我們內(nèi)部也進(jìn)行了小范圍的嘗試,效果很不錯(cuò)。
第四,介紹了 Gemini,阿里內(nèi)部的面向流計(jì)算的分層狀態(tài)存儲(chǔ),我們?cè)谶@個(gè)過(guò)程中進(jìn)行了一些云原生以及存算分離模型的探索。
6 Flink 大狀態(tài)管理痛點(diǎn)
從這里開始 我們就進(jìn)入改造實(shí)踐了。
6.1 Flink 狀態(tài)管理
狀態(tài)管理是有狀態(tài)流計(jì)算的核心。目前在 Flink 生產(chǎn)環(huán)境中使用的最多的狀態(tài)后端是基于 RocksDB 的實(shí)現(xiàn),它是一個(gè)以本地磁盤為主的狀態(tài)管理,將狀態(tài)文件存儲(chǔ)于本地,同時(shí)在進(jìn)行檢查點(diǎn)的時(shí)候?qū)⑽募芷谛詫懭?DFS 。這是一種存算一體的架構(gòu),它足夠簡(jiǎn)單,在小狀態(tài)作業(yè)下能夠保證穩(wěn)定高效,可以滿足絕大部分場(chǎng)景的需求。隨著 Flink 的發(fā)展,業(yè)務(wù)場(chǎng)景日益復(fù)雜,大狀態(tài)作業(yè)屢見(jiàn)不鮮,在存算一體的架構(gòu)下涌現(xiàn)了很多與狀態(tài)管理有關(guān)的現(xiàn)實(shí)問(wèn)題。
6.2 大狀態(tài)作業(yè)痛點(diǎn)
大狀態(tài)作業(yè)下,基于 RocksDB 本地磁盤存算一體的狀態(tài)管理主要會(huì)遇到以下四方面的問(wèn)題:
-
本地磁盤有可能會(huì)出現(xiàn)空間不足的情況,通常解決這類問(wèn)題的方法就是擴(kuò)容。在目前集群部署或是云原生部署的模式下,單獨(dú)進(jìn)行本地盤的擴(kuò)容是不方便的,所以用戶一般會(huì)增加并發(fā)度,也就是涉及到存儲(chǔ)和計(jì)算綁在一起進(jìn)行擴(kuò)容,加劇了計(jì)算資源的浪費(fèi)。
-
作業(yè)正常狀態(tài)訪問(wèn)時(shí),本地磁盤 I/O 也會(huì)遇到一些瓶頸。這導(dǎo)致作業(yè)整體性能不足,同樣需要進(jìn)行擴(kuò)并發(fā)操作。
-
檢查點(diǎn)的開銷比較大。由于狀態(tài)非常大,在檢查點(diǎn)期間對(duì)于遠(yuǎn)端存儲(chǔ)訪問(wèn)量呈現(xiàn)一個(gè)尖峰態(tài)勢(shì)。
-
在作業(yè)恢復(fù)的時(shí)候,需要從遠(yuǎn)端讀取全量文件到本地,這個(gè)過(guò)程也十分緩慢。
上述前兩點(diǎn)是影響用戶成本的問(wèn)題,而檢查點(diǎn)的開銷與恢復(fù)速度是 Flink 中影響易用性的關(guān)鍵問(wèn)題。
6.3 存算分離的架構(gòu)
對(duì)于以上問(wèn)題,我們提出了存算分離的架構(gòu)來(lái)解決。存算分離可以擺脫本地磁盤的限制,將遠(yuǎn)端存儲(chǔ)(DFS)作為主存儲(chǔ),同時(shí)將空閑的本地磁盤作為一個(gè) Cache 來(lái)進(jìn)行使用。同時(shí)用戶仍可以選擇本地磁盤作為主存儲(chǔ),還用原來(lái)的模式來(lái)運(yùn)行。這樣做的顯著的好處是,一方面由于磁盤空間和 I/O 性能不足的問(wèn)題不再影響計(jì)算資源,另一方面是狀態(tài)檢查點(diǎn)與恢復(fù)在遠(yuǎn)端就可以直接完成,變得更加輕量級(jí)。從架構(gòu)上完美解決了大狀態(tài)作業(yè)面臨的問(wèn)題。
7 阿里云自研狀態(tài)存儲(chǔ)后端 Gemini 的存算分離實(shí)踐
在進(jìn)入存算分離架構(gòu)探討的最開始,我希望先從阿里云自研的企業(yè)級(jí)狀態(tài)存儲(chǔ) Gemini 入手,探尋它在存算分離上的一些實(shí)踐,主要分為以下三項(xiàng):
7.1 多種文件系統(tǒng)分層管理
Gemini 能夠把遠(yuǎn)端作為狀態(tài)主存儲(chǔ)的一部分。它首先將狀態(tài)文件存儲(chǔ)于本地磁盤,如果本地磁盤不足,則將文件移動(dòng)到遠(yuǎn)端存儲(chǔ)。本地磁盤中存留的是訪問(wèn)概率高的文件,遠(yuǎn)端存儲(chǔ)的是不容易訪問(wèn)的文件。兩部分共同構(gòu)成了主存儲(chǔ),并在此基礎(chǔ)上進(jìn)行了冷熱劃分,保證了在給定資源條件下的高效服務(wù)。Gemini 的這種文件分層管理模式擺脫了本地磁盤空間的限制。理論上本地空間可以配置為零,以達(dá)到純遠(yuǎn)端存儲(chǔ)的效果。
7.2 狀態(tài)懶加載
Gemini 能夠支持遠(yuǎn)端文件存儲(chǔ),在作業(yè)恢復(fù)的場(chǎng)景之下,無(wú)需將數(shù)據(jù)從遠(yuǎn)端文件加載回本地就可以開啟服務(wù),使用戶作業(yè)進(jìn)入運(yùn)行狀態(tài)。這一功能稱為狀態(tài)懶加載。在實(shí)際恢復(fù)過(guò)程中,Gemini 僅需將元數(shù)據(jù)以及少量?jī)?nèi)存中的數(shù)據(jù)從遠(yuǎn)端加載回,就可以重建整個(gè)存儲(chǔ)并啟動(dòng)。
雖然作業(yè)已經(jīng)從遠(yuǎn)端文件啟動(dòng)了,但讀取遠(yuǎn)端文件涉及到更長(zhǎng)的 I/O 延遲,性能仍舊不理想,此時(shí)需要使用內(nèi)存和本地磁盤進(jìn)行加速。Gemini 會(huì)使用后臺(tái)線程進(jìn)行異步下載,將未下載的數(shù)據(jù)文件逐漸轉(zhuǎn)移至本地磁盤。下載過(guò)程分為多種策略,比如按照 LSM-tree 層次的順序,或者按照實(shí)際訪問(wèn)的順序來(lái)下載。這些策略可以在不同場(chǎng)景進(jìn)一步縮短從懶加載恢復(fù)到全速運(yùn)行性能的時(shí)間。
7.3 Gemini 延遲剪裁
在改并發(fā)的場(chǎng)景中,比如將兩個(gè)并發(fā)的狀態(tài)數(shù)據(jù)合并成一個(gè)并發(fā)時(shí),目前 RocksDB 是把這兩份數(shù)據(jù)都下載完成之后再做一個(gè)合并,涉及到將多余的數(shù)據(jù)剪裁掉,重建數(shù)據(jù)文件,其速度是比較慢的。社區(qū)針對(duì)這個(gè)過(guò)程進(jìn)行了很多的針對(duì)性優(yōu)化,但仍然避免不了數(shù)據(jù)文件的下載。Gemini 只需要把這兩部分?jǐn)?shù)據(jù)的元數(shù)據(jù)進(jìn)行加載,并且把它們合成一個(gè)特殊的 LSM-tree 結(jié)構(gòu),就可以啟動(dòng)服務(wù),這一過(guò)程稱為延遲剪裁。
重建后 LSM-tree 的層數(shù)相比正常情況下會(huì)比較多。比如針對(duì)圖中的例子,有兩個(gè) L0 層,兩個(gè) L1 層和兩個(gè) L2 層。由于 Flink 有 KeyGroup 數(shù)據(jù)劃分的機(jī)制存在,層數(shù)變多并不會(huì)對(duì)讀鏈路長(zhǎng)度造成影響。由于并未對(duì)數(shù)據(jù)進(jìn)行實(shí)際的裁剪,會(huì)存在一些多余的數(shù)據(jù),這些數(shù)據(jù)會(huì)在之后的整理 (Compaction) 過(guò)程逐步清理掉。延遲剪裁的過(guò)程無(wú)需對(duì)數(shù)據(jù)本身進(jìn)行下載和實(shí)際合并操作,它可以極大地縮短狀態(tài)恢復(fù)的時(shí)間。
7.4 Gemini 恢復(fù)效果
有了異步剪裁狀態(tài)+狀態(tài)懶加載,對(duì)于 Gemini 來(lái)說(shuō),恢復(fù)時(shí)間即作業(yè)從 INITIALIZING 到 RUNNING 的狀態(tài)可以變得非常之短,相比于本地狀態(tài)存儲(chǔ)的方案是一個(gè)極大的提升。
我們針對(duì) Gemini 與 RocksDB 的改并發(fā)時(shí)間進(jìn)行了評(píng)測(cè)。評(píng)測(cè)的指標(biāo)為從作業(yè)啟動(dòng)一直到恢復(fù)原有性能的時(shí)間,這包含了 Gemini 異步下載文件的時(shí)間。從上述實(shí)驗(yàn)結(jié)果中可以看到 Gemini 相比于RocksDB 在縮容、擴(kuò)容的場(chǎng)景下都有明顯的提升。
8 存算分離的進(jìn)一步探索
Gemini 做存算分離相關(guān)的優(yōu)化部分解決了前述大作業(yè)場(chǎng)景的問(wèn)題。本地空間不足的問(wèn)題可以通過(guò)遠(yuǎn)端空間來(lái)解決。針對(duì)檢查點(diǎn)開銷大的問(wèn)題,因?yàn)橐呀?jīng)有一部分文件遠(yuǎn)端存儲(chǔ)上了,無(wú)需再次上傳,這部分的開銷也得以減少。針對(duì)作業(yè)恢復(fù)慢的問(wèn)題,狀態(tài)懶加載+延遲剪裁功能,使得作業(yè)能夠快速的恢復(fù)運(yùn)行狀態(tài)。
這里還有一個(gè)功能是對(duì) Memtable 的快照。Gemini 在做檢查點(diǎn)的時(shí)候,是將 Memtable 的原樣上傳到遠(yuǎn)端存儲(chǔ)上,不會(huì)影響 Memtable flush 的過(guò)程,也不會(huì)影響內(nèi)部的 Compaction。它的效果和通用增量快照的 changelog 的效果是類似的,都會(huì)緩解檢查點(diǎn)時(shí)的 CPU 開銷和 DFS I/O 量的尖峰。
8.1 Gemini 存算分離的問(wèn)題
Gemini 在存算分離方面做了不錯(cuò)的實(shí)踐,在阿里內(nèi)部與云上客戶的大狀態(tài)作業(yè)場(chǎng)景下均取得了不錯(cuò)的效果。但它仍存在著一些問(wèn)題:
第一個(gè)問(wèn)題,Gemini 還是把本地磁盤作為主存的一部分,狀態(tài)文件是優(yōu)先寫到本地磁盤的,這并非最徹底的一個(gè)存算分離。這樣會(huì)導(dǎo)致檢查點(diǎn)時(shí)上傳文件數(shù)量還是會(huì)比較多,持續(xù)時(shí)間較長(zhǎng),做不到非常輕量級(jí)的檢查點(diǎn)。
第二個(gè)問(wèn)題,是所有存算分離方案都會(huì)遇到的一個(gè)問(wèn)題,就是與本地方案的性能差距。目前的方案中 Gemini 已經(jīng)利用了本地磁盤,但本地磁盤的利用效率并不是最高的。如果更多的請(qǐng)求可以落到內(nèi)存或者本地磁盤,對(duì)應(yīng)的遠(yuǎn)端 I/O 的請(qǐng)求數(shù)降低,作業(yè)整體性能會(huì)有提升。另外,異步 I/O 是很多存儲(chǔ)系統(tǒng)都會(huì)采用的優(yōu)化。它使用提高 I/O 并行度的方式來(lái)解決提高作業(yè)的吞吐,是值得嘗試的下一步優(yōu)化方向。
針對(duì)這幾個(gè)問(wèn)題我們進(jìn)行了簡(jiǎn)單的探索,首先是做了一個(gè)非常徹底的存算分離,直接寫入遠(yuǎn)端存儲(chǔ)并且把本地磁盤直接作為 Cache 來(lái)使用,在此基礎(chǔ)上實(shí)踐了不同形式的 Cache。第二方面,我們實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的異步 I/O PoC,驗(yàn)證其在存算分離場(chǎng)景上的性能提升。
8.2 直接寫入遠(yuǎn)端與本地磁盤Cache的探索
8.2.1 原始方案:基于文件的本地磁盤 Cache
直接使用遠(yuǎn)端存儲(chǔ)作為主存的改動(dòng)我們不作詳述,在這里主要探討 Cache 的形態(tài)與優(yōu)化問(wèn)題。最簡(jiǎn)單的架構(gòu)是基于文件的 Cache 。如果遠(yuǎn)端的文件被訪問(wèn)到,它會(huì)被加載到本地磁盤 Cache。與此同時(shí)內(nèi)存 Cache 仍然存在,并且仍舊采用 BlockCache 的形式。這個(gè)形式是非常簡(jiǎn)單高效的架構(gòu)。但是內(nèi)存 BlockCache 和本地磁盤的文件 Cache 有很大的一個(gè)數(shù)據(jù)重復(fù),這相當(dāng)于浪費(fèi)了很多空間。另一方面,由于文件的粒度相對(duì)較粗,對(duì)于同一個(gè)文件的不同 block ,其訪問(wèn)的概率并不一樣,所以會(huì)有一些冷的 block 維持在磁盤中,降低了本地磁盤的命中率。針對(duì)這兩個(gè)問(wèn)題,我們?cè)O(shè)計(jì)了全新的本地磁盤 Cache 的形態(tài),對(duì)上述問(wèn)題進(jìn)行優(yōu)化。
8.2.2 優(yōu)化方案:基于 Block 的本地磁盤 Cache
我們提出將本地磁盤與內(nèi)存結(jié)合起來(lái),組成一個(gè)以 block 為粒度的混合式 Cache。它使用一個(gè)整體的 LRU 進(jìn)行統(tǒng)一的管理,不同 block 只有介質(zhì)上的不同。內(nèi)存上相對(duì)冷的 block 會(huì)異步地刷到本地磁盤上,磁盤的 block 是按照順序以追加寫的形式來(lái)寫在底層文件中。如果由于 LRU 策略淘汰了某些磁盤的 block,必然會(huì)映射到某個(gè)文件上形成空洞。為了維持 Cache 空間有效性,我們采取了空間回收來(lái)進(jìn)行優(yōu)化。空間回收的過(guò)程是一個(gè)空間和 CPU 開銷的權(quán)衡。
不同層的文件如 L0 file 、L1 file 以及 L2 file,它們的生命周期是不一樣的。對(duì)于 L0 file 來(lái)講,它的生命周期比較短一些,但是熱度相對(duì)高。對(duì)于 L2 file 來(lái)講,文件本身更容易存活,但是熱度是相對(duì)低的。根據(jù)這些不同的特點(diǎn),我們可以采取不同的策略來(lái)進(jìn)行空間回收。來(lái)自不同層文件 block 會(huì)被 Cache 在不同的底層文件中。針對(duì)不同的底層文件可以執(zhí)行不同的空間回收閾值與頻率,這樣可以保證最大的空間回收效率。
另外我們針對(duì) block 淘汰策略也提出了優(yōu)化方案。最原始的 LRU 是根據(jù)命中頻率來(lái)進(jìn)行管理的,某個(gè) block 一段時(shí)間內(nèi)不命中則會(huì)被淘汰。這種策略并沒(méi)有考慮到在緩存某一個(gè)block 的空間開銷。也就是說(shuō)可能為了緩存某個(gè) block,卻有更多的 block 沒(méi)有辦法進(jìn)行緩存。在這里引入了一個(gè)新的評(píng)判體系叫做緩存效率,用一段時(shí)間內(nèi)命中次數(shù)除以 block 大小,來(lái)更好的評(píng)判每一個(gè)緩存的 block 是否應(yīng)該被緩存。這種評(píng)判方式的缺點(diǎn)是開銷會(huì)比較大。最基本的 LRU 針對(duì)于查詢都是 O(1) 的,但緩存效率的評(píng)分需要實(shí)現(xiàn)一個(gè)優(yōu)先隊(duì)列,其運(yùn)行效率會(huì)有較大下降。所以在這里的思路還是在保持 LRU 主體管理的情況下,針對(duì) block 的緩存效率異常的情況進(jìn)行特殊化處理。
目前發(fā)現(xiàn)有兩部分異常,第一部分是內(nèi)存中的 data block 。它的命中率是內(nèi)存中相對(duì)低的,但是它的占比能達(dá)到 50%。目前對(duì)于它的策略就是進(jìn)行壓縮,其代價(jià)是每次訪問(wèn)涉及到解壓,但這個(gè)開銷要比進(jìn)行一個(gè) I/O 的開銷要小得多。第二部分是磁盤中的 filter block 。雖然它有命中,但它的大小是比較大的,緩存效率并不高。在這里實(shí)現(xiàn)了一個(gè)傾向于把磁盤中的 filter block 優(yōu)先踢出的策略,使得相對(duì)上層的數(shù)據(jù)可以緩存進(jìn)來(lái)。在測(cè)試作業(yè)場(chǎng)景中,這兩條特殊規(guī)則與 LRU 相結(jié)合,相比于沒(méi)有這兩條規(guī)則的時(shí)候,整體 TPS 會(huì)上升 22%,效果比較顯著。
但直接寫入遠(yuǎn)端使系統(tǒng)出現(xiàn)了遠(yuǎn)端文件冷讀問(wèn)題,即文件第一次生成后的讀取仍然需要涉及到遠(yuǎn)端 I/O。為了解決這個(gè)問(wèn)題,我們?cè)谶@里也做了一個(gè)小的優(yōu)化,在本地磁盤上提供一個(gè)上傳遠(yuǎn)端的隊(duì)列,并且讓其中的文件多緩存一段時(shí)間。這個(gè)時(shí)間并不會(huì)很長(zhǎng),大概是二三十秒的一個(gè)級(jí)別,在此期間隊(duì)列文件的遠(yuǎn)端 I/O 會(huì)變?yōu)楸镜?I/O。這樣的做法能夠讓遠(yuǎn)端冷讀的問(wèn)題大大的緩解。
到目前為止我們有兩種存算分離的 Cache 方案,第一種是基于文件的本地磁盤 Cache 方案,它的優(yōu)點(diǎn)是非常簡(jiǎn)單和有效,在磁盤充足的場(chǎng)景下有與本地方案類似的性能,因?yàn)楸镜卮疟P可以緩存所有文件。第二種是混合式 block cache 的優(yōu)化,在本地磁盤不足的情況下是一個(gè)非常好的方案,因?yàn)樗嵘?Cache 的命中率。但是它也帶來(lái)了比較大的管理開銷。如果我們想要有一個(gè)通用的方案來(lái)適配所有場(chǎng)景,應(yīng)該怎么做呢?
8.2.3 混合方案:自適應(yīng)變化
將上述兩種方案結(jié)合,我們?cè)O(shè)計(jì)了一個(gè)自適應(yīng)變化的的混合方案。在磁盤充足的情況下使用的是基于文件的 Cache 方案,在磁盤不足的情況下,會(huì)把本地磁盤自動(dòng)的和內(nèi)存結(jié)合在一起組成混合式 block cache 方案。兩種方案的結(jié)合會(huì)讓它們兩個(gè)的優(yōu)點(diǎn)結(jié)合在一起,在所有的場(chǎng)景下都能夠最大化的滿足性能效率的需求。
8.2.4 混合方案:評(píng)測(cè)
我們針對(duì)上述提出的混合方案使用測(cè)試作業(yè)進(jìn)行評(píng)測(cè)??梢钥吹皆?TPS 上,新方案相比于文件為粒度的原始緩存方案有 80% 的提升。同時(shí)它也伴隨著一些 CPU 的開銷,用 CPU 效率(TPS/CPU)作為評(píng)判標(biāo)準(zhǔn),新方案也有 40% 的提升。Cache 命中率的提升是 TPS 提升的一個(gè)主要來(lái)源。
8.3 異步I/O的探索
8.3.1同步單條處理模式
第二項(xiàng)探索是對(duì) Flink 進(jìn)行的異步 I/O 改造與測(cè)試。如圖展示了目前 Flink 的單線程處理模型,在 Task 線程上面,所有的數(shù)據(jù)是按順序來(lái)進(jìn)行處理的。對(duì)于每一條數(shù)據(jù)處理,會(huì)分為算子(operator)的 CPU 開銷,狀態(tài)(State)訪問(wèn)的 CPU 開銷,以及狀態(tài)訪問(wèn)所需的 I/O 時(shí)間,其中 I/O 是最大的一塊開銷。由于存算分離需要訪問(wèn)遠(yuǎn)端存儲(chǔ),其 I/O 延遲會(huì)比本地方案大,最終會(huì)導(dǎo)致整體 TPS 有明顯下降。
8.3.2 批量處理+內(nèi)部異步模式
我們對(duì)這一模式進(jìn)行更改,使得 State 操作可以同時(shí)進(jìn)行。在 Task 線程的角度來(lái)講,State 被并行化之后整體的時(shí)間被縮小,所以 TPS 會(huì)有一個(gè)提升。同時(shí),Task 線程需要預(yù)先攢批,這和 micro-batch 做的事情是非常類似的,同理也可以借用預(yù)聚合的功能,降低 state 訪問(wèn)的數(shù)目,TPS 得以進(jìn)一步提升。
8.3.3 算子異步+批量處理模式
更進(jìn)一步,在加上狀態(tài)訪問(wèn)異步的基礎(chǔ)之上,可以繼續(xù)探索從算子的角度上進(jìn)行異步化的過(guò)程。這意味著狀態(tài)訪問(wèn)已經(jīng)開始了異步執(zhí)行后,讓 Task 線程得以繼續(xù)進(jìn)行其他數(shù)據(jù)的 CPU 操作。但這樣做有一個(gè)問(wèn)題:狀態(tài)訪問(wèn) I/O 一般都是時(shí)間比較長(zhǎng)的,雖然在 Task 線程閑的時(shí)候可以做一些其他的數(shù)據(jù)的處理工作,但是最終會(huì)一個(gè)速率不匹配的問(wèn)題,瓶頸最終還會(huì)落到狀態(tài)訪問(wèn)上,會(huì)退化到?jīng)]有做此優(yōu)化的情況。
經(jīng)過(guò)權(quán)衡,我們認(rèn)為僅采用攢批,再加上批內(nèi)的狀態(tài)訪問(wèn)使用異步 I/O 這種方式,是一個(gè)比較平衡的方案。
8.3.4 存算分離+批量化:評(píng)測(cè)
我們做了一個(gè)簡(jiǎn)單的支持批量異步的接口的狀態(tài)后端,并在社區(qū) Microbenchmark 上面做了一個(gè)簡(jiǎn)單的測(cè)試,目前僅涉及到 value get 的場(chǎng)景。從對(duì)比結(jié)果上可以看到,批量執(zhí)行加上異步 I/O 是對(duì)存算分離場(chǎng)景有很大的提升。
9 批量化異步 I/O 存算分離適用場(chǎng)景
上述探索的批量化執(zhí)行的存算分離狀態(tài)訪問(wèn)有獨(dú)特的應(yīng)用場(chǎng)景。對(duì)于大狀態(tài)作業(yè)來(lái)講,存算分離在功能上解決了最開始所述的幾個(gè)問(wèn)題,在性能上,用批量接口的方式來(lái)彌補(bǔ)它的低的問(wèn)題。
9.1 性能分析
此種方案的性能來(lái)源是 State 訪問(wèn)在批次內(nèi)并行化,減少了狀態(tài)訪問(wèn)的時(shí)間,提升了計(jì)算節(jié)點(diǎn)的 CPU 利用率。這種方案對(duì)于大狀態(tài)作業(yè)性能提升是很有用的。
9.2 定性性能分析
在小狀態(tài)作業(yè)的場(chǎng)景下,狀態(tài)訪問(wèn)可以做到非常的快,將狀態(tài)訪問(wèn)從 Task 線程抽離出來(lái)的提升量很小,且引入了線程之間交互的開銷。所以在小狀態(tài)的場(chǎng)景,這種批量異步狀態(tài)訪問(wèn)的方案或許還不如原始本地狀態(tài)管理方案。
隨著狀態(tài)大小逐漸增大,狀態(tài) I/O 開銷逐漸增大并成為了瓶頸,異步 I/O 的執(zhí)行當(dāng)于攤薄了每個(gè) I/O 所耗的時(shí)間。這導(dǎo)致了圖中紅色線的下降是較慢的,而本地狀態(tài)管理(藍(lán)色線)降低會(huì)比較快。在達(dá)到某個(gè)狀態(tài)大小后,異步 I/O 的方案性能會(huì)顯著的好。這種方案需要消耗 I/O 帶寬,如果狀態(tài)訪問(wèn)已經(jīng)達(dá)到了 I/O 上限,異步 I/O 不能減少 I/O 的總時(shí)間,故此時(shí)它的斜率跟本地狀態(tài)管理差不多。
如果狀態(tài)很小的時(shí)候就達(dá)到 I/O 上限,并行化執(zhí)行并不會(huì)產(chǎn)生效果,上圖所示的便是這個(gè)場(chǎng)景。
總結(jié)一下,批量并異步執(zhí)行狀態(tài)訪問(wèn)在滿足以下條件時(shí)會(huì)有優(yōu)勢(shì):
-
大狀態(tài)作業(yè)場(chǎng)景且狀態(tài)訪問(wèn)是作業(yè)的瓶頸
-
I/O 并沒(méi)有達(dá)到瓶頸(未打滿)
-
業(yè)務(wù)對(duì)于攢批的延遲(亞秒到秒級(jí)別)可以接受文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-835721.html
絕大部分存算分離場(chǎng)景下,由于 I/O 性能是存儲(chǔ)集群提供,可以支撐比較大的 I/O 量且可以靈活伸縮,一般不會(huì)過(guò)早達(dá)到 I/O 瓶頸狀態(tài),異步 I/O 可以很好的優(yōu)化存算分離場(chǎng)景。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-835721.html
到了這里,關(guān)于Flink 2.0 狀態(tài)管理存算分離架構(gòu)演進(jìn)與分離改造實(shí)踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!