知乎 Flink 取代 Spark Streaming 的實(shí)戰(zhàn)之路
“數(shù)據(jù)智能” (Data Intelligence) 有一個(gè)必須且基礎(chǔ)的環(huán)節(jié),就是數(shù)據(jù)倉庫的建設(shè),同時(shí),數(shù)據(jù)倉庫也是公司數(shù)據(jù)發(fā)展到一定規(guī)模后必然會(huì)提供的一種基礎(chǔ)服務(wù)。從智能商業(yè)的角度來講,數(shù)據(jù)的結(jié)果代表了用戶的反饋,獲取結(jié)果的及時(shí)性就顯得尤為重要,快速的獲取數(shù)據(jù)反饋能夠幫助公司更快的做出決策,更好的進(jìn)行產(chǎn)品迭代,實(shí)時(shí)數(shù)倉在這一過程中起到了不可替代的作用。
本文主要講述知乎的實(shí)時(shí)數(shù)倉實(shí)踐以及架構(gòu)的演進(jìn),這包括以下幾個(gè)方面
- 實(shí)時(shí)數(shù)倉 1.0 版本,主題: ETL 邏輯實(shí)時(shí)化,技術(shù)方案: Spark Streaming。
- 實(shí)時(shí)數(shù)倉 2.0 版本,主題:數(shù)據(jù)分層,指標(biāo)計(jì)算實(shí)時(shí)化,技術(shù)方案: Flink Streaming。
- 實(shí)時(shí)數(shù)倉未來展望:Streaming SQL 平臺(tái)化,元信息管理系統(tǒng)化,結(jié)果驗(yàn)收自動(dòng)化。
實(shí)時(shí)數(shù)倉 1.0 版本
1.0 版本的實(shí)時(shí)數(shù)倉主要是對(duì)流量數(shù)據(jù)做實(shí)時(shí) ETL,并不計(jì)算實(shí)時(shí)指標(biāo),也未建立起實(shí)時(shí)數(shù)倉體系,實(shí)時(shí)場(chǎng)景比較單一,對(duì)實(shí)時(shí)數(shù)據(jù)流的處理主要是為了提升數(shù)據(jù)平臺(tái)的服務(wù)能力。實(shí)時(shí)數(shù)據(jù)的處理向上依賴數(shù)據(jù)的收集,向下關(guān)系到數(shù)據(jù)的查詢和可視化,下圖是實(shí)時(shí)數(shù)倉 1.0 版本的整體數(shù)據(jù)架構(gòu)圖。
如果想及時(shí)了解 Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
第一部分是數(shù)據(jù)采集,由三端 SDK 采集數(shù)據(jù)并通過 Log Collector Server 發(fā)送到 Kafka。第二部分是數(shù)據(jù) ETL,主要完成對(duì)原始數(shù)據(jù)的清洗和加工并分實(shí)時(shí)和離線導(dǎo)入 Druid。第三部分是數(shù)據(jù)可視化,由 Druid 負(fù)責(zé)計(jì)算指標(biāo)并通過 Web Server 配合前端完成數(shù)據(jù)可視化。
其中第一、三部分的相關(guān)內(nèi)容請(qǐng)分別參考:知乎客戶端埋點(diǎn)流程、模型和平臺(tái)技術(shù),Druid 與知乎數(shù)據(jù)分析平臺(tái),此處我們?cè)敿?xì)介紹第二部分。由于實(shí)時(shí)數(shù)據(jù)流的穩(wěn)定性不如離線數(shù)據(jù)流,當(dāng)實(shí)時(shí)流出現(xiàn)問題后需要離線數(shù)據(jù)重刷歷史數(shù)據(jù),因此實(shí)時(shí)處理部分我們采用了 lambda 架構(gòu)。
Lambda 架構(gòu)有高容錯(cuò)、低延時(shí)和可擴(kuò)展的特點(diǎn),為了實(shí)現(xiàn)這一設(shè)計(jì),我們將 ETL 工作分為兩部分:Streaming ETL 和 Batch ETL。
Streaming ETL
這一部分我會(huì)介紹實(shí)時(shí)計(jì)算框架的選擇、數(shù)據(jù)正確性的保證、以及 Streaming 中一些通用的 ETL 邏輯,最后還會(huì)介紹 Spark Streaming 在實(shí)時(shí) ETL 中的穩(wěn)定性實(shí)踐。
計(jì)算框架選擇
在 2016 年年初,業(yè)界用的比較多的實(shí)時(shí)計(jì)算框架有 Storm 和 Spark Streaming。Storm 是純流式框架,Spark Streaming 用 Micro Batch 模擬流式計(jì)算,前者比后者更實(shí)時(shí),后者比前者吞吐量大且生態(tài)系統(tǒng)更完善,考慮到知乎的日志量以及初期對(duì)實(shí)時(shí)性的要求,我們選擇了 Spark Streaming 作為實(shí)時(shí)數(shù)據(jù)的處理框架。
數(shù)據(jù)正確性保證
Spark Streaming 的端到端 Exactly-once 需要下游支持冪等、上游支持流量重放,這里我們?cè)?Spark Streaming 這一層做到了 At-least-once,正常情況下數(shù)據(jù)不重不少,但在程序重啟時(shí)可能會(huì)重發(fā)部分?jǐn)?shù)據(jù),為了實(shí)現(xiàn)全局的 Exactly-once,我們?cè)谙掠巫隽巳ブ剡壿?,關(guān)于如何去重后面我會(huì)講到。
通用 ETL 邏輯
ETL 邏輯和埋點(diǎn)的數(shù)據(jù)結(jié)構(gòu)息息相關(guān),我們所有的埋點(diǎn)共用同一套 Proto Buffer Schema,大致如下所示。
message LogEntry {
optional BaseInfo base = 1;
optional DetailInfo detail = 2;
optional ExtraInfo extra = 3;
}
BaseInfo:日志中最基本的信息,包括用戶信息、客戶端信息、時(shí)間信息、網(wǎng)絡(luò)信息等日志發(fā)送時(shí)的必要信息。DetailInfo:日志中的視圖信息,包括當(dāng)前視圖、上一個(gè)視圖等用于定位用戶所在位置的信息。ExtraInfo:日志中與特定業(yè)務(wù)相關(guān)的額外信息。
針對(duì)上述三種信息我們將 ETL 邏輯分為通用和非通用兩類,通用邏輯和各個(gè)業(yè)務(wù)相關(guān),主要應(yīng)用于 Base 和 Detail 信息,非通用邏輯則是由需求方針對(duì)某次需求提出,主要應(yīng)用于 Extra 信息。這里我們列舉 3 個(gè)通用邏輯進(jìn)行介紹,這包括:動(dòng)態(tài)配置 Streaming、UTM 參數(shù)解析、新老用戶識(shí)別。
動(dòng)態(tài)配置 Streaming
由于 Streaming 任務(wù)需要 7 * 24 小時(shí)運(yùn)行,但有些業(yè)務(wù)邏輯,比如:存在一個(gè)元數(shù)據(jù)信息中心,當(dāng)這個(gè)元數(shù)據(jù)發(fā)生變化時(shí),需要將這種變化映射到數(shù)據(jù)流上方便下游使用數(shù)據(jù),這種變化可能需要停止 Streaming 任務(wù)以更新業(yè)務(wù)邏輯,但元數(shù)據(jù)變化的頻率非常高,且在元數(shù)據(jù)變化后如何及時(shí)通知程序的維護(hù)者也很難。動(dòng)態(tài)配置 Streaming 為我們提供了一個(gè)解決方案,該方案如下圖所示。
如果想及時(shí)了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
我們可以把經(jīng)常變化的元數(shù)據(jù)作為 Streaming Broadcast 變量,該變量扮演的角色類似于只讀緩存,同時(shí)針對(duì)該變量可設(shè)置 TTL,緩存過期后 Executor 節(jié)點(diǎn)會(huì)重新向 Driver 請(qǐng)求最新的變量。通過這種機(jī)制可以非常自然的將元數(shù)據(jù)的變化映射到數(shù)據(jù)流上,無需重啟任務(wù)也無需通知程序的維護(hù)者。
UTM 參數(shù)解析
UTM 的全稱是 Urchin Tracking Module,是用于追蹤網(wǎng)站流量來源的利器,關(guān)于 UTM 背景知識(shí)介紹可以參考網(wǎng)上其他內(nèi)容,這里不再贅述。下圖是我們解析 UTM 信息的完整邏輯。
如果想及時(shí)了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
流量數(shù)據(jù)通過 UTM 參數(shù)解析后,我們可以很容易滿足以下需求
- 查看各搜索引擎導(dǎo)流情況以及這些流量來自于哪些熱門搜索詞。
- 市場(chǎng)部某次活動(dòng)帶來的流量大小,如:頁面瀏覽數(shù)、獨(dú)立訪問用戶數(shù)等。
- 從站內(nèi)分享出去的鏈接在各分享平臺(tái)(如:微信、微博)被瀏覽的情況。
新老用戶識(shí)別
對(duì)于互聯(lián)網(wǎng)公司而言,增長(zhǎng)是一個(gè)永恒的話題,實(shí)時(shí)拿到新增用戶量,對(duì)于增長(zhǎng)運(yùn)營十分重要。例如:一次投放 n 個(gè)渠道,如果能拿到每個(gè)渠道的實(shí)時(shí)新增用戶數(shù),就可以快速判斷出那些渠道更有價(jià)值。我們用下圖來表達(dá) Streaming ETL 中是如何識(shí)別新老用戶的。
如果想及時(shí)了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
判斷一個(gè)用戶是不是新用戶,最簡(jiǎn)單的辦法就是維護(hù)一個(gè)歷史用戶池,對(duì)每條日志判斷該用戶是否存在于用戶池中。 由于日志量巨大,為了不影響 Streaming 任務(wù)的處理速度,我們?cè)O(shè)計(jì)了兩層緩存:Thread Local Cache 和 Redis Cache,同時(shí)用 HBase 做持久化存儲(chǔ)以保存歷史用戶。訪問速度:本地內(nèi)存 > 遠(yuǎn)端內(nèi)存 > 遠(yuǎn)端磁盤,對(duì)于我們這個(gè)任務(wù)來說,只有 1% 左右的請(qǐng)求會(huì)打到 HBase,日志高峰期 26w/s,完全不會(huì)影響任務(wù)的實(shí)時(shí)性。當(dāng)然本地緩存 LruCache 的容量大小和 Redis 的性能也是影響實(shí)時(shí)性的兩個(gè)因素。
Streaming ETL 除了上述幾個(gè)通用場(chǎng)景外,還有一些其他邏輯,這些邏輯的存在有的是為了滿足下游更方便的使用數(shù)據(jù)的需求,有的是對(duì)某些錯(cuò)誤埋點(diǎn)的修復(fù),總之 Streaming ETL 在整個(gè)實(shí)時(shí)數(shù)倉中處于指標(biāo)計(jì)算的上游,有著不可替代的作用。
Spark Streaming 在實(shí)時(shí)數(shù)倉 1.0 中的穩(wěn)定性實(shí)踐
Spark Streaming 消費(fèi) Kafka 數(shù)據(jù)推薦使用 Direct 模式。我們?cè)缙谑褂玫氖?High Level 或者叫 Receiver 模式并使用了 checkpoint 功能,這種方式在更新程序邏輯時(shí)需要?jiǎng)h除 checkpoint 否則新的程序邏輯就無法生效。另外,由于使用了 checkpoint 功能,Streaming 任務(wù)會(huì)保持和 Hdfs 通信,可能會(huì)因?yàn)?NameNode 的抖動(dòng)導(dǎo)致 Streaming 任務(wù)抖動(dòng)。因此,推薦使用 Direct 模式,關(guān)于這種模式和 Receiver 模式的詳細(xì)對(duì)比,可以參考官方文檔。
保證 Spark Streaming 任務(wù)的資源穩(wěn)定。以 Yarn 為例,運(yùn)行 Streaming 任務(wù)的隊(duì)列能夠分配到的最小資源小于了任務(wù)所需要的資源,任務(wù)會(huì)出現(xiàn)頻繁丟失 Executor 的情況,這會(huì)導(dǎo)致 Streaming 任務(wù)變慢,因?yàn)閬G失的 Executor 所對(duì)應(yīng)的數(shù)據(jù)需要重新計(jì)算,同時(shí)還需要重新分配 Executor。
Spark Streaming 消費(fèi) Kafka 時(shí)需要做數(shù)據(jù)流限速。默認(rèn)情況下 Spark Streaming 以盡可能大的速度讀取消息隊(duì)列,當(dāng) Streaming 任務(wù)掛了很久之后再次被啟動(dòng)時(shí),由于拉取的數(shù)據(jù)量過大可能會(huì)導(dǎo)致上游的 Kafka 集群 IO 被打爆進(jìn)而出現(xiàn) Kafka 集群長(zhǎng)時(shí)間阻塞。可以使用 Streaming Conf 參數(shù)做限速,限定每秒拉取的最大速度。
Spark Streaming 任務(wù)失敗后需要自動(dòng)拉起。長(zhǎng)時(shí)間運(yùn)行發(fā)現(xiàn),Spark Streaming 并不能 7 * 24h 穩(wěn)定運(yùn)行,我們用 Supervisor 管理 Driver 進(jìn)程,當(dāng)任務(wù)掛掉后 Driver 進(jìn)程將不復(fù)存在,此時(shí) Supervisor 將重新拉起 Streaming 任務(wù)。
Batch ETL
接下來要介紹的是 Lambda 架構(gòu)的第二個(gè)部分:Batch ETL,此部分我們需要解決數(shù)據(jù)落地、離線 ETL、數(shù)據(jù)批量導(dǎo)入 Druid 等問題。針對(duì)數(shù)據(jù)落地我們自研了 map reduce 任務(wù) Batch Loader,針對(duì)數(shù)據(jù)修復(fù)我們自研了離線任務(wù) Repair ETL,離線修復(fù)邏輯和實(shí)時(shí)邏輯共用一套 ETL Lib,針對(duì)批量導(dǎo)入 ProtoParquet 數(shù)據(jù)到 Druid,我們擴(kuò)展了 Druid 的導(dǎo)入插件。
Repair ETL
數(shù)據(jù)架構(gòu)圖中有兩個(gè) Kafka,第一個(gè) Kafka 存放的是原始日志,第二個(gè) Kafka 存放的是實(shí)時(shí) ETL 后的日志,我們將兩個(gè) Kafka 的數(shù)據(jù)全部落地,這樣做的目的是為了保證數(shù)據(jù)鏈路的穩(wěn)定性。因?yàn)閷?shí)時(shí) ETL 中有大量的業(yè)務(wù)邏輯,未知需求的邏輯也許會(huì)給整個(gè)流量數(shù)據(jù)帶來安全隱患,而上游的 Log Collect Server 不存在任何業(yè)務(wù)邏輯只負(fù)責(zé)收發(fā)日志,相比之下第一個(gè) Kafka 的數(shù)據(jù)要安全和穩(wěn)定的多。Repair ETL 并不是經(jīng)常啟用,只有當(dāng)實(shí)時(shí) ETL 丟失數(shù)據(jù)或者出現(xiàn)邏輯錯(cuò)誤時(shí),才會(huì)啟用該程序用于修復(fù)日志。
Batch Load 2 HDFS
前面已經(jīng)介紹過,我們所有的埋點(diǎn)共用同一套 Proto Buffer Schema,數(shù)據(jù)傳輸格式全部為二進(jìn)制。我們自研了落地 Kafka PB 數(shù)據(jù)到 Hdfs 的 Map Reduce 任務(wù) BatchLoader,該任務(wù)除了落地?cái)?shù)據(jù)外,還負(fù)責(zé)對(duì)數(shù)據(jù)去重。在 Streaming ETL 階段我們做到了 At-least-once,通過此處的 BatchLoader 去重我們實(shí)現(xiàn)了全局 Exactly-once。BatchLoader 除了支持落地?cái)?shù)據(jù)、對(duì)數(shù)據(jù)去重外,還支持多目錄分區(qū)(p_date/p_hour/p_plaform/p_logtype)、數(shù)據(jù)回放、自依賴管理(早期沒有統(tǒng)一的調(diào)度器)等。截止到目前,BatchLoader 落地了 40+ 的 Kakfa Topic 數(shù)據(jù)。
Batch Load 2 Druid
采用 Tranquility 實(shí)時(shí)導(dǎo)入 Druid,這種方式強(qiáng)制需要一個(gè)時(shí)間窗口,當(dāng)上游數(shù)據(jù)延遲超過窗值后會(huì)丟棄窗口之外的數(shù)據(jù),這種情況會(huì)導(dǎo)致實(shí)時(shí)報(bào)表出現(xiàn)指標(biāo)錯(cuò)誤。為了修復(fù)這種錯(cuò)誤,我們通過 Druid 發(fā)起一個(gè)離線 Map Reduce 任務(wù)定期重導(dǎo)上一個(gè)時(shí)間段的數(shù)據(jù)。通過這里的 Batch 導(dǎo)入和前面的實(shí)時(shí)導(dǎo)入,實(shí)現(xiàn)了實(shí)時(shí)數(shù)倉的 Lambda 架構(gòu)。
實(shí)時(shí)數(shù)倉 1.0 的幾個(gè)不足之處
到目前為止我們已經(jīng)介紹完 Lambda 架構(gòu)實(shí)時(shí)數(shù)倉的幾個(gè)模塊,1.0 版本的實(shí)時(shí)數(shù)倉有以下幾個(gè)不足
- 所有的流量數(shù)據(jù)存放在同一個(gè) Kafka Topic 中,如果下游每個(gè)業(yè)務(wù)線都要消費(fèi),這會(huì)導(dǎo)致全量數(shù)據(jù)被消費(fèi)多次,Kafka 出流量太高無法滿足該需求。
- 所有的指標(biāo)計(jì)算全部由 Druid 承擔(dān),Druid 同時(shí)兼顧實(shí)時(shí)數(shù)據(jù)源和離線數(shù)據(jù)源的查詢,隨著數(shù)據(jù)量的暴漲 Druid 穩(wěn)定性急劇下降,這導(dǎo)致各個(gè)業(yè)務(wù)的核心報(bào)表不能穩(wěn)定產(chǎn)出。
- 由于每個(gè)業(yè)務(wù)使用同一個(gè)流量數(shù)據(jù)源配置報(bào)表,導(dǎo)致查詢效率低下,同時(shí)無法對(duì)業(yè)務(wù)做數(shù)據(jù)隔離和成本計(jì)算。
實(shí)時(shí)數(shù)倉 2.0 版本
隨著數(shù)據(jù)量的暴漲,Druid 中的流量數(shù)據(jù)源經(jīng)常查詢超時(shí)同時(shí)各業(yè)務(wù)消費(fèi)實(shí)時(shí)數(shù)據(jù)的需求也開始增多,如果繼續(xù)沿用實(shí)時(shí)數(shù)倉 1.0 架構(gòu),需要付出大量的額外成本。于是,在實(shí)時(shí)數(shù)倉 1.0 的基礎(chǔ)上,我們建立起了實(shí)時(shí)數(shù)倉 2.0,梳理出了新的架構(gòu)設(shè)計(jì)并開始著手建立實(shí)時(shí)數(shù)倉體系,新的架構(gòu)如下圖所示。
如果想及時(shí)了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
原始層
實(shí)時(shí)數(shù)倉 1.0 我們只對(duì)流量數(shù)據(jù)做 ETL 處理,在 2.0 版本中我們加入了對(duì)業(yè)務(wù)庫的變更日志 Binlog 的處理,Binlog 日志在原始層為庫級(jí)別或者 Mysql 實(shí)例級(jí)別,即:一個(gè)庫或者實(shí)例的變更日志存放在同一個(gè) Kafka Topic 中。同時(shí)隨著公司業(yè)務(wù)的發(fā)展不斷有新 App 產(chǎn)生,在原始層不僅采集「知乎」日志,像知乎極速版以及內(nèi)部孵化項(xiàng)目的埋點(diǎn)數(shù)據(jù)也需要采集,不同 App 的埋點(diǎn)數(shù)據(jù)仍然使用同一套 PB Schema。
明細(xì)層
明細(xì)層是我們的 ETL 層,這一層數(shù)據(jù)是由原始層經(jīng)過 Streaming ETL 后得到。其中對(duì) Binlog 日志的處理主要是完成庫或者實(shí)例日志到表日志的拆分,對(duì)流量日志主要是做一些通用 ETL 處理,由于我們使用的是同一套 PB 結(jié)構(gòu),對(duì)不同 App 數(shù)據(jù)處理的邏輯代碼可以完全復(fù)用,這大大降低了我們的開發(fā)成本。
匯總層之明細(xì)匯總
明細(xì)匯總層是由明細(xì)層通過 ETL 得到,主要以寬表形式存在。業(yè)務(wù)明細(xì)匯總是由業(yè)務(wù)事實(shí)明細(xì)表和維度表 Join 得到,流量明細(xì)匯總是由流量日志按業(yè)務(wù)線拆分和流量維度 Join 得到。流量按業(yè)務(wù)拆分后可以滿足各業(yè)務(wù)實(shí)時(shí)消費(fèi)的需求,我們?cè)诹髁坎鸱诌@一塊做到了自動(dòng)化,下圖演示了流量數(shù)據(jù)自動(dòng)切分的過程。
如果想及時(shí)了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
Streaming Proxy 是流量分發(fā)模塊,它消費(fèi)上游 ETL 后的全量數(shù)據(jù)并定期讀取埋點(diǎn)元信息,通過將流量數(shù)據(jù)與元信息數(shù)據(jù)進(jìn)行「Join」完成按業(yè)務(wù)進(jìn)行流量拆分的邏輯,同時(shí)也會(huì)對(duì)切分后的流量按業(yè)務(wù)做 ETL 處理。 只要埋點(diǎn)元信息中新增一個(gè)埋點(diǎn),那么這個(gè)埋點(diǎn)對(duì)應(yīng)的數(shù)據(jù)就會(huì)自動(dòng)切分到該業(yè)務(wù)的 Kafka 中,最終業(yè)務(wù) Kafka 中的數(shù)據(jù)是獨(dú)屬于當(dāng)前業(yè)務(wù)的且已經(jīng)被通用 ETL 和業(yè)務(wù) ETL 處理過,這大大降低了各個(gè)業(yè)務(wù)使用數(shù)據(jù)的成本。
匯總層之指標(biāo)匯總
指標(biāo)匯總層是由明細(xì)層或者明細(xì)匯總層通過聚合計(jì)算得到,這一層產(chǎn)出了絕大部分的實(shí)時(shí)數(shù)倉指標(biāo),這也是與實(shí)時(shí)數(shù)倉 1.0 最大的區(qū)別。知乎是一個(gè)生產(chǎn)內(nèi)容的平臺(tái),對(duì)業(yè)務(wù)指標(biāo)的匯總我們可以從內(nèi)容角度和用戶角度進(jìn)行匯總,從內(nèi)容角度我們可以實(shí)時(shí)統(tǒng)計(jì)內(nèi)容(內(nèi)容可以是答案、問題、文章、視頻、想法)的被點(diǎn)贊數(shù)、被關(guān)注數(shù)、被收藏?cái)?shù)等指標(biāo),從用戶角度我可以實(shí)時(shí)統(tǒng)計(jì)用戶的粉絲數(shù)、回答數(shù)、提問數(shù)等指標(biāo)。對(duì)流量指標(biāo)的匯總我們分為各業(yè)務(wù)指標(biāo)匯總和全局指標(biāo)匯總。對(duì)各業(yè)務(wù)指標(biāo)匯總,我們可以實(shí)時(shí)統(tǒng)計(jì)首頁、搜索、視頻、想法等業(yè)務(wù)的卡片曝光數(shù)、卡片點(diǎn)擊數(shù)、CTR 等,對(duì)全局指標(biāo)匯總我們主要以實(shí)時(shí)會(huì)話為主,實(shí)時(shí)統(tǒng)計(jì)一個(gè)會(huì)話內(nèi)的 PV 數(shù)、卡片曝光數(shù)、點(diǎn)擊數(shù)、瀏覽深度、會(huì)話時(shí)長(zhǎng)等指標(biāo)。
指標(biāo)匯總層的存儲(chǔ)選型
不同于明細(xì)層和明細(xì)匯總層,指標(biāo)匯總層需要將實(shí)時(shí)計(jì)算好的指標(biāo)存儲(chǔ)起來以供應(yīng)用層使用。我們根據(jù)不同的場(chǎng)景選用了 HBase 和 Redis 作為實(shí)時(shí)指標(biāo)的存儲(chǔ)引擎。Redis 的場(chǎng)景主要是滿足帶 Update 操作且 OPS 較高的需求,例如:實(shí)時(shí)統(tǒng)計(jì)全站所有內(nèi)容(問題、答案、文章等)的累計(jì) PV 數(shù),由于瀏覽內(nèi)容產(chǎn)生大量的 PV 日志,可能高達(dá)幾萬或者幾十萬每秒,需要對(duì)每一條內(nèi)容的 PV 進(jìn)行實(shí)時(shí)累加,這種場(chǎng)景下選用 Redis 更為合適。HBase 的場(chǎng)景主要是滿足高頻 Append 操作、低頻隨機(jī)讀取且指標(biāo)列較多的需求,例如:每分鐘統(tǒng)計(jì)一次所有內(nèi)容的被點(diǎn)贊數(shù)、被關(guān)注數(shù)、被收藏?cái)?shù)等指標(biāo),將每分鐘聚合后的結(jié)果行 Append 到 HBase 并不會(huì)帶來性能和存儲(chǔ)量的問題,但這種情況下 Redis 在存儲(chǔ)量上可能會(huì)出現(xiàn)瓶頸。
指標(biāo)計(jì)算打通指標(biāo)系統(tǒng)和可視化系統(tǒng)
指標(biāo)口徑管理依賴指標(biāo)系統(tǒng),指標(biāo)可視化依賴可視化系統(tǒng),我們通過下圖的需求開發(fā)過程來講解如何將三者聯(lián)系起來。
如果想及時(shí)了解Spark、Hadoop或者Hbase相關(guān)的文章,歡迎關(guān)注微信公共帳號(hào):iteblog_hadoop
1.需求方整理好需求文檔后向數(shù)倉工程師提出需求并約會(huì)議評(píng)審需求,需求文檔中必須包含指標(biāo)的計(jì)算口徑和指標(biāo)對(duì)應(yīng)的維度。
2.數(shù)倉工程師根據(jù)需求文檔對(duì)需求進(jìn)行評(píng)審,評(píng)審不通過則返回需求方進(jìn)一步整理需求并重新提需。
3.在需求評(píng)審?fù)ㄟ^后,數(shù)倉工程師開始排期開發(fā)
- 首先在可視化系統(tǒng)中創(chuàng)建一個(gè)數(shù)據(jù)源,這個(gè)數(shù)據(jù)源是后期配置實(shí)時(shí)報(bào)表的數(shù)據(jù)源,創(chuàng)建數(shù)據(jù)源也即在 HBase 中創(chuàng)建一張 HBase 表。
- 針對(duì)該數(shù)據(jù)源創(chuàng)建指標(biāo)列,創(chuàng)建指標(biāo)列也即在 HBase 列族中創(chuàng)建列,創(chuàng)建指標(biāo)列的同時(shí)會(huì)將該指標(biāo)信息錄入指標(biāo)管理系統(tǒng)。
- 針對(duì)該數(shù)據(jù)源綁定維表,這個(gè)維表是后期配置多維報(bào)表時(shí)選用維度值要用的,如果要綁定的維表已經(jīng)存在,則直接綁定,否則需要導(dǎo)入維表。
- 一個(gè)完整的數(shù)據(jù)源創(chuàng)建后,數(shù)倉工程師才能開發(fā)實(shí)時(shí)應(yīng)用程序,通過應(yīng)用程序?qū)⒍嗑S指標(biāo)實(shí)時(shí)寫入已創(chuàng)建的數(shù)據(jù)源中。
4.需求方根據(jù)已創(chuàng)建的數(shù)據(jù)源直接配置實(shí)時(shí)報(bào)表。
應(yīng)用層
應(yīng)用層主要是使用匯總層數(shù)據(jù)以滿足業(yè)務(wù)需求。應(yīng)用層主要分三塊:
1.通過直接讀取指標(biāo)匯總數(shù)據(jù)做實(shí)時(shí)可視化,滿足固化的實(shí)時(shí)報(bào)表需求,這部分由實(shí)時(shí)大盤服務(wù)承擔(dān);
2. 推薦算法等業(yè)務(wù)直接消費(fèi)明細(xì)匯總數(shù)據(jù)做實(shí)時(shí)推薦;
3. 通過 Tranquility 程序?qū)崟r(shí)攝入明細(xì)匯總數(shù)據(jù)到 Druid,滿足實(shí)時(shí)多維即席分析需求。
實(shí)時(shí)數(shù)倉 2.0 中的技術(shù)實(shí)現(xiàn)
相比實(shí)時(shí)數(shù)倉 1.0 以 Spark Streaming 作為主要實(shí)現(xiàn)技術(shù),在實(shí)時(shí)數(shù)倉 2.0 中,我們將 Flink 作為指標(biāo)匯總層的主要計(jì)算框架。 Flink 相比 Spark Streaming 有更明顯的優(yōu)勢(shì),主要體現(xiàn)在:低延遲、Exactly-once 語義支持、Streaming SQL 支持、狀態(tài)管理、豐富的時(shí)間類型和窗口計(jì)算、CEP 支持等。
我們?cè)趯?shí)時(shí)數(shù)倉 2.0 中主要以 Flink 的 Streaming SQL 作為實(shí)現(xiàn)方案。使用 Streaming SQL 有以下優(yōu)點(diǎn):易于平臺(tái)化、開發(fā)效率高、維度成本低等。目前 Streaming SQL 使用起來也有一些缺陷:1. 語法和 Hive SQL 有一定區(qū)別,初使用時(shí)需要適應(yīng);2.UDF 不如 Hive 豐富,寫 UDF 的頻率高于 Hive。
實(shí)時(shí)數(shù)倉 2.0 取得的進(jìn)展
- 在明細(xì)匯總層通過流量切分滿足了各個(gè)業(yè)務(wù)實(shí)時(shí)消費(fèi)日志的需求。目前完成流量切分的業(yè)務(wù)達(dá)到 14+,由于各業(yè)務(wù)消費(fèi)的是切分后的流量,Kafka 出流量下降了一個(gè)數(shù)量級(jí)。
- 各業(yè)務(wù)核心實(shí)時(shí)報(bào)表可以穩(wěn)定產(chǎn)出。由于核心報(bào)表的計(jì)算直接由數(shù)倉負(fù)責(zé),可視化系統(tǒng)直接讀取實(shí)時(shí)結(jié)果,保證了實(shí)時(shí)報(bào)表的穩(wěn)定性,目前多個(gè)業(yè)務(wù)擁有實(shí)時(shí)大盤,實(shí)時(shí)報(bào)表達(dá) 40+。
- 提升了即席查詢的穩(wěn)定性。核心報(bào)表的指標(biāo)計(jì)算轉(zhuǎn)移到數(shù)倉,Druid 只負(fù)責(zé)即席查詢,多維分析類的需求得到了滿足。
- 成本計(jì)算需求得到了解決。由于各業(yè)務(wù)擁有了獨(dú)立的數(shù)據(jù)源且各核心大盤由不同的實(shí)時(shí)程序負(fù)責(zé),可以方便的統(tǒng)計(jì)各業(yè)務(wù)使用的存儲(chǔ)資源和計(jì)算資源
實(shí)時(shí)數(shù)倉未來展望
從實(shí)時(shí)數(shù)倉 1.0 到 2.0,不管是數(shù)據(jù)架構(gòu)還是技術(shù)方案,我們?cè)谏疃群蛷V度上都有了更多的積累。隨著公司業(yè)務(wù)的快速發(fā)展以及新技術(shù)的誕生,實(shí)時(shí)數(shù)倉也會(huì)不斷的迭代優(yōu)化。短期可預(yù)見的我們會(huì)從以下方面進(jìn)一步提升實(shí)時(shí)數(shù)倉的服務(wù)能力。
- Streaming SQL 平臺(tái)化。目前 Streaming SQL 任務(wù)是以代碼開發(fā) maven 打包的方式提交任務(wù),開發(fā)成本高,后期隨著 Streaming SQL 平臺(tái)的上線,實(shí)時(shí)數(shù)倉的開發(fā)方式也會(huì)由 Jar 包轉(zhuǎn)變?yōu)?SQL 文件。
- 實(shí)時(shí)數(shù)據(jù)元信息管理系統(tǒng)化。對(duì)數(shù)倉元信息的管理可以大幅度降低使用數(shù)據(jù)的成本,離線數(shù)倉的元信息管理已經(jīng)基本完善,實(shí)時(shí)數(shù)倉的元信息管理才剛剛開始。
- 實(shí)時(shí)數(shù)倉結(jié)果驗(yàn)收自動(dòng)化。對(duì)實(shí)時(shí)結(jié)果的驗(yàn)收只能借助與離線數(shù)據(jù)指標(biāo)對(duì)比的方式,以 Hive 和 Kafka 數(shù)據(jù)源為例,分別執(zhí)行 Hive SQL 和 Flink SQL,統(tǒng)計(jì)結(jié)果并對(duì)比是否一致實(shí)現(xiàn)實(shí)時(shí)結(jié)果驗(yàn)收的自動(dòng)化。