來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭祕,必須學習一手

前言

本次分享主要有三個部分:Kylin 在滴滴的整體應用、架構的實踐經驗、滴滴全局字典最新版本的實現以及 Kylin 最新實時 OLAP 探索經驗分享。

Kylin 在滴滴的應用&架構

Kylin 在滴滴的三類應用場景

第一類是產品類的需求,這一類需求的特點比較明顯,即用戶要求整個查詢的響應時間非常小,理論上都是秒級而且穩定;同時各產品 RD 的接入成本需要特別低,一般的 RD 可能不是很擅長大數據技術,不太清楚怎麼用 Spark、Hbase 進行數據查詢,他們通常最擅長就是通過 JDBC 去連接,然後用標準的 SQL 進行操作。引入 Kylin 後可以極大地提高這類用戶對接大數據的效率(之前如果產品要通過大數據查詢報表數據,一般有兩種做法:一種是將數據通過離線算好後再導回 MySQL,另一種是離線算好後灌入第三方存儲如 HBase,再通過 KV 或者 Phoenix 查詢)。

第二類需求是報表類的需求,在滴滴接入的主要是自定義的報表。滴滴有一個類似於 tableau 報表系統的自研平臺,運營分析人員可以在上面自助配置相應的報表,Kylin 主要起到加速作用。

第三類需求是活動營銷,包括事前範圍分析,以及事後營銷結果分析,這也是在 Kylin 上面做的。活動營銷這一類的 cube,其生命週期可能不是太長,通常在一到兩個月之間。

滴滴 Kylin 集群現狀

目前,Kylin 在滴滴一共有六個集群,其中五個在國內,另一個在國外。當前線上的主要版本還是 Kylin 2.0,但滴滴目前正在把 2.0 往 3.0 遷移,所以在國內也搭建了 Kylin 3.0 集群。目前 Cube 數量大概在三千二百個左右,每天構建任務數大約有四千多個,HBase 表規模在五萬左右。

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

這是 Kylin 3.0 的截圖,可以發現它整個查詢時延還是非常低的,基本上平均時延在 0.29 秒,而這還可以更快。另外數據膨脹也比較低,差不多是 1.83 的量級。


來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

這個是一個 Presto 對比 Kylin 的查詢截圖,查詢數據量不太大。Kylin 穩定在 0.1 秒以內反饋結果,而 Presto 需要 6 到 25 秒,Kylin 對於命中了 Cuboid 的查詢在時間和穩定性都表現出色。

目前滴滴 Kylin 3.0 對接了 Presto 作為下推引擎,解決用戶提交未建模(Cube)的 SQL 查詢時也可以拿到結果的需求,當然響應時長可能會有一定差別。

使用 Kylin 過程中的痛點及解決方式

1. 易用性、靈活性

Kylin 在穩定性和易用性,以及釋放數倉人員的雙手等方面做了很多工作,但是也會有一些易用性或者靈活性上面的問題。

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

(1)維度表的數據要求嚴格。比如說維度表裡面其中一個要求是 ID 不能重複,且每條數據都必須是唯一的。但是目前滴滴數倉中有一部分維度表,是每天根據分區全量放進 Hive 表的(每個分區都有全量數據)。而這類數據是沒有辦法直接在 Kylin 中被當做維度表使用的。

(2)沒有字段預處理功能。通常來說就算是標準化的表,我們可能也會有對某些字段進行一些簡單處理地需求,比如進行 concat、substr 等這樣一些操作。

(3)Kylin 增量構建的時候,他對分區的格式比較固定且精確到天的分區只能有一個分區字段(如 DT=20190528)一個字符串。但是由於歷史原因,滴滴目前有很多的表的分區可能有三層,比如 year 一層,month 一層,day 一層,這種是沒有辦法直接使用的。

(4)Kylin 對於複雜 SQL 建模支持較弱。另外一個使用場景比較特殊,即 Model 管理,但複用率底。Kylin 要求用戶在創建 Cube 前一定要創建 Model, 但是 Model 的複用性在我們公司並不高,Model 和 Cube 的比例基本是 1:1。這導致整個 model 的維護成本較高,因而我們希望用戶只暴露 Cube 層。

針對易用性、靈活性問題,滴滴的解決方式如下:

針對複雜 SQL、Model 管理、字段預處理、分區、維度數據有重複等問題,在用戶對接 Kylin 的時候,我們在中間增加了”建模轉換”層。用戶通過在公司自研的數易報表平臺進行建模配置,然後由報表系統提交給建模轉換層,負責對用戶 SQL 進行預處理,主要是將用戶的 SQL 轉換成 Kylin 可以使用的表:創建一張臨時表,而這張臨時表就是 Kylin 需要的一張標準表,並調用 Kylin 的 API 進行建模。這樣不論用戶寫多麼複雜的 SQL,還有包括剛剛提到的這些字段的轉換,都可以通過 Kylin 進行加速。

這個時候用戶做的事情就變得很簡單,他只需要在報表平臺寫相關的 SQL,配置維度或度量。剩下的事情就交給建模平臺,它會去調相應的 API 創建建模以及打通調度系統,從而屏蔽整個 load table 以及創建 model,cube 等過程,上文提到的那些複雜 SQL 轉換也完成了。

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

2. 廣播時延、元數據一致性問題

第二個問題是在較高併發的情況Kylin元數據可能會出現一致性和時延問題。

一方面Kylin的每個節點的元數據通信是通過廣播的機制處理,即在A節點做了變更,通過Api的方式廣播到其他節點,這時A和其他節點會有時延,尤其是在較高併發修改元數據時(批量創建或修改model/cube/table等),此問題會比較突出;

另一方面,滴滴使用HBase作為Kylin的存儲引擎,Kylin很多地方在做模型管理的時候分為多個步驟(如:創建Model時就有兩步需要update HBase中的數據。先將Model的schemal信息保存進hbase並廣播到其他節點,然後在update project的信息並廣播到其他節點),由於沒有分佈式事物,這兩步是可能會出現元數據一致性的問題的。

針對時延和元數據一致性問題,滴滴的解決方式如下:

虛擬一個 State 角色,其他平臺所有對 Kylin 的元數據的CUD API 操作,全部都在這樣一個角色上運行,這個角色的模式是 standby/active。這只是一個虛擬的角色,並非真實地添加了一個這樣的形象,可以把某兩個 build 的節點當做 State 角色。另外我們還添加一個元數據補全的 API,當系統發現某個元數據出現問題後,可以調用這個 API 來進修補全操作(之前可能需要人為修改 HBase 中的元數據或者遠程 Debug 解決)。

在創建 Model 的時候用戶做了兩件事情,第一件事情是把 model 存到 HBase 中進行持久化,第二件事是 update HBase 中相關 project 的元數據,刪除的時候也是同樣的步驟,但是兩個步驟有可能沒辦法全部成功,這樣就會導致系統中有髒數據的存在,甚至會引發元數據不一致等問題。而且這種數據是不好清理的,因為它在 HBase 裡是一張大表,一條一條地清理會非常麻煩。最開始時,要想清理這樣一些數據,只能通過 debug 的方式。

現在採取補全 API 的方式,思路也很簡單,既然 Model 不能刪除是因為有某個 Cube 依賴(實際這個 Cube 已經不存在了),對此,我們就會通過這個 API 虛擬一個 Cube,相當於把它補全進去,再去調 API,就可以把這個 Model 清除掉了。

3. 集群治理方面的實踐

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

· Job 調度

第一個問題是滴滴現在的調度只能調度最近 3 天的 job,為什麼只調度最近 3 天的 job?

我們每天的任務數差不多是四千個左右。Kylin 目前的做法是把整個 Job 全部 Load 出來,一個一個的串行判斷看能否滿足調度需求或者能不能調度,這個調度時間還是比較長的,而且隨著 job 數的不斷累積,單次輪訓一次的時間還會不斷增加,最後會導致原本預計的1分鐘輪訓一次,變為 5 分鐘甚至 10 分鐘還無法完成。我們的做法是,在這裡做了過濾,只允許拿出最近三天的任務去調度。另外有一些任務,它可能永遠都無法 Build 完成(基數特別大、超多維度等)、或者 Build 的時候總是失敗(比如沒有權限),這些任務如果不處理就會導致一致佔用運行中的任務資源,最後甚至導致耗光所有的 Build 資源(達到 Build 最大任務數)而無法運行新任務。對於這樣一些情況,我們目前加了自動處理機制,會自動 Discard 掉用戶運行時長大於 24 小時的任務,避免系統中出現殭屍任務。

· API 加速

另外還有一些 API,我們將 API 與數據的處理做了分離,如 Purge 或者 Discard 的操作,這些 API 調用的時候時候會真正觸發數據的刪除或者一系列動作(涉及到數據清除、元數據清理其實會是一個比較耗時的過程),為了提高整個 API 的響應速度,我們目前把所有的 API 與數據操作做了分離,API 調用的時候只是把狀態做了一個變更,這樣可以大大提供 API 響應速度和成功率。真正的數據清理會放在定期歷史數據和元數據清理的任務中去做。

4. 集群運維

· 配置與代碼分離

在運維方面,滴滴把 Kylin 的配置和代碼做了分離,因為版本迭代的比較多,但整個配置改動比較少,所以我們將 Kylin 的配置和代碼進行分開管理。另外 Kylin 集群上會增加一個負載均衡層。這樣,一方面能解決集群的負載均衡情況,另一方面還能在以後 Kylin 版本的升級中做到對用戶完全透明。

· 監控或探活類服務

滴滴還加了一些監控或者是探活類的服務。我們單獨加了一個在線看日誌和遠程重啟 Kylin 的小工具。這樣當 Kylin 出現問題而電腦又不在身邊時,就可以通過這個小工具在手機上實時地看到日誌或進行相應的重啟操作。這是一個簡單又實用的功能。監控方面,除了添加錯誤日誌、正在運行的任務數等一些指標監控外,我們還添加了一個探活服務,實時探測 Kylin 查詢是否正常。

· 使用 Spark Livy 構建

目前,滴滴計算引擎正在大力推 Spark,所以對於 Kylin,我們也推薦使用 Spark 的方式進行構建,Spark Livy 構建方面也是由滴滴貢獻到社區。

· 全局字典構建

全局字典構建方面,尤其是在精準去重耗時優化,去重結果明細鑽取方面,我們做了比較多的工作,下面會詳細介紹滴滴最新版本的全局字典。


滴滴全局字典最新版本介紹

背景介紹

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

最開始用社區 Tire Tree 方式構建字典,可能遇到這樣幾個問題:第一個是數據量達到 3-4 億規模的時候,可能就到達了瓶頸,比如出不來結果,或者對內存的要求特別高。另外構建速度從最開始只需要四五分鐘,到後來可能十個小時也出不來結果。另一個需求是我們希望減少重複構建,在社區,單個 cube 內列的複用是有的,但它在整個集群內部是沒有的,而我們希望列在整個集群間也可以複用。最後是一個隱性的需求,即目前精準去重的字典是不能反查的。比如說,我們只能求出這個 UV 今天是五十個,但是至於是哪五十個,是不知道的。在這樣的背景下,然後我們做了三個版本的迭代。


滴滴全局字典的三個版本迭代

第一個版本是純 Hive 的實現,已經貢獻給社區了。這個版本由於使用了 Hive 的 order by,會隨著數據量的增加在 order by 這一步 MR 的 shuffle 過程達到瓶頸(時間和單 MR 的內存),最終無法構建全局字典。

第二個版本是在第一個版本上面做了一些改進,解決全局排序在一個 shuffle中的問題。這個版本解決了突破單列構建數量的瓶頸,基本上在 Kylin 全局字典目前允許的最大範圍(21 億數據量)內都可以恆定在 15 分鐘出結果。

第三個版本在第二個版本又做了一次改進,將第二個版本在同一個 Cube 多列求精準去重由串行改成並行的方式。在理論上實現無論一個 Cube 有多少列精準去重的需求,也不管單列的數據量有多大,都是可以恆定在 15 分鐘左右出結果。

接下來大概與大家分享下,全局字典3個版本實現邏輯。

通俗而言,字典就是把一個字符串轉換成唯一的一個 int 類型編碼,這是最終字典要做的事,我們現在的做法如下:

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

Version 1:

第一步通過 HQL 把本次需要構建字典的增量原始值給取出來,比如說這次需要增量構建的字典原始值有張三、李三,同時會查詢此 Cube 之前字典裡面的最大編碼,比如之前字典中只有王芳,他的編碼是 1,則這個 Cube 當前的最大編碼即為 1。

第二步通過 HQL 真正編碼,我們把第一步得到的增量原始值採用 order by 排序並通過 row number 的方式給每個值一個編碼(每個值真正的編碼為 row number + 之前字典的 max 編碼值)。比如此時李三對應的編碼就為 2,張三編碼就是 3.

第三步通過 HQL 與之前的字典表做合併,合併後此 Cube的字典裡面有三行記錄(王芳,1|李三,2|張三|3),如上圖。

最後一步,通過 HQL 用字典表中的字典編碼去 replace 掉 Kylin 第一步的臨時扁平表的原始值。即把張三和李三、王芳等,替換成他們的編碼。後續關於這一列就無需再編碼了(已經是 Int 類型),這是第一版,已經發給社區了。


來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

Version 2:

第二版在增量抽取 Extract、 Merge 和 Replace 步驟與Version 1 還是一樣的,主要改動是在第二步 Dict 編碼部分。Version 1 因為採用Hive Order by 的形式編碼,最後一個 order by shuffle 的過程隨著數據量的增加會成為單點,時效和內存則會成為瓶頸。所以Version 2 我們用 MR total Order Partition 編碼替換掉 Hive 的 Order by 編碼。TotalOrder Partition 最終求出的順序和編碼值與 Hive Order by 獲取的結果一模一樣,但是他的整個 map reduce 過程是並行化的,不再受數據量和單節點的限制,基本突破了超高基數字典編碼的瓶頸。


來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

Version 3:

第三版本,又在第二版本上面做了迭代,將同一個 cube 多列精準去重由串行改為並行的方式。第二版本里面因為我們使用了 total Order Partition,這種機制只適合對某一列做排序,做不到多列並行排序,又或改造成本非常大。經過思考,我們發現並非整個字典編碼真的需要順序,只需要滿足每個原始值在同一個字典中有一個唯一的 Int 編碼,編碼最後緊湊就可以了。既然不在乎排序,那我們也不需要用 Total Order Partition 了,普通的 MR 就可以。最後我們採用的 Multiple Output 和自定義 Partitoner 的方式,來處理多列並行編碼。理論上,V3 版本無論多少列單個 Cube求精準去重,只要單列的基數在 Kylin 允許的字典基數(2^31-1)範圍內,均可以在 15 分鐘能夠完成。

另外這種版本的字典編碼是可以反查的。後續我們還可以在全局字典上做更多的事情,如明細鑽取、數據反查、數據公海等。數據公海是指我們希望所有 Cube集群都可以共用這個字典。數據中臺提倡 One ID、One Service 這樣一些概念,我們未來也可能會在此有一些突破。

當然採用這種方式構建字典目前也還有一些瓶頸,比如在小數據量的情況下,它的構建速度其實是沒有社區的 Trie Tree 方式快的,Trie Tree 採用單節點內存中操作,小數據量構建會很快。咱們這種編碼方式無論數據量多少可能都需要十來分鐘,因為 4 個步驟(Extract、Dict、Merge、Replace)每步都需要啟動MR,後續這塊兒也會進行進一步優化。

上述幾個步驟都是通過 MR 實現的,未來其實也可以用 Spark 函數來實現,我們現在沒有這樣做,一方面是基於時間問題,還有一部分原因是他的時效性已經達到我們的要求。但是基於代碼優雅性比如說全切 Spark 版本的話,這其實是需要做改善的。

Kylin RT OLAP 探索經驗分享

RT OLAP 新引入的兩種角色和兩種概念

第三部分主要分享 Kylin 社區目前主推的實時 OLAP 的探索過程。整個探索也是從今年 8 月底、9 月份的時候開始的。

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

社區截圖

實時 OLAP 模塊在架構上主要增加了兩個角色,一個是 Coordinator,一個是 Receiver。Coordinator 類似於一個 Master 的角色,它會負責 receiver 的管理、分配/解除分配 topic 的partition到指定的replica set, 停止或重啟消息的消費 , 提交構建任務等。Receiver 負責真正的從 kafaka 中消費數據並做基本的計算,是真正幹活的節點。因為添加了實時的鏈路,查詢時會根據時間區間決定去歷史部分還是實時部分查詢,歷史部分還是和原來一樣,去 HBase 上面去查詢,實時部分則會相應的 Receiver 節點查詢。

下面這個圖,主要詳細講解 Coordinator 和 Reciver 兩種角色與 Kafka topic 、Assignment、Replica Set 之間的關係:

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

Coordinator 節點採用的是 Standby/Active 的架構,節點可以有 N 個,但是同時對我提供的服務只有一個,即通過 ZK 選舉產生 Master 節點。Coordinator 首先會負責管理這些 Receiver 的節點,以及某個 Kafka partition 到底由哪些 Receiver 去消費,還會負責去提交 Build 任務即把實時部分的數據進行進一步預計算後存儲到 Hbase 裡面去,另外 Coordinator 還會做一些 metrics 信息採集的工作。

上面已經提過了,Receiver 是真正負責消費的角色,消費過程如下:Kylin 實時 OLAP 增加了一個 Replica Set 的概念類似於副本組,每個 Replica Set 是由 N 多個 Receiver 節點組成,同一個 Replica Set 裡面的 Receiver 負責消費同樣的數據,類似於一組 Receiver 結點去負責消費某些 Kafka 中的某些 partition 數據。另外每個 Replica Set 裡面會有一個 Receiver 節點是這組的 Master 節點,這個被選中為 Master 節點的 Receiver 除了做消費的活以外,可能還會做一些額外的事情,比如說幫助用戶把這個構建的歷史數據上傳到 HDFS 上去。

第二個概念是 Assignment。Assignment 屬於 Cube 層面的一個屬性,通俗一點講,Assignment 保存了某個 Cube 的實時數據由哪些 Replica Set 負責消費,每個 Replica Set 負責消費這個 Cube 中 Kafka topic 中的哪些 partition。如上圖左上角,某個 Cube 由 ID 為 0 和 1 的這兩個 Replicat Set 負責消費,其中 Replica set 0 負責消費 topic 的 partition ID 為 0、2、5 的消息,Replica set 1 負責消費 topic 的 partition ID 為 1、3、4 的消息.

這是整個實時的新引進的兩個角色和兩種概念的介紹。

Segment狀態的流轉過程

來自滴滴 3000+ Kylin Cube 背後的實踐經驗揭秘,必須學習一手

在實時方面, segment 的增加了 3 種新的狀態:Active、Immutable 以及 Remote Persisted,Ready 是之前的離線 OLAP 也有的。

Active 狀態是由 Receiver 在消費 Kafka 數據的時候創建的,當消費到某一條數據發現它不屬於已經創建的 Segment 的時間範圍,它就會創建一個新的 Segment,狀態為 Active。只有屬於 Active 狀態的 Segment 才會接收新的數據,只要是在這個區間以內的數據都會放在這個 Active 的 segment 裡面去,當到達一定時間、一定狀態以後,狀態就會變成 immutable 的狀態。

變成 immutable 狀態的數據不能再接收新的數據。Active 狀態變更為 Immutable,是由 Receiver 在消費每條數據的時候判斷,這條數據對應的 active segment 是否已經創建,如果沒有,它就要創建一個新的 active segment,這時同時也會去判斷是否有處於 Active 狀態的 Segment 達到了變成 Immutable 狀態的一個條件,如果達到了則將這個 Segment 由 Active 變更為 Immutable 狀態。除了這種情況下 Active 會變成 Immutable 狀態外,另外當我們在做 Re-assign 的時候,即更換某個 Cube 的消費 Receiver 節點時,不再繼續負責消費此 Cube 的 Receiver 節點上處於 Active 狀態的 Segment 會全部變成 Immutable 狀態。

第三個狀態是 Remote Persisted,當某個 Segment 變更為 Immutable 狀態後,表示此 Segment 不再接收新的數據,接下來就需要把處於 Immutable 狀態的 Segment 進行歷史化處理,並構建到 HBase 裡面去。在此之前,首先要把本地 Receiver 上面的數據上傳到 HDFS 上面,上傳完成後,則Segment 相應的狀態將變成Remote Persisted。Receiver 會啟動一個後臺的定時輪詢線程,負責將 Cube 的 Build 策略配置為 Full_Build 的 Immutable 狀態的 Segment 上傳到 HDFS,當然真正上傳數據的只有 Replica Set 中處於 Master 節點的 Receiver 上傳。

第四個就是 ready 狀態,Segment 變更為 Ready 狀態後表示這部分數據已經轉換為離線部分數據,並已經存入到 HBase 中了。當 Receiver 把某個 Segment 數據上傳到 HDFS 以後,Receiver 會調用一次 Coordinator 的 API,通知 Coordinator 這個 Cube 現在可以去做 Build 操作(啟動 MR Build 任務將實時數據進一步處理如字典合併,然後把相應數據轉換成 HFile 存入 HBase 中);同時 Receiver還會把一些有關此 Segment 的一些元數據信息寫入 ZK中,供 Coordinator 啟動 Build 任務時使用。當 Build 任務構建成功後,Segment 的狀態將會由 Remote Persisted 狀態變更為 Ready。這就是整個 Segment 狀態的流轉過程。

滴滴調研 Kylin 實時 OLAP 過程中的問題

第一個是整個 Kylin 實時 OLAP 每個 Segment 各個狀態的流轉和處理都是通過時間順序串行處理的。這可能會引發一些問題,比如只要一旦有一個 Segment 在某步出了問題,則整個 Cube 可能都不再工作了。

另一個是分佈式事務問題,因為 Kylin RT OLAP 的元數據一部分在 HBase 中,一部分在 ZK 中,還有一部分在內存,但是整個是沒有分佈式事物的,某些地方也沒有冥等性策略,這是極有可能出現元數據與實際不一致的情況,一旦出現了數據不一致,就可能導致某個 Segment 無法按照整個正常的流程流轉導致這個Segment 不能變更為 ready,同時因為 Segment 的時間順序處理,進而導致後續此 Cube 的 Segment 也沒有辦法進一步變更成 ready,最終只能將此 Cube Disable 和數據 purge 掉後重新消費解決,這對生產實時場景來說是不可接受的。這裡我們在一些關鍵元數據管理的步驟加入了冥等性策略,大部分也已經反饋給社區了。調整過一版本後,目前沒有發現 Segment 因為元數據不一致而導致失敗的情況。

第三個是將實時部分數據通過 MR build 轉換成離線存入 HBase 的過程,這個 Build 任務可能會遇到永遠無法 Build 成功的 bad case(比如代碼的 Bug 或者上傳到 HDFS 上的數據被刪除了等),通常來說如果是離線 OLAP 我們只需要把這個 Segment 的 Build job discard 掉後重新提交一個 Build 任務就可以了。但是對於實時 OLAP 之前是沒有 disable 功能的,再加上上面的時間順序問題會導致整個 Cube 都只能 disable 、purge 掉數據後重頭再來 Cube。現在我們在這個地方加了相應的一個機制,Segment 可以 discard,discard 後可以自動重新提交 Build 任務進行恢復。

另外的遇到的一個問題就是時區的問題,總是會差 8 個時區。我們和社區對於時區的問題都改了一個版本,社區是在查詢端改的,每次查詢的時候在用戶的 SQL 上把時間列自動偏移 8 個小時。這種改法對代碼優雅性而言是很好的,但是可能會遺留另外一些問題,比如說涉及到跨天,查詢出來的數據可能就不是正確的了;另一個是對每一條查詢出的結果裡面所有的時間列也還需要在轉換一次 8 小時偏差才會是用戶想要的結果。我們的改法是在入庫的時候就把時間糾正成用戶想要的正確時間點,比如差 8 個小時就加 8 個小時,這樣對於入庫的點直接作一個糾正,用戶在查詢的時候,就會得到真正想要這樣結果。而這種對於代碼優雅性來說未必合適,因為 Kylin 存儲的是 timestamp,我們相當於在 timestamp 上加了 8 小時,不過這種改法比較簡單對後續的查詢也比較徹底。

此外,還有一個 Build 時長的問題,把 Remote Persisted 數據轉換成 Ready,這個 Build 過程還是挺長的,當然也得看數據量以及配的 Segment 窗口時間有多少,這一塊需要上線測一下,根據自己的實際情況進行配置,正常情況下 Build 時間一定要小於 Segment 窗口時間,否則長期累積會達到此 Cube 的最大 Build 併發的限制,嚴重的時候會導致不在消費新的 Kafka 中的數據了(因為阻塞了太多 Segment 沒有變成 ready 狀態),所以大家在上線前儘量去測試一下, Segment 窗口期到底多長是比較合適的。

期待 Kylin 早日發佈實時 OLAP 穩定版本(已於 19 年 12 月 20 日發佈),對真正實現離線、實時 OLAP 統一引擎具有非常重大的意義。


分享到:


相關文章: