Presto 在阿里云實(shí)時(shí)日志分析中的實(shí)踐和優(yōu)化
一、業(yè)務(wù)背景
首先第一部分介紹一下我們的業(yè)務(wù)背景。阿里云 SLS 是一個(gè)云上一站式可觀測(cè)日志服務(wù)平臺(tái)。
SLS 提供了強(qiáng)大的數(shù)據(jù)采集、數(shù)據(jù)加工、消費(fèi)投遞等能力,數(shù)據(jù)采集利器 ilogtail 目前也已經(jīng)完全開(kāi)源。數(shù)據(jù)采集上來(lái)后提供數(shù)據(jù)的統(tǒng)一存儲(chǔ),包括熱存、智能冷存等,幫助用戶(hù)盡可能節(jié)省成本。在存儲(chǔ)之上,提供了數(shù)據(jù)處理與分析能力,包括即席查詢(xún)分析、關(guān)聯(lián)分析等。這兩塊構(gòu)成了整個(gè) SLS 產(chǎn)品的核心基礎(chǔ)能力。在這個(gè)基礎(chǔ)能力之上提供了豐富的工具和應(yīng)用,最終服務(wù)于各種不同的角色和用戶(hù)。
本文將聚焦在存儲(chǔ)和分析基礎(chǔ)能力上面的建設(shè),重點(diǎn)分享日志分析系統(tǒng),以及在面對(duì)核心問(wèn)題時(shí)的一些架構(gòu)設(shè)計(jì)思路和經(jīng)驗(yàn)。
這是具體日志分析業(yè)務(wù)覆蓋和服務(wù)的能力,主要是圍繞日志場(chǎng)景去進(jìn)行數(shù)據(jù)分析。日志數(shù)據(jù)的形態(tài)是多種多樣的,包括無(wú)結(jié)構(gòu)的、半結(jié)構(gòu)的以及結(jié)構(gòu)化的。我們?cè)跀?shù)據(jù)源層面統(tǒng)一收集、存儲(chǔ)到存儲(chǔ)引擎當(dāng)中,再通過(guò) SQL 的分析引擎向上層提供數(shù)據(jù)分析服務(wù)。
具體業(yè)務(wù),包括比如實(shí)時(shí)監(jiān)控、實(shí)時(shí)大屏這一類(lèi)基于日志數(shù)據(jù)分析去做的一些業(yè)務(wù),其刷新率非常高,所以用戶(hù)的并發(fā)查詢(xún)請(qǐng)求量非常大;還有一些比如像基于日志的數(shù)據(jù)去做實(shí)時(shí)的告警、鏈路分析、交互式分析、AI 異常檢測(cè)等,這一類(lèi)業(yè)務(wù)主要是對(duì)于數(shù)據(jù)的時(shí)效性要求非常高,要求查詢(xún)和分析延時(shí)要能夠做到秒級(jí)實(shí)時(shí)。
還有一類(lèi)業(yè)務(wù),比如像可視化工具、運(yùn)營(yíng)報(bào)表、schedule SQL 這一類(lèi)的業(yè)務(wù),數(shù)據(jù)量是非常大的,面臨超大數(shù)據(jù)規(guī)模的問(wèn)題。就整體業(yè)務(wù)覆蓋而言,SLS 除了在阿里云上對(duì)外提供日志服務(wù)外,在集團(tuán)內(nèi)部也被眾多的 BU 所使用,同時(shí)也經(jīng)歷了多年雙十一的挑戰(zhàn)。
分析引擎的整體能力方面,我們目前每天大概有數(shù)十億次的查詢(xún),每天的行掃描規(guī)模大概在千萬(wàn)億級(jí)別,吞吐大概在數(shù)十 PB 規(guī)模。而我們平均的查詢(xún)延時(shí)小于 300ms,在業(yè)務(wù)高峰時(shí)刻的并發(fā)峰值能夠達(dá)到 7.2 萬(wàn),屆時(shí)系統(tǒng)會(huì)面臨數(shù)十萬(wàn)的 QPS 壓力。以上就是整體業(yè)務(wù)的情況。
二、核心問(wèn)題
面對(duì)上述業(yè)務(wù)場(chǎng)景和需求,我們面臨的最核心問(wèn)題主要包括四個(gè)方面。
首先,區(qū)別于傳統(tǒng)的離線數(shù)倉(cāng),我們是一個(gè)在線的實(shí)時(shí)分析服務(wù),所以對(duì)于查詢(xún)的低延時(shí)要求非常高。我們要求秒級(jí)的查詢(xún),并且數(shù)據(jù)要可見(jiàn)即可得、可得即可算。
第二,我們面對(duì)的數(shù)據(jù)處理規(guī)模是非常大的,數(shù)據(jù)的行掃描規(guī)模可能從百萬(wàn)到千億級(jí)別不等,并且規(guī)模是彈性多變的。
第三,會(huì)面臨用戶(hù)高并發(fā)的查詢(xún)壓力,像雙十一這種業(yè)務(wù)高峰時(shí)刻能達(dá)到 7.2 萬(wàn)的并發(fā)峰值,同時(shí)單點(diǎn)會(huì)有上千的并發(fā)查詢(xún)、數(shù)十萬(wàn)的計(jì)算任務(wù),所以如何去解決系統(tǒng)在面臨這種高并發(fā)查詢(xún)下的負(fù)載壓力,是我們面臨的又一個(gè)核心問(wèn)題。
最后還要去解決整個(gè)云服務(wù)的高可用以及租戶(hù)間的隔離,由于云服務(wù)多、租戶(hù)是共享云上資源的,所以不可避免會(huì)有各種各樣的熱點(diǎn)資源爭(zhēng)用。怎樣去解決服務(wù)的治理以及壓力的防控,保障云服務(wù)的高可用,也是我們面臨的核心問(wèn)題之一。
三、關(guān)鍵設(shè)計(jì)
接下來(lái)主要圍繞這四個(gè)核心的問(wèn)題,分享在系統(tǒng)架構(gòu)設(shè)計(jì)以及關(guān)鍵環(huán)節(jié)上面的思考和權(quán)衡。首先是 SLS 日志查詢(xún)分析范式,主要是由三部分因素組成:第一部分是查詢(xún)語(yǔ)句,類(lèi)似于搜索引擎,可以根據(jù)相關(guān)的關(guān)鍵字或者是一些過(guò)濾查詢(xún)條件,將特征數(shù)據(jù)檢索出來(lái)。第二部分是分析語(yǔ)句,也就是標(biāo)準(zhǔn)的 SQL 語(yǔ)句,可以針對(duì)檢索出來(lái)的一些特征數(shù)據(jù),進(jìn)行靈活的統(tǒng)計(jì)和分析。第三部分是時(shí)間范圍,可以指定任意的時(shí)間范圍,在這個(gè)范圍內(nèi)進(jìn)行日志數(shù)據(jù)的分析。所以這三個(gè)要素構(gòu)成了 SLS 整個(gè)日志查詢(xún)分析的范式。
日志數(shù)據(jù)有它自己的一些特點(diǎn)。首先時(shí)間是日志數(shù)據(jù)的一個(gè)天然屬性。其次日志分析 99% 的場(chǎng)景是面向特征的,比如像上圖中的示例,服務(wù)訪問(wèn)日志中包含時(shí)間、日志級(jí)別、地域、訪問(wèn)域名、http status、延時(shí)等多個(gè)字段,我們可能就想分析來(lái)自 cn-shanghai 地域的訪問(wèn)情況,那我們可以通過(guò)關(guān)鍵詞檢索過(guò)濾出需要分析的數(shù)據(jù)。第三,分析的數(shù)據(jù)往往具有局部性,比如對(duì)于上面的服務(wù)日志,我們可能就想分析 status 字段,那對(duì)于每一條檢索出來(lái)的日志,并不需要將整行日志的數(shù)據(jù)全部加載。這些日志數(shù)據(jù)的特點(diǎn)是實(shí)時(shí)、低延時(shí)查詢(xún)分析的關(guān)鍵所在。
實(shí)時(shí)計(jì)算、低延遲的關(guān)鍵,我認(rèn)為首先是快速定位數(shù)據(jù),其次是高效加載數(shù)據(jù),最后是如何執(zhí)行高效計(jì)算。在這里索引和列存是關(guān)鍵。首先介紹一下我們的存儲(chǔ)模型,這是一個(gè)三級(jí)結(jié)構(gòu),最外層是 project,實(shí)現(xiàn)了用戶(hù)級(jí)別的隔離;在 project 內(nèi)可以有多個(gè) logstore,它是日志數(shù)據(jù)的存儲(chǔ)單元,實(shí)現(xiàn)了生命周期 TTL 的管理;在一個(gè) logstore 內(nèi)部是由多個(gè)數(shù)據(jù)分片(我們叫它 Shard)組成。Shard 間是按照 Range 粒度進(jìn)行切分,日志數(shù)據(jù)的寫(xiě)入,是類(lèi)似于一個(gè)隊(duì)列的形式進(jìn)行追加,然后按照 hash 均衡負(fù)載到各個(gè) Shard 分片上。最終是以 LSM-Tree(log structure merge Tree)的寫(xiě)入模型將數(shù)據(jù)存儲(chǔ)下來(lái)。
前面我們剛剛提到了日志的一個(gè)天然屬性是時(shí)間,這里我們基于 LSM 追加寫(xiě)入模型,其實(shí)日志數(shù)據(jù)在一個(gè) Shard 內(nèi)都是按照時(shí)間進(jìn)行分布的。所以第一個(gè)關(guān)鍵點(diǎn)是基于時(shí)間檢索模型,根據(jù) From 和 To 的時(shí)間范圍可以快速地定位到某一個(gè) Shard 在某一段時(shí)間內(nèi)的數(shù)據(jù)。同時(shí)根據(jù)查詢(xún)分析范式,對(duì)于前面的查詢(xún)條件,我們可以利用索引倒排技術(shù),高效檢索出來(lái)我們需要的特征數(shù)據(jù)。同時(shí),剛剛還提到分析數(shù)據(jù)可能是局部的,用戶(hù)可能只需要分析日志數(shù)據(jù)中的某些字段,所以我們實(shí)現(xiàn)了列存,對(duì)于索引字段進(jìn)行列式存儲(chǔ),分析時(shí)將指定列的列存數(shù)據(jù)加載上來(lái)進(jìn)行分析即可。
所以,最終在 LSM 寫(xiě)入之后,會(huì)進(jìn)行異步的索引和列存構(gòu)建過(guò)程,最終統(tǒng)一存儲(chǔ)到我們的分布式存儲(chǔ)。這就構(gòu)成了我們整體的存儲(chǔ)模型??傮w來(lái)說(shuō),通過(guò)索引和列存,以空間來(lái)?yè)Q時(shí)間,減少了 IO 次數(shù)和無(wú)效的數(shù)據(jù)掃描,提升了數(shù)據(jù)讀取和計(jì)算效率。
再來(lái)看計(jì)算和存儲(chǔ)架構(gòu),首先無(wú)論是存儲(chǔ)還是計(jì)算,都是分布式架構(gòu)。日志數(shù)據(jù)的寫(xiě)入基于 LSM 模型,在寫(xiě)入節(jié)點(diǎn)上面,一部分熱數(shù)據(jù)在 memory 里面,另一部分則已經(jīng) Dump 下去,最終寫(xiě)到分布式存儲(chǔ)中,這部分是數(shù)據(jù)寫(xiě)入。而查詢(xún)分析時(shí)需要加載數(shù)據(jù),我們希望能高效利用 LSM 模型特性,盡可能地從 memory 中加載數(shù)據(jù),減少不必要的網(wǎng)絡(luò)和磁盤(pán) IO,因此在存儲(chǔ)和計(jì)算架構(gòu)上,我們進(jìn)行了數(shù)據(jù)本地性的設(shè)計(jì),將計(jì)算節(jié)點(diǎn)和存儲(chǔ)節(jié)點(diǎn)放在同一個(gè)機(jī)器上面,同時(shí)因?yàn)橛?jì)算節(jié)點(diǎn)和存儲(chǔ)節(jié)點(diǎn)是跨進(jìn)程的,所以涉及到數(shù)據(jù)的交互,這里是通過(guò) domain socket 進(jìn)行控制面的通信,通過(guò) share memory 完成數(shù)據(jù)交接。
通過(guò)數(shù)據(jù)本地性的設(shè)計(jì),我們利用了 LSM 里面本地的 mem cache,同時(shí)利用分布式存儲(chǔ)節(jié)點(diǎn)上面的 page cache,減少了不必要的磁盤(pán) IO;同時(shí)也避免了節(jié)點(diǎn)間跨網(wǎng)絡(luò)的 IO 開(kāi)銷(xiāo),最終有效地提升了 IO 效率。
有了前面這兩點(diǎn),要實(shí)現(xiàn)實(shí)時(shí)低延遲計(jì)算,仍然存在不少挑戰(zhàn)。這里引用計(jì)算機(jī)領(lǐng)域一個(gè)大佬的話(huà)“所有計(jì)算機(jī)領(lǐng)域的問(wèn)題都可以通過(guò)另外一層抽象來(lái)解決”。我們其實(shí)也是借鑒了這一思想,在整個(gè)系統(tǒng)里面實(shí)現(xiàn)了一個(gè)分層緩存。
在數(shù)據(jù)層面,利用了分布式存儲(chǔ)節(jié)點(diǎn)上面的 page cache,利用寫(xiě)入節(jié)點(diǎn)上面的 memory cache 這樣的一些緩存能力。
在索引層面,緩存了倒排數(shù)值、字典等等一些索引塊的信息,減少反復(fù)索引數(shù)據(jù)的加載以及解碼開(kāi)銷(xiāo)。
在分析引擎層面,對(duì)元數(shù)據(jù)進(jìn)行緩存,將索引字段信息、Shard 分片信息,還有數(shù)據(jù)分布等這些信息進(jìn)行緩存,來(lái)加速 SQL 語(yǔ)義的解析以及物理執(zhí)行計(jì)劃的生成過(guò)程。同時(shí),對(duì)于相同 SQL 的邏輯執(zhí)行計(jì)劃進(jìn)行了緩存,來(lái)減少分析引擎核心節(jié)點(diǎn) coordinator 上面的重復(fù) SQL 解析的開(kāi)銷(xiāo)。
在調(diào)度層面,對(duì)數(shù)據(jù)的分片以及任務(wù)執(zhí)行的調(diào)度歷史進(jìn)行緩存,這樣做的好處是可能有一些節(jié)點(diǎn)上面已經(jīng)加載過(guò)一部分的數(shù)據(jù),它已經(jīng)執(zhí)行過(guò)一些歷史任務(wù),對(duì)這些調(diào)度歷史進(jìn)行緩存之后,可以基于親和力的調(diào)度,下次再計(jì)算的時(shí)候,可以再調(diào)度到這個(gè)節(jié)點(diǎn)上,最大化的利用數(shù)據(jù)的本地性以及下層緩存的一些收益。
在計(jì)算緩存層面,實(shí)現(xiàn)了一個(gè) partial agg operator 的算子。它主要是緩存相同數(shù)據(jù)在相同算子上的部分聚合計(jì)算結(jié)果,來(lái)避免相同數(shù)據(jù)反復(fù)加載和計(jì)算的開(kāi)銷(xiāo)。
最終在結(jié)果緩存層面,會(huì)緩存完全相同的查詢(xún)的最終計(jì)算結(jié)果,來(lái)減少無(wú)效的查詢(xún)開(kāi)銷(xiāo)。基本上通過(guò)這三個(gè)層面,在查詢(xún)的實(shí)時(shí)性以及低延時(shí)上面,可以做到較好的表現(xiàn)。
第二個(gè)核心問(wèn)題就是超大數(shù)據(jù)規(guī)模的問(wèn)題。我們剛剛所講的存儲(chǔ)模型,由于用戶(hù)的日志數(shù)據(jù)越寫(xiě)越多,數(shù)據(jù)塊可能越來(lái)越多。按照我們前面數(shù)據(jù)本地性這樣的設(shè)計(jì),所有的計(jì)算要在這樣的一個(gè)存儲(chǔ)節(jié)點(diǎn)上面去走,隨著單 Shard 上數(shù)據(jù)規(guī)模越來(lái)越大,單節(jié)點(diǎn)的數(shù)據(jù)讀取和計(jì)算能力可能是不夠的。所以整體來(lái)說(shuō),我們會(huì)將 LSM 落到分布式存儲(chǔ)里面的一些 block 的數(shù)據(jù)塊,把它散列到更多的存儲(chǔ)節(jié)點(diǎn)上面,分派給上層更多的計(jì)算節(jié)點(diǎn),這樣整體再交給上面的計(jì)算匯聚層,去做相關(guān)的計(jì)算的匯聚。這樣一來(lái),在存儲(chǔ)層面我們的 IO 壓力可以得到水平散列,在計(jì)算層面,我們的計(jì)算并行度能夠得到大幅的提升,在計(jì)算節(jié)點(diǎn)上面的內(nèi)存、CPU 這些資源也能夠得到水平擴(kuò)展。這個(gè)是我們?cè)谡w架構(gòu)上面做的調(diào)整(即存儲(chǔ)計(jì)算分離)。
但是我們會(huì)面臨新的挑戰(zhàn)。由于剛剛所說(shuō)的數(shù)據(jù)本地性的設(shè)計(jì),就是為了避免網(wǎng)絡(luò)開(kāi)銷(xiāo)來(lái)高效地利用數(shù)據(jù)的本地的緩存,這種存算分離的模式,可能會(huì)丟失一部分?jǐn)?shù)據(jù)的本地性,可能會(huì)導(dǎo)致延時(shí)的增高。另外,雖然我們?nèi)プ隽怂降臄U(kuò)展,但是由于數(shù)據(jù)的一些熱點(diǎn)或者是一些傾斜,可能會(huì)造成一些局部的熱點(diǎn)的負(fù)載壓力。
針對(duì)數(shù)據(jù)本地性丟失問(wèn)題,我們的應(yīng)對(duì)方式是基于親和力的調(diào)度,再去調(diào)度到這個(gè)節(jié)點(diǎn)上,利用這個(gè)節(jié)點(diǎn)上的數(shù)據(jù)的本地性,盡可能減少數(shù)據(jù)加載以及延時(shí)的開(kāi)銷(xiāo)。另外一個(gè)就是去對(duì)負(fù)載進(jìn)行實(shí)時(shí)的感知,通過(guò)均衡調(diào)度的一些策略,盡量去減少系統(tǒng)的負(fù)載的一些熱點(diǎn)。所以整體來(lái)說(shuō),我們是在速度和規(guī)模之間進(jìn)行一個(gè)權(quán)衡。通過(guò)水平擴(kuò)展,我們可以實(shí)現(xiàn) IO、內(nèi)存以及 CPU 等資源的橫向擴(kuò)展能力。同時(shí)通過(guò)存算分離的架構(gòu),可以提升存算的并行度,解決超大數(shù)據(jù)規(guī)模的問(wèn)題。并通過(guò)親和力的調(diào)度,以及負(fù)載均衡來(lái)應(yīng)對(duì)新的挑戰(zhàn)。
第三個(gè)核心問(wèn)題,系統(tǒng)會(huì)面臨一些高并發(fā)的查詢(xún)壓力。整體來(lái)說(shuō),分析引擎的架構(gòu)是非常簡(jiǎn)單的,前面會(huì)有一個(gè) coordinator,也就是一個(gè)協(xié)調(diào)節(jié)點(diǎn)。具體工作的 worker 節(jié)點(diǎn),統(tǒng)一由 coordinator 節(jié)點(diǎn)來(lái)負(fù)責(zé)整體任務(wù)的調(diào)度。所以當(dāng)用戶(hù)的并發(fā)查詢(xún)請(qǐng)求越來(lái)越高的時(shí)候,coordinator 上面的負(fù)載就會(huì)非常大,因?yàn)樗纫薪忧懊嬗脩?hù)的查詢(xún)請(qǐng)求,同時(shí)還要負(fù)責(zé) SQL 的整體的解析任務(wù),同時(shí)還要負(fù)責(zé)整體的計(jì)算過(guò)程當(dāng)中的任務(wù)調(diào)度。我們?cè)趯?shí)際線上也進(jìn)行了采樣分析,發(fā)現(xiàn) SQL 解析部分,包括詞法分析、語(yǔ)法分析,還有 planner 生成以及優(yōu)化改寫(xiě)這些步驟,對(duì)于 CPU 的消耗開(kāi)銷(xiāo)是非常大的,尤其是 plan 生成和優(yōu)化改寫(xiě)這兩步。
另一方面,我們也分析了我們線上的一些業(yè)務(wù),發(fā)現(xiàn)很多業(yè)務(wù)來(lái)自于儀表盤(pán)、智能告警,還有 schedule SQL 這樣一些業(yè)務(wù)。這類(lèi)業(yè)務(wù)查詢(xún)是固定不變的,只變動(dòng)一些時(shí)間。所以這樣的查詢(xún)所對(duì)應(yīng)的邏輯執(zhí)行計(jì)劃是不變的,我們就在這個(gè)層面去做了查詢(xún) plan 這樣的一個(gè)緩存,通過(guò) plan 的 cache 來(lái)減少系統(tǒng)關(guān)鍵節(jié)點(diǎn)上面的關(guān)鍵負(fù)載的開(kāi)銷(xiāo)。最終的效果是緩存命中率能夠達(dá)到 75%,同時(shí)關(guān)鍵節(jié)點(diǎn)上 CPU 的消耗能夠降低 20% 到 30%,而且我們的 JVM 的 GC 壓力和次數(shù)也有明顯的降低。
另外一個(gè)高并發(fā)的問(wèn)題就是我們的 coordinator 節(jié)點(diǎn)上可能會(huì)存在這種網(wǎng)絡(luò)連接數(shù)爆炸式的增長(zhǎng)。因?yàn)?coordinator 在整個(gè)分析系統(tǒng)中,是核心協(xié)調(diào)節(jié)點(diǎn),它要和集群里面所有的 worker 節(jié)點(diǎn)進(jìn)行通信,任務(wù)上面進(jìn)行節(jié)點(diǎn)上面的調(diào)度交互。所以當(dāng)集群里面的節(jié)點(diǎn)規(guī)模越來(lái)越大,單個(gè) coordinator 節(jié)點(diǎn)網(wǎng)絡(luò)通信的量是非常大的。面臨的挑戰(zhàn)是單秒就可能達(dá)到 10 萬(wàn)以上的并發(fā)任務(wù)數(shù)。原來(lái)是 HTTP 短連接這種通信模式,單個(gè) coordinator 作為一個(gè)客戶(hù)端,要去和所有的 worker 節(jié)點(diǎn)進(jìn)行通信。我們的應(yīng)對(duì)方案就是復(fù)用信道,將 HTTP 短連接改造成 RPC 長(zhǎng)連。通過(guò)復(fù)用信道來(lái)減少反復(fù)建連的開(kāi)銷(xiāo)。同時(shí)可以有效控制連接的規(guī)模,在集群內(nèi)把連接數(shù)做到恒定可控。
第四個(gè)核心問(wèn)題是服務(wù)的高可用以及租戶(hù)之間的隔離,這也是我們作為云服務(wù)不得不解決的一個(gè)核心問(wèn)題。云上多租戶(hù)的一個(gè)核心挑戰(zhàn)在于如何在共享資源的前提下去做好租戶(hù)之間的隔離,做好服務(wù)的可用性。我們的思路跟 Linux 的多租戶(hù)分時(shí)復(fù)用的思路是相似的,分成若干的時(shí)間片去給用戶(hù)使用相關(guān)的資源。重點(diǎn)在于我們?cè)趺慈プ龈綦x,以及怎么保證系統(tǒng)的可用性,我們通過(guò)限流的方式來(lái)做自我的保護(hù),限制用戶(hù)的使用。首先我們實(shí)現(xiàn)了分布式的用戶(hù)查詢(xún)隊(duì)列,基于一致性哈??梢詫⒕唧w的用戶(hù)落到具體的 coordinator 節(jié)點(diǎn)上,在 coordinator 節(jié)點(diǎn)上來(lái)統(tǒng)一管控用戶(hù)的資源使用情況,控制用戶(hù)的并發(fā)查詢(xún)數(shù)。同時(shí)在執(zhí)行過(guò)程當(dāng)中,去監(jiān)控用戶(hù)的內(nèi)存以及查詢(xún)時(shí)間的情況來(lái)限定其使用。
在具體的執(zhí)行層面,我們會(huì)對(duì) task 的時(shí)間片進(jìn)行有效的限定,這里面包括計(jì)算層面的,還有查詢(xún)檢索層面的,以及 IO 層面的各種任務(wù)時(shí)間片。最后,在存儲(chǔ)層面,我們會(huì)對(duì)整體的數(shù)據(jù)掃描量進(jìn)行一個(gè)限定,避免一下打爆我們的網(wǎng)絡(luò)帶寬。整體來(lái)說(shuō),通過(guò)這樣的一個(gè)分層的限流措施,我們可以比較好地做到在共享資源情況下的租戶(hù)隔離,也做到一個(gè)比較好的系統(tǒng)的自我防護(hù),保證服務(wù)的高可用。
這里還帶來(lái)另外一個(gè)問(wèn)題,由于我們做了各種限定,可能用戶(hù)的數(shù)據(jù)在計(jì)算的過(guò)程當(dāng)中沒(méi)有加載完整,這就會(huì)導(dǎo)致查詢(xún)不精確。針對(duì)這種情況,我們的解決思路是并沒(méi)有直接去返回,查詢(xún)失敗了會(huì)把本次查詢(xún)的一個(gè)已經(jīng)計(jì)算出來(lái)的結(jié)果返回,并且會(huì)標(biāo)記這個(gè)結(jié)果是不精確的。同時(shí)由于我們分層緩存的設(shè)計(jì),通過(guò)讓用戶(hù)進(jìn)一步地去查詢(xún),可以漸進(jìn)式地去逼近一個(gè)精確的結(jié)果。整體來(lái)說(shuō),我們是通過(guò)分層的保護(hù)和限流,來(lái)實(shí)現(xiàn)租戶(hù)資源之間的隔離和服務(wù)的穩(wěn)定可用。同時(shí)我們要在速度、規(guī)模還有穩(wěn)定性上面去做一些權(quán)衡和取舍。
總結(jié)一下前面所介紹的實(shí)踐經(jīng)驗(yàn)。
首先,通過(guò)索引列存、數(shù)據(jù)本地性,以及分級(jí)的緩存,解決了第一個(gè)核心問(wèn)題——查詢(xún)的實(shí)時(shí)性以及低延時(shí)問(wèn)題;
第二,通過(guò)水平的擴(kuò)展、存算分離等架構(gòu)上的改造,解決了第二個(gè)核心問(wèn)題;
第三,通過(guò)一些關(guān)鍵節(jié)點(diǎn)上面的性能提升,以及網(wǎng)絡(luò)上的優(yōu)化,解決了系統(tǒng)高并發(fā)上的壓力。我們目前能夠支持云上的海量用戶(hù)的在線并發(fā)查詢(xún)。同時(shí)我們經(jīng)受住了多年雙 11 大促業(yè)務(wù)高峰并發(fā)峰值的考驗(yàn)。
最后,通過(guò)分層的限流以及調(diào)度隔離,實(shí)現(xiàn)了整體的服務(wù)的高可用以及多租戶(hù)的隔離,可以穩(wěn)定支撐阿里集團(tuán)數(shù)十個(gè) BU,數(shù)千條業(yè)務(wù)線的日志分析需求。