天天看點

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

當業務發展到一定規模,實時資料倉庫是一個必要的基礎服務。從資料驅動方面考慮,多元實時資料分析系統的重要性也不言而喻。但是當資料量巨大的情況下,拿騰訊看點來說,一天上報的資料量達到萬億級的規模,要實作極低延遲的實時計算和亞秒級的多元實時查詢是有技術挑戰的。

本文将介紹資訊流場景下,騰訊看點的實時資料倉庫和多元實時資料分析系統的技術架構。

1、可解決的痛點

可以先看一下,多元實時資料分析系統可以解決哪些痛點。比如:

  • 推薦同學 10 分鐘前上了一個推薦政策,想知道在不同人群的推薦效果怎麼樣?
  • 營運同學想知道,在廣東省的使用者中,最火的廣東地域内容是哪些,友善做地域 Push。
  • 稽核同學想知道,過去 5 分鐘,遊戲類被舉報最多的内容和賬号是哪些?
  • 老闆可能想了解,過去 10 分鐘有多少使用者在看點消費了内容,對消費人群有一個宏觀了解。

2、調研

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

在進行開發之前,我們做了這些調研。

  1. 離線資料分析平台能否滿足這些需求,結論是不能滿足。離線資料分析平台不行的原因如下。
  • C 側資料上報過來,需要經過 Spark 的多層離線計算,最終結果出庫到 MySQL 或者 ES 提供給離線分析平台查詢。這個過程的延時最少 3-6 個小時,目前比較常見的都是提供隔天的查詢,是以很多實時性要求高的業務場景都是不能滿足的。
  • 另一個問題是,騰訊看點的資料量太大,帶來的不穩定性也比較大,經常會有預料不到的延遲。是以,離線分析平台是無法滿足很多需求的。
  1. 實時資料分析平台的話,事業群内部提供了準實時資料查詢的功能,底層技術用的是 Kudu+Impala,Impala 雖然是 MPP 架構的大資料計算引擎,并且通路以列式存儲資料的 Kudu。但是對于實時資料分析場景來說,查詢響應的速度和資料的延遲都還是比較高,查詢一次實時 DAU,傳回結果耗時至少幾分鐘,無法提供良好的互動式使用者體驗。是以(Kudu+Impala)這種通用大資料處理架構的速度優勢更多的是相比(Spark+Hdfs)這種離線分析架構來說的,對于我們這個實時性要求更高的場景,是無法滿足的。

3、項目背景

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

經過剛才的介紹,再來看下我們這個項目的背景。

作者發文的内容被内容中心引入,經過内容稽核鍊路,啟用或者下架。啟用的内容給到推薦系統和營運系統,然後推薦系統和營運系統将内容進行 C 側分發。内容分發給 C 側使用者之後,使用者會産生各種行為,曝光、點選、舉報等,通過埋點上報實時接入到消息隊列中。

接下來我們做了兩部分工作,就是圖中有顔色的這兩部分。

  • 第一部分建構了一個騰訊看點的實時資料倉庫。
  • 第二部分就是基于 OLAP 存儲引擎,開發了多元實時資料分析系統。

我們為什麼要建構實時數倉,因為原始的上報資料量非常大,一天上報峰值就有上萬億條。而且上報格式混亂。缺乏内容次元資訊、使用者畫像資訊,下遊沒辦法直接使用。而我們提供的實時數倉,是根據騰訊看點資訊流的業務場景,進行了内容次元的關聯,使用者畫像的關聯,各種粒度的聚合,下遊可以非常友善的使用實時資料。

4、方案選型

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

那就看下我們多元實時資料分析系統的方案選型,選型我們對比了行業内的領先方案,選擇了最符合我們業務場景的方案。

  • 第一塊是實時數倉的選型,我們選擇的是業界比較成熟的 Lambda 架構,他的優點是靈活性高、容錯性高、成熟度高和遷移成本低;缺點是實時、離線資料用兩套代碼,可能會存在一個口徑修改了,另一個沒改的問題,我們每天都有做資料對賬的工作,如果有異常會進行告警。
  • 第二塊是實時計算引擎選型,因為 Flink 設計之初就是為了流處理,SparkStreaming 嚴格來說還是微批處理,Strom 用的已經不多了。再看 Flink 具有 Exactly-once 的準确性、輕量級 Checkpoint 容錯機制、低延時高吞吐和易用性高的特點,我們選擇了 Flink 作為實時計算引擎。
  • 第三塊是實時存儲引擎,我們的要求就是需要有次元索引、支援高并發、預聚合、高性能實時多元 OLAP 查詢。可以看到,Hbase、Tdsql 和 ES 都不能滿足要求,Druid 有一個缺陷,它是按照時序劃分 Segment,無法将同一個内容,存放在同一個 Segment上,計算全局 TopN 隻能是近似值,是以我們選擇了最近兩年大火的 MPP 資料庫引擎 ClickHouse。

5、設計目标與設計難點

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

我們多元實時資料分析系統分為三大子產品

  1. 實時計算引擎
  2. 實時存儲引擎
  3. App層

難點主要在前兩個子產品:實時計算引擎和實時存儲引擎。

  1. 千萬級/s 的海量資料如何實時接入,并且進行極低延遲維表關聯。
  2. 實時存儲引擎如何支援高并發寫入、高可用分布式和高性能索引查詢,是比較難的。

這幾個子產品的具體實作,看一下我們系統的架構設計。

6、架構設計

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

前端采用的是開源元件 Ant Design,利用了 Nginx 伺服器,部署靜态頁面,并反向代理了浏覽器的請求到背景伺服器上。

背景服務是基于騰訊自研的 RPC 背景服務架構寫的,并且會進行一些二級緩存。

實時數倉部分,分為了接入層、實時計算層和實時數倉存儲層。

  • 接入層主要是從千萬級/s 的原始消息隊列中,拆分出不同行為資料的微隊列,拿看點的視訊來說,拆分過後,資料就隻有百萬級/s 了;
  • 實時計算層主要負責,多行行為流水資料進行行轉列,實時關聯使用者畫像資料和内容次元資料;
  • 實時數倉存儲層主要是設計出符合看點業務的,下遊好用的實時消息隊列。我們暫時提供了兩個消息隊列,作為實時數倉的兩層。一層 DWM 層是内容 ID-使用者ID 粒度聚合的,就是一條資料包含内容 ID-使用者ID 還有 B 側内容資料、C 側使用者資料和使用者畫像資料;另一層是 DWS 層,是内容ID粒度聚合的,一條資料包含内容 ID,B 側資料和 C 側資料。可以看到内容 ID-使用者ID 粒度的消息隊列流量進一步減小到十萬級/s,内容 ID 粒度的更是萬級/s,并且格式更加清晰,次元資訊更加豐富。

實時存儲部分分為實時寫入層、OLAP 存儲層和背景接口層。

  • 實時寫入層主要是負責 Hash 路由将資料寫入;
  • OLAP 存儲層利用 MPP 存儲引擎,設計符合業務的索引和物化視圖,高效存儲海量資料;
  • 背景接口層提供高效的多元實時查詢接口。

7、實時計算

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

這個系統最複雜的兩塊,實時計算和實時存儲。

先介紹實時計算部分:分為實時關聯和實時數倉。

7.1 實時高性能維表關聯

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

實時維表關聯這一塊難度在于。百萬級/s的實時資料流,如果直接去關聯 HBase,1 分鐘的資料,關聯完 HBase 耗時是小時級的,會導緻資料延遲嚴重。

我們提出了幾個解決方案:

  • 第一個是,在 Flink 實時計算環節,先按照 1 分鐘進行了視窗聚合,将視窗内多行行為資料轉一行多列的資料格式,經過這一步操作,原本小時級的關聯耗時下降到了十幾分鐘,但是還是不夠的。
  • 第二個是,在通路 HBase 内容之前設定一層 Redis 緩存,因為 1000 條資料通路 HBase 是秒級的,而通路 Redis 是毫秒級的,通路 Redis 的速度基本是通路 HBase 的 1000 倍。為了防止過期的資料浪費緩存,緩存過期時間設定成 24 小時,同時通過監聽寫 HBase Proxy 來保證緩存的一緻性。這樣将通路時間從十幾分鐘變成了秒級。
  • 第三個是,上報過程中會上報不少非正常内容 ID,這些内容 ID 在内容 HBase中是不存儲的,會造成緩存穿透的問題。是以在實時計算的時候,我們直接過濾掉這些内容 ID,防止緩存穿透,又減少一些時間。
  • 第四個是,因為設定了定時緩存,會引入一個緩存雪崩的問題。為了防止雪崩,我們在實時計算中,進行了削峰填谷的操作,錯開設定緩存的時間。

可以看到,優化前後,資料量從百億級減少到了十億級,耗時從小時級減少到了數十秒,減少 99%。

7.2 下遊提供服務

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

實時數倉的難度在于:它處于比較新的領域,并且各個公司各個業務差距比較大,怎麼能設計出友善,好用,符合看點業務場景的實時數倉是有難度的。

先看一下實時數倉做了什麼,實時數倉對外就是幾個消息隊列,不同的消息隊列裡面存放的就是不同聚合粒度的實時資料,包括内容 ID、使用者ID、C 側行為資料、B 側内容次元資料和使用者畫像資料等。

我們是怎麼搭建實時數倉的,就是上面介紹的實時計算引擎的輸出,放到消息隊列中儲存,可以提供給下遊多使用者複用。

我們可以看下,在我們建設實時資料倉庫前後,開發一個實時應用的差別。沒有數倉的時候,我們需要消費千萬級/s 的原始隊列,進行複雜的資料清洗,然後再進行使用者畫像關聯、内容次元關聯,才能拿到符合要求格式的實時資料,開發和擴充的成本都會比較高,如果想開發一個新的應用,又要走一遍這個流程。有了數倉之後,如果想開發内容 ID 粒度的實時應用,就直接申請 TPS 萬級/s 的 DWS 層的消息隊列。開發成本變低很多,資源消耗小很多,可擴充性也強很多。

看個實際例子,開發我們系統的實時資料大屏,原本需要進行如上所有操作,才能拿到資料。現在隻需要消費 DWS 層消息隊列,寫一條 Flink SQL 即可,僅消耗 2 個 CPU 核心,1G 記憶體。

可以看到,以 50 個消費者為例,建立實時數倉前後,下遊開發一個實時應用,可以減少 98%的資源消耗。包括計算資源,存儲資源,人力成本和開發人員學習接入成本等等。并且消費者越多,節省越多。就拿 Redis 存儲這一部分來說,一個月就能省下上百萬人民币。

8、實時存儲

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

介紹完實時計算,再來介紹實時存儲。

這塊分為三個部分來介紹:

  • 第一是 分布式-高可用
  • 第二是 海量資料-寫入
  • 第三是 高性能-查詢

8.1 分布式-高可用

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

我們這裡聽取的是 Clickhouse 官方的建議,借助 ZK 實作高可用的方案。資料寫入一個分片,僅寫入一個副本,然後再寫 ZK,通過 ZK 告訴同一個分片的其他副本,其他副本再過來拉取資料,保證資料一緻性。

這裡沒有選用消息隊列進行資料同步,是因為 ZK 更加輕量級。而且寫的時候,任意寫一個副本,其它副本都能夠通過 ZK 獲得一緻的資料。而且就算其它節點第一次來擷取資料失敗了,後面隻要發現它跟 ZK 上記錄的資料不一緻,就會再次嘗試擷取資料,保證一緻性。

8.2 海量資料-寫入

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

資料寫入遇到的第一個問題是,海量資料直接寫入 Clickhouse 的話,會導緻 ZK 的 QPS 太高,解決方案是改用 Batch 方式寫入。Batch 設定多大呢,Batch 太小的話緩解不了 ZK 的壓力,Batch 也不能太大,不然上遊記憶體壓力太大,通過實驗,最終我們選用了大小幾十萬的 Batch。

第二個問題是,随着資料量的增長,單 QQ 看點的視訊内容每天可能寫入百億級的資料,預設方案是寫一張分布式表,這就會造成單台機器出現磁盤的瓶頸,尤其是 Clickhouse 底層運用的是 Mergetree,原理類似于 HBase、RocketsDB 的底層 LSM-Tree。在合并的過程中會存在寫放大的問題,加重磁盤壓力。峰值每分鐘幾千萬條資料,寫完耗時幾十秒,如果正在做 Merge,就會阻塞寫入請求,查詢也會非常慢。我們做的兩個優化方案:一是對磁盤做 Raid,提升磁盤的 IO;二是在寫入之前進行分表,直接分開寫入到不同的分片上,磁盤壓力直接變為 1/N。

第三個問題是,雖然我們寫入按照分片進行了劃分,但是這裡引入了一個分布式系統常見的問題,就是局部的 Top 并非全局 Top 的問題。比如同一個内容 ID 的資料落在了不同的分片上,計算全局 Top100 閱讀的内容 ID,有一個内容 ID 在分片 1 上是 Top100,但是在其它分片上不是 Top100,導緻彙總的時候,會丢失一部分資料,影響最終結果。我們做的優化是在寫入之前加上一層路由,将同一個内容 ID 的記錄,全部路由到同一個分片上,解決了該問題。

介紹完寫入,下一步介紹 Clickhouse 的高性能存儲和查詢。

8.3 高性能-存儲-查詢

Clickhouse 高性能查詢的一個關鍵點是稀疏索引。稀疏索引這個設計就很有講究,設計得好可以加速查詢,設計不好反而會影響查詢效率。我根據我們的業務場景,因為我們的查詢大部分都是時間和内容 ID 相關的,比如說,某個内容,過去 N 分鐘在各個人群表現如何?我按照日期,分鐘粒度時間和内容 ID 建立了稀疏索引。針對某個内容的查詢,建立稀疏索引之後,可以減少 99%的檔案掃描。

還有一個問題就是,我們現在資料量太大,次元太多。拿 QQ 看點的視訊内容來說,一天流水有上百億條,有些次元有幾百個類别。如果一次性把所有次元進行預聚合,資料量會指數膨脹,查詢反而變慢,并且會占用大量記憶體空間。我們的優化,針對不同的次元,建立對應的預聚合物化視圖,用空間換時間,這樣可以縮短查詢的時間。

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐

分布式表查詢還會有一個問題,查詢單個内容 ID 的資訊,分布式表會将查詢下發到所有的分片上,然後再傳回查詢結果進行彙總。實際上,因為做過路由,一個内容 ID 隻存在于一個分片上,剩下的分片都在空跑。針對這類查詢,我們的優化是背景按照同樣的規則先進行路由,直接查詢目标分片,這樣減少了 N-1/N 的負載,可以大量縮短查詢時間。而且由于我們是提供的 OLAP 查詢,資料滿足最終一緻性即可,通過主從副本讀寫分離,可以進一步提升性能。

我們在背景還做了一個 1 分鐘的資料緩存,針對相同條件查詢,背景就直接傳回了。

8.4 擴容

這裡再介紹一下我們的擴容的方案,調研了業内的一些常見方案。

比如 HBase,原始資料都存放在 HDFS 上,擴容隻是 Region Server 擴容,不涉及原始資料的遷移。但是 Clickhouse 的每個分片資料都是在本地,是一個比較底層存儲引擎,不能像 HBase 那樣友善擴容。

Redis 是哈希槽這種類似一緻性哈希的方式,是比較經典分布式緩存的方案。Redis slot 在 Rehash 的過程中雖然存在短暫的 ask 讀不可用,但是總體來說遷移是比較友善的,從原 h[0]遷移到 h[1],最後再删除 h[0]。但是 Clickhouse 大部分都是 OLAP 批量查詢,不是點查,而且由于列式存儲,不支援删除的特性,一緻性哈希的方案不是很适合。

目前擴容的方案是,另外消費一份資料,寫入新 Clickhouse 叢集,兩個叢集一起跑一段時間,因為實時資料就儲存 3 天,等 3 天之後,背景服務直接通路新叢集。

9、成果

騰訊看點實時資料倉庫:DWM 層和 DWS 層,資料延遲 1 分鐘。

遠見多元實時資料分析系統:亞秒級響應多元條件查詢請求,在未命中緩存情況下,過去 30 分鐘的查詢,99%的請求耗時在 1 秒内;過去 24 小時的查詢,90%的請求耗時在 5 秒内,99%的請求耗時在 10 秒内。

更多 Flink 技術交流可加入 Flink 社群釘釘大群。

騰訊看點基于 Flink 的實時數倉及多元實時資料分析實踐