kylin+SuperSet實現實時大數據報表的快速開發

最近我的團隊將報表計算引擎從阿里的ads遷移到了kylin上,解決了非常多的問題,將一些我們的解決方案分享出來,希望對讀者或者在用kylin的人有所幫助。

一、 之前現狀和問題

之前我們系統的報表都是基於阿里的rocketmq和ADS開發的,業務系統在業務代碼中將數據同步到rocketmq中,然後ads再從rocketmq同步數據,再基於ads提供的api開發查詢邏輯,前端還要開發報表展示的代碼。這種方式上線以後,隨著數據量的不斷增長暴露出了很多缺陷。

  1. 經常會出現消息丟失的情況,或者系統變慢的情況。
  2. 由於購買的阿里雲的服務,rocketmq和ADS服務對我們來說一直是一個黑盒,問題很不好定位和解決,而且很多問題的解決依賴於阿里雲,響應時效不是很及時,長此以來積累了大量的報表問題,客戶抱怨聲不斷。
  3. 開發工作量龐大,產品人員設計好一張報表以後,要上線要苦等一個多月的開發時間,而且遇到問題還無法上線。

基於以上問題我們覺得再繼續用阿里的ads作為我們的報表計算引擎,後續問題會越來越多。因此我們嘗試使用新的報表引擎,這個報表引擎對我們一定不是一個黑盒。

二、 報表計算引擎的選擇(kylin)

基於以上幾個問題,在對tidb,druid,kylin,mdrill等各種開源系統進行調研以後,最終選擇了kylin作為我們的報表計算引擎,一方面是sql支持度相對來說比其他系統好比如精確distinct功能,一方面是和hadoop的幾個組件集成得非常好,tidb和已有hadoop組件集成得不大好,需要重新搭建集群代價很大。還有就是基於java開發很符合團隊的技能特點,可以根據業務特點定製我們自己的版本。

三、 數據分鐘級延遲問題解決(canal+flume+kafka)

選好了kylin這個報表計算引擎後,還需要解決的就是我們報表計算的數據延遲最大也要到分鐘級別,這個可以通過kylin的kafka數據源來實現,配置方式見下面的鏈接。

http://kylin.apache.org/cn/docs/tutorial/cube_streaming.html

但是使用kafka還有一個問題就是業務系統的數據怎麼實時的傳輸到kafka呢,之前都是在業務系統中編寫數據發送邏輯到消息隊列中,這種方式和業務系統耦合非常大,隨便改點邏輯都需要依賴於業務系統上版本週期很長,溝通成本很大。因此我們採取了用阿里巴巴開源的canal抓取mysql binlog的方式,實時的去抓取mysql的增刪改查數據,這種方式要開啟mysql的binlog。Canal項目的主頁:

https://github.com/alibaba/canal

有了canal抓取並解析binlog以後,還有一個問題要解決的是怎麼讓canal抓取到的數據可靠的傳輸到kafka中,基於canal和kafka的api自己開發的方式,成本很大,而且要考慮高可用,容錯,擴展性等問題,再者我們的時間和開發資源也非常有限,因此我們基於flume的接口開發了一個canal source,充分利用flume的靈活性,擴展性,高可用,負載均衡和容錯等特性,同時也可以和已有的source,channel和sink組件隨意組合。

這樣通過 canal+flume+kafka 和 kylin的streamingcube 特性,我們就很好的解決了數據分鐘級別的延遲問題。

四、 數據實時更新和刪除問題

下一個要解決的問題就是數據的更新和刪除的問題,這個我們是基於業務邏輯來解決的,當然我們在實現上會考慮好業務場景的通用性,每次更新和刪除數據我們都不會去修改原來的數據,而是往kafka中插入新的數據並標記這條數據是刪除,還是更新,並記錄前後值的變化,同時在接入層面儘可能對數據進行去重處理,降低後續cube構建和sql編寫的難度。

由於我們在數據層面和原來的變化了,因此我們還需要在sql層面進行改寫,當然改寫後的sql肯定要利用上kylin的預計算特性,否則查詢速度很慢。

在解決數據實時更新和刪除問題上,耗費了我們大量的時間,前後也討論過很多種方案,而且實現起來需要對kylin的預計算特性有深入的瞭解,對維度設計要利用kylin的特性充分的進行精簡,否則會走彎路。

下面是我們的model和cube界面:

kylin+SuperSet實現實時大數據報表的快速開發

五、 併發查詢問題

接下來就是併發查詢的問題了,由於kylin本身就帶有cache特性,負載均衡而且採用的是預計算模式,因此應付併發上很好辦,負載均衡這一塊開始準備用nginx做負載均衡,後來覺得自己維護還是很麻煩,而且我們其他系統已經在使用阿里的SLB做負載均衡了,因此最終我們還是用SLB來做負載均衡。

最終我們做到了能夠將數據在5分鐘以內延遲下,支持實時的刪除和更新操作,對報表各個維度的數據進行查詢,彙總在1秒以內返回,明細在1到3秒內返回。

六、 使用superset報表開發方式

最後要解決的一個問題就是開發效率的問題了,之前我們的報表開發後臺首先要手工編寫大量的sql,然後使用spring和mybatis編寫大量的業務邏輯,並通過微服務的方式暴露接口,然後前端再根據接口,編寫前端展示代碼,而且移動端,電腦端都要寫一套。

這種方式開發週期長,耗費人力大,而且工作挑戰不大也比較枯燥,大家都很痛苦,產品等得痛苦,開發開發得痛苦。

因此我們調研了幾個前端的工具,後來發現了airbnb開源的superset這個好東西,操作簡單,圖表美觀,而且單表不支持的情況可以通過自定義sql來支持。最關鍵的是kylin對它進行了很好的集成,鏈接如下:

http://kylin.apache.org/blog/2018/01/01/kylin-and-superset/

還有一個關鍵點是superset的圖表可以通過iframe嵌入到網頁中數據不是靜態的而是隨時更新的,還支持在電腦端和手機端展示,對數據和圖表的權限控制也做得非常到位。基本滿足了自助開發,然後嵌入到頁面中展示的要求,可以大大節省我們的報表開發週期和開發工作量,甚至可以做到讓產品自助拖拽式開發。

Superset Kylin數據源配置:

kylin+SuperSet實現實時大數據報表的快速開發

圖表開發:

kylin+SuperSet實現實時大數據報表的快速開發

Iframe嵌入:

kylin+SuperSet實現實時大數據報表的快速開發

七、 最終的架構

kylin+SuperSet實現實時大數據報表的快速開發

八、 一些實現細節

  1. canal 主備切換的時候數據會重複,這個問題需要在接入層面或者在canal層面注意,我們是在接入層面監測到切換後對最近數據進行實時去重(自己編寫flume source帶去重邏輯,會緩存一個可配置時間段的數據,因為canal切換很快所以不需要緩存很長時間,而且用storm裡面的timecachmap不會影響到性能)。
  2. kylin不支持hadoop和habse的高版本,之前我嘗試把我們的集群升級到了hdp3.0版本(hive3.1,hadoop3.0,hbase2.1),也嘗試修改kylin源碼來適配高版本,但是改到後面發現工作量非常大,時間來不及只好又把集群回退到了hdp2.6.4版本,後面把kylin修改好以後再升級集群。
  3. 查詢一定要利用kylin的預計算特性否則時間會很長,尤其是子查詢很可能會導致利用不上預計算特性。
  4. 設計cube的時候維度一定要儘量精簡,cube計算時可根據數據量情況選擇不同算法,rowkey可根據查詢場景做一些優化。
  5. Kylin的distinct有精確distinct和非精確的,精確的計算要佔用非常大的內存。
  6. steaming表是不能和lookup表進行join的。
  7. superset支持iframe嵌入要修改一些配置權限配置和跨站訪問配置,否則不能展示或者要登錄。

跨站訪問修改這個配置:

HTTP_HEADERS = {'X-Frame-Options': ' '}

免登錄訪問加入以下配置:

PUBLIC_ROLE_LIKE_GAMMA = True

Public 角色的permissions裡把以下三個加上

can explore on Superset

can explore json on Superset

all database access on all_database_access

8.使用多個kylin實例的時候,會存在多臺服務器上session信息不一致問題,,可以通過配置Kylin將Session信息保存到Redis中(或MySQL、MemCache等),實現多個Kylin實例的Session共享。

九、 寫在後面

時間倉促,整體方案寫出來了,具體細節和遇到的問題寫得不夠詳細或者寫得不對的對方,有需要進一步瞭解的可以留言交流。後續報表這一塊我們會進一步做到自定義報表到時的維度挑戰是一個更大的問題,肯定需要進一步的優化當前方案。


分享到:


相關文章: