騰訊看點基於 Flink 的實時數倉及多維實時數據分析實踐

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

本文將介紹信息流場景下,騰訊看點的實時數據倉庫和多維實時數據分析系統的技術架構。sql

一、可解決的痛點

能夠先看一下,多維實時數據分析系統能夠解決哪些痛點。好比:數據庫

  • 推薦同窗 10 分鐘前上了一個推薦策略,想知道在不一樣人羣的推薦效果怎麼樣?
  • 運營同窗想知道,在廣東省的用戶中,最火的廣東地域內容是哪些,方便作地域 Push。
  • 審覈同窗想知道,過去 5 分鐘,遊戲類被舉報最多的內容和帳號是哪些?
  • 老闆可能想了解,過去 10 分鐘有多少用戶在看點消費了內容,對消費人羣有一個宏觀瞭解。

二、調研

在進行開發以前,咱們作了這些調研。 瀏覽器

1. 離線數據分析平臺可否知足這些需求,結論是不能知足。離線數據分析平臺不行的緣由以下。緩存

  • C 側數據上報過來,須要通過 Spark 的多層離線計算,最終結果出庫到 MySQL 或者 ES 提供給離線分析平臺查詢。這個過程的延時最少 3-6 個小時,目前比較常見的都是提供隔天的查詢,因此不少實時性要求高的業務場景都是不能知足的。
  • 另外一個問題是,騰訊看點的數據量太大,帶來的不穩定性也比較大,常常會有預料不到的延遲。因此,離線分析平臺是沒法知足不少需求的。

2. 實時數據分析平臺的話,事業羣內部提供了準實時數據查詢的功能,底層技術用的是 Kudu+Impala,Impala 雖然是 MPP 架構的大數據計算引擎,而且訪問以列式存儲數據的 Kudu。可是對於實時數據分析場景來講,查詢響應的速度和數據的延遲都仍是比較高,查詢一次實時 DAU,返回結果耗時至少幾分鐘,沒法提供良好的交互式用戶體驗。因此(Kudu+Impala)這種通用大數據處理框架的速度優點更多的是相比(Spark+Hdfs)這種離線分析框架來講的,對於咱們這個實時性要求更高的場景,是沒法知足的。服務器

三、項目背景

通過剛纔的介紹,再來看下咱們這個項目的背景。做者發文的內容被內容中心引入,通過內容審覈鏈路,啓用或者下架。啓用的內容給到推薦系統和運營系統,而後推薦系統和運營系統將內容進行 C 側分發。內容分發給 C 側用戶以後,用戶會產生各類行爲,曝光、點擊、舉報等,經過埋點上報實時接入到消息隊列中。接下來咱們作了兩部分工做,就是圖中有顏色的這兩部分。架構

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

咱們爲何要構建實時數倉,由於原始的上報數據量很是大,一天上報峯值就有上萬億條。並且上報格式混亂。缺少內容維度信息、用戶畫像信息,下游沒辦法直接使用。而咱們提供的實時數倉,是根據騰訊看點信息流的業務場景,進行了內容維度的關聯,用戶畫像的關聯,各類粒度的聚合,下游能夠很是方便的使用實時數據。併發

四、方案選型

那就看下咱們多維實時數據分析系統的方案選型,選型咱們對比了行業內的領先方案,選擇了最符合咱們業務場景的方案。框架

  • 第一塊是實時數倉的選型,咱們選擇的是業界比較成熟的 Lambda 架構,他的優勢是靈活性高、容錯性高、成熟度高和遷移成本低;缺點是實時、離線數據用兩套代碼,可能會存在一個口徑修改了,另外一個沒改的問題,咱們天天都有作數據對帳的工做,若是有異常會進行告警。
  • 第二塊是實時計算引擎選型,由於 Flink 設計之初就是爲了流處理,SparkStreaming 嚴格來講仍是微批處理,Strom 用的已經很少了。再看 Flink 具備 Exactly-once 的準確性、輕量級 Checkpoint 容錯機制、低延時高吞吐和易用性高的特色,咱們選擇了 Flink 做爲實時計算引擎。
  • 第三塊是實時存儲引擎,咱們的要求就是須要有維度索引、支持高併發、預聚合、高性能實時多維 OLAP 查詢。能夠看到,Hbase、Tdsql 和 ES 都不能知足要求,Druid 有一個缺陷,它是按照時序劃分 Segment,沒法將同一個內容,存放在同一個 Segment上,計算全局 TopN 只能是近似值,因此咱們選擇了最近兩年大火的 MPP 數據庫引擎 ClickHouse。

五、設計目標與設計難點

咱們多維實時數據分析系統分爲三大模塊分佈式

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

難點主要在前兩個模塊:實時計算引擎和實時存儲引擎。

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

這幾個模塊的具體實現,看一下咱們系統的架構設計。

六、架構設計

前端採用的是開源組件 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.1 實時高性能維表關聯

實時維表關聯這一塊難度在於。百萬級/s的實時數據流,若是直接去關聯 HBase,1 分鐘的數據,關聯完 HBase 耗時是小時級的,會致使數據延遲嚴重。

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

  • 第一個是,在 Flink 實時計算環節,先按照 1 分鐘進行了窗口聚合,將窗口內多行行爲數據轉一行多列的數據格式,通過這一步操做,本來小時級的關聯耗時降低到了十幾分鍾,可是仍是不夠的。
  • 第二個是,在訪問 HBase 內容以前設置一層 Redis 緩存,由於 1000 條數據訪問 HBase 是秒級的,而訪問 Redis 是毫秒級的,訪問 Redis 的速度基本是訪問 HBase 的 1000 倍。爲了防止過時的數據浪費緩存,緩存過時時間設置成 24 小時,同時經過監聽寫 HBase Proxy 來保證緩存的一致性。這樣將訪問時間從十幾分鍾變成了秒級。
  • 第三個是,上報過程當中會上報很多很是規內容 ID,這些內容 ID 在內容 HBase中是不存儲的,會形成緩存穿透的問題。因此在實時計算的時候,咱們直接過濾掉這些內容 ID,防止緩存穿透,又減小一些時間。
  • 第四個是,由於設置了定時緩存,會引入一個緩存雪崩的問題。爲了防止雪崩,咱們在實時計算中,進行了削峯填谷的操做,錯開設置緩存的時間。

能夠看到,優化先後,數據量從百億級減小到了十億級,耗時從小時級減小到了數十秒,減小 99%。

7.2 下游提供服務

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

先看一下實時數倉作了什麼,實時數倉對外就是幾個消息隊列,不一樣的消息隊列裏面存放的就是不一樣聚合粒度的實時數據,包括內容 ID、用戶ID、C 側行爲數據、B 側內容維度數據和用戶畫像數據等。

咱們是怎麼搭建實時數倉的,就是上面介紹的實時計算引擎的輸出,放到消息隊列中保存,能夠提供給下游多用戶複用。

咱們能夠看下,在咱們建設實時數據倉庫先後,開發一個實時應用的區別。沒有數倉的時候,咱們須要消費千萬級/s 的原始隊列,進行復雜的數據清洗,而後再進行用戶畫像關聯、內容維度關聯,才能拿到符合要求格式的實時數據,開發和擴展的成本都會比較高,若是想開發一個新的應用,又要走一遍這個流程。有了數倉以後,若是想開發內容 ID 粒度的實時應用,就直接申請 TPS 萬級/s 的 DWS 層的消息隊列。開發成本變低不少,資源消耗小不少,可擴展性也強不少。

看個實際例子,開發咱們系統的實時數據大屏,本來須要進行如上全部操做,才能拿到數據。如今只須要消費 DWS 層消息隊列,寫一條 Flink SQL 便可,僅消耗 2 個 CPU 核心,1G 內存。

能夠看到,以 50 個消費者爲例,創建實時數倉先後,下游開發一個實時應用,能夠減小 98%的資源消耗。包括計算資源,存儲資源,人力成本和開發人員學習接入成本等等。而且消費者越多,節省越多。就拿 Redis 存儲這一部分來講,一個月就能省下上百萬人民幣。

八、實時存儲

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

這塊分爲三個部分來介紹

  • 第一是 分佈式-高可用
  • 第二是 海量數據-寫入
  • 第三是 高性能-查詢

8.1 分佈式-高可用

咱們這裏聽取的是 Clickhouse 官方的建議,藉助 ZK 實現高可用的方案。數據寫入一個分片,僅寫入一個副本,而後再寫 ZK,經過 ZK 告訴同一個分片的其餘副本,其餘副本再過來拉取數據,保證數據一致性。

這裏沒有選用消息隊列進行數據同步,是由於 ZK 更加輕量級。並且寫的時候,任意寫一個副本,其它副本都可以經過 ZK 得到一致的數據。並且就算其它節點第一次來獲取數據失敗了,後面只要發現它跟 ZK 上記錄的數據不一致,就會再次嘗試獲取數據,保證一致性。

8.2 海量數據-寫入

數據寫入遇到的第一個問題是,海量數據直接寫入 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 看點的視頻內容來講,一天流水有上百億條,有些維度有幾百個類別。若是一次性把全部維度進行預聚合,數據量會指數膨脹,查詢反而變慢,而且會佔用大量內存空間。咱們的優化,針對不一樣的維度,創建對應的預聚合物化視圖,用空間換時間,這樣能夠縮短查詢的時間。

分佈式表查詢還會有一個問題,查詢單個內容 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 天以後,後臺服務直接訪問新集羣。

九、成果

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

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

相關文章
相關標籤/搜索