導讀:本文主要介紹京東在構建OLAP從無到有各環節考慮的重點,由需求場景出發,剖析當前存在的問題,並提供解決方案,最後介紹OLAP的發展過程。
▌需求場景
1. 京東資料入口
① 業務資料:訂單
京東作為一家電商企業,擁有自營商品銷售平臺和全鏈路物流通道。首先第一資料入口就是訂單,針對不同訂單進行多維度分析,比如:對訂單分析、對店鋪分析、對商品品類分析等等。
展開對訂單維度來說,因為我們作為電商,訂單是非常重要的一個維度分析和資料支撐,所以常結合訂單SKU,計算品類下單轉化率。
② 行為資料:點選和搜尋
使用者在京東商城的操作,比如點選和搜尋,我們會將使用者的這些行為結合訂單資訊,來做一些分析,比如分析商品的熱銷和滯銷程度,以及轉化情況,最常見的就是漏斗分析,來計算轉化率。
③ 廣告和推薦
基於使用者下單情況,我們會推送廣告和推薦給到使用者,然後進行計算,分析廣告觸達相關情況。
④ 監控指標
對於監控指標,是我們一個巨大的場景,因為在我們這裡,除了使用者行為資料,還有很多運維的資料也需要管理起來。
2. 京東資料出口
京東的資料出口,主要分類兩大類:離線和實時
① 離線
- 月報和週報
典型離線場景:財務報表經常需要月報週報。
- 機器學習
會用到大量的一些訓練資料,這些資料的生成也會用到OLAP的一些特性來把資料進行分析,產生一些訓練的資料。
② 實時
- 互動式查詢
非研發同事,比如營運分析人員,經常需要臨時查詢業務資料,比如查詢最近一週訂單的彙總以及明細資料,對這些資料進行分析,輔助決策。
- 實時大屏展示
平臺做大促或者實時監控運營情況,會依照大屏的指標,實時動態調整資源。比如營銷策略、廣告費投入、供應鏈庫存。尤其重要的是,在大促銷的時候,可以進行動態資源的調整,比如車輛資源排程、根據促銷效果決策活動是否需要進行調整等。
▌問題與解決方案
以上是京東的部分業務場景,和大多數闡述資料架構不同,我們本次將資料搭建的過程分為4個方面:資料怎麼寫進來;寫進來以後怎麼進行儲存;儲存以後又怎麼進行取用;最後是如何管理前3個環節。
1. 寫
① 資料來源及資料結構多樣性
現狀:
資料來源來源多樣化:檔案系統(本地檔案&分散式系統檔案)& MQ
- 本地檔案,比如說伺服器本地的資料,直接匯入進來
- 資料量比較大時,在使用者本地存不了這麼大的資料量,會將資料儲存在HDFS上
- Kafka或者MQ資料,上游將產生的資料直接儲存到訊息佇列中,在京東內部,這種MQ的系統有多個,但是我們需要統一進行接入
- 資料結構的多樣化,最常見:CSV、TSV、JSON、AVRO、PARQUET、BINLOG等
問題:
多種資料來源及資料型別,對於開發人員來說,進行資料分析的成本相對比較高,我們希望分析人員,只需要專注於業務邏輯本身,直接進行SQL查詢,而無需關心資料來源。
解決方案:
建立統一匯入資料服務,將多樣化的資料來源和資料型別進行封裝,透過給使用者配置許可權,使用者只需要在視覺化介面直接進行操作,即可完成資料的匯入操作,具體的操作也是比較簡單,以MQ資料來源舉例:
- 選擇資料來源的topic
- 指定匯入的目標源
- 選擇資料格式
- 選擇對應的資料欄位型別等等
② 資料的時效性
現狀:
實時的資料需要實時進行計算和展示;離線的資料,可以定時的推送並計算一次,對時效的要求比較低。
問題:
如何保證實時和離線資料的時效性,且不會相互影響?
解決方案:
對實時叢集和離線叢集進行物理隔離,防止互相干擾,這樣做的好處有:
實時和離線對於資源的需求不同,實時資料寫入非常頻繁,而離線的資料只是在指定執行的時間點比較多,區分開便於管理。
③ 資料的更新和刪除
問題:
對於OLAP的架構來說,如何做到既要查詢搜尋又要更新呢?
解決方案:
- 資料更新,採用覆蓋寫的方案。以訂單為例,使用者下了一個訂單1,此時下單狀態為1,後面使用者進行了支付操作,訂單狀態為2,那麼我們會重新推送一條全量的資料,只是狀態的欄位值發生看變化。
- 資料刪除,採用刪除分割槽然後重新匯入這個分割槽資料,或者採用版本管理方式,因為透過新版本的資料會覆蓋原來的版本,起到刪除的作用。
③ 高吞吐
問題:
以京東現在的體量,每天的資料是很大的,如何解決高吞吐問題呢?
解決方案:
機房配置萬兆網路,另外對於實時場景,配備SSD;離線場景,配備HDD。
2. 存
① 海量資料
問題:
京東的資料,TB資料量是非常常見的,有些時候會達到PB級別,那麼採用單機的方式肯定是行不通的,那麼如何解決資料儲存的問題呢?
解決方案:
- 採用分散式解決大規模資料的問題。
- 為了提高效率,採用了列式儲存,對後續指標的計算效率也有提升,其實在OLAP的架構中,大多數都是列式儲存。
- 採用不同類別的壓縮方式,比如snappy等。
② 容錯性
問題:
資料現在是科技類企業非常重要的資產,那麼如何保障資料的安全性性呢?
解決方案:
其一:多副本的容錯方式,我們的OLAP採用三副本的方式,所以其中1個或2個副本損壞或遷移時做擴容都比較容易處理。
其二:RAID獨立磁碟冗餘陣列(RAID,redundant array of independent disks),因為磁碟金屬機器經常會壞,加上有一些機器過儲存在損壞的風險,所以我們也透過raid解決一部分資料容錯性的問題,防止磁碟壞掉之後整個機器不能提供服務的情況。
③ 一致性
解決方案:
解決資料的一致性的問題,需要使用到分散式協調和本地事務機制。
- 分散式協調,比如zookeeper
- 本地事務機制:對於本地的提交,是否透過事務來保證資料的一致性
透過兩者的結合,來實現資料的一致性。
3. 讀
① 查詢速度
問題:
資料儲存到系統中以後,如何高效的進行取用呢?
解決方案:
- 通用方式,資料進行分割槽分片,在很多場景,對資料的分析都是按照時間進行分割槽,分割槽以後,再進行分片或者分桶。 比如:訂單資訊,我們可能按天查詢,那麼就可以按照實際日期進行分割槽;比如,儲存10年的資料,不可能全部查詢,我們按照統計則按月進行分割槽。
- 預聚合,提前進行預計算,減少一次性計算的資料量,提高效能。
- 索引,大部分場景下會使用索引,比如做明細查詢,可能會到hash索引、betree、範圍查詢或者倒排。
- 物化檢視,其實和預聚合的功能類似,資料進入到物化檢視中時,提前進行一些預計算。
② 易用性
問題:
如何實現系統的易用性?
解決方案:
- 需要OLAP系統相容JDBC和ODBC,同時支援標準的SQL。
- 提供介面化的操作,這種方式可以避免所有的運營分析人員都具備Mysql等資料庫的環境,可以直接登入圖形化介面進行查詢的操作。
③ QPS
問題:
如何提高QPS?
解決方案:
- 快取,使用doris時,增加比如partitioncache,或者結果級快取,或者分割槽快取機制來提升查詢效率。
- 多副本,設定多副本的方式,透過犧牲部分儲存空間,來提升QPS,但是這個效果有限。
- 提升機器的規模。
4. 管理
現狀:
早期我們碰到磁碟壞了,搞得手忙腳亂,替換磁碟或者是下機器操作時間很長,而且這個操作完成之後還涉及重新平衡資料或者資料遷移,這個過程非常麻煩。
問題:
如何降低運維成本?
解決方案:
- 建設監控和報警機制,進行提前預防。
- 最佳化節點的下線,在京東系統中,有兩種方式: 方式1:透過黑名單的方式,如果監控到某個節點經常不健康,我們會把它納入黑名單,並將他踢下線了。 方式2:透過指令碼操作,但是從最開始我們需要替換一個節點,估計從發現到替換完成得三小時,現在透過一些比較自動化的東西,現在大概十分鐘左右能做到一個節點的替換。
▌發展歷程
1.0時代
1.0時代的場景比較少,資料量也比較少,主要是訂單相關的一些資料,分析透過關係型資料庫就能搞定,比如說oracle或者mysql。
可透過資料儲備同步到備庫做分析,或者mysql一個是slave庫,主庫做一些利用線上業務,然後備庫對存貨的一些分析和查詢。
2.0時代
到了2.0場景,不再是簡單處理訂單問題,還要處理物流、供應鏈、客服、支付等等場景。
場景大增,資料量也爆發式增長,從原來的G到現在的TB甚至PB級別。傳統關係性資料庫,已經不能滿足需求了。
這個時候我們開始搭建了離線數倉,在數倉中進行分析,主要用Hive和Spark進行計算,資料都是T-1,臨時查詢資料的體驗非常差,需要耗時分鐘級別且還是昨天的資料。
3.0時代
為提升查詢資料的速度和資料的時效性,開始做實時查詢。我們現在使用統一OLAP服務,從最開始使用Kylin處理一些離線的業務,到現在我們用了doris和clickhouse結合起來,同時處理實時和離線,統一服務介面,對使用者和開發人員開放。
同時針對不同的業務,提供不同的計算引擎,我們現在提供一個整體打包解決方案,業務只需要在OLAP的服務上,進行統一部署到資料技術平臺即可,大大減少了開發成本。
未來規劃
① 管理平臺最佳化
- ClickHouse的動態伸縮。
- 智慧化運維。智慧最佳化節點上下線或者資料均衡這些方面的工作。主要想要透過減少人工干預操作,降低時間的浪費。在京東的系統中,現在擁有上千臺的伺服器,如果一直由人工來處理的話,那麼成本非常高。
② 最佳化查詢速度
- 最佳化實時計算快取。在doris中,使用partitioncacahe或者sqlcache在離線場景中比較有效,後續將考慮在實時計算中引入快取進行最佳化。
- 索引智慧化管理。索引的引擎有非常多種,如果需要開發人員瞭解所有的引擎,學習成本是比較高的,我們能不能做成智慧化的索引引擎呢?這樣的話使用者不需要再去關心類似的一個索引怎麼建的問題,而是我們在透過使用者的一些查詢行為分析,自動的來給他做索引的建立,這樣簡化工作成本,讓開發人員有更多的心思去做好運營和分析。
▌問答環節
Q1:請問老師貴司有用過druid引擎嗎?
A1:沒有,我們調研發現,第一,druid對sql的支援不是很友好;第二,druid擅長於持續性的資料場景,但是京東訂單是一個頻繁發生狀態變化的一個場景,它是不太好處理的,所以當時我們也沒有選druid。
Q2:clickhouse和doris如何根據業務場景選型,有哪些坑?
A2:
第一,查詢效能:在查詢表不多即沒有太多表關聯情況下,clickhouse查詢速度比較快,但是在做大表關聯查詢時,doris的效能會好於clickhouse。
第二,QPS:clickhouse是在極限使用CPU的效能,但是doris的QPS效能在某些場景下會比clickhouse好。
第三,運維成本:doris的運維成本會小於clickhouse,至少現在對我們來看,因為它會有節點自動上下線擴容收容會很方便,但是clickhouse做這個方面比較麻煩。
第四,資料更新:clickhouse資料更新的引擎有三種,使用者在使用的時候比較麻煩,但是doris,它直接進行資料覆蓋,就能做到一個更新,操作更方便。
Q3:doris和clickhouse是自動選擇,還是需要使用者自己去選,如果是自動選的話,識別機制是什麼樣的?
A3:目前還沒有做到自動選。當前先整體提供解決方案,我們為使用者提供技術支撐,未來可能會想著如何去打通統一化,因為它的模型建立不太一樣,它的sql是有差異的。
Q4:資料接入CK方面,京東目前是什麼樣的方案?
A4:目前有兩條路線。
一個是使用者自己業務側接入,因為有些歷史原因,使用者他已經用了很久的clickhouse,他自己有比較成熟的一套接入系統。
一個是使用clickhouse來接入,不管是從離線還是從kafka中,這種方式是我們在平臺側,在平臺側開發了統一的OLAP服務,使用者可以上面操作。就如前面所說,使用者選擇資料來源,再選一個目標源,點選它執行匯入,就可以完成。
今天的分享就到這裡,謝謝大家。
分享嘉賓:
李陽
京東 | 資深研發工程師
京東資深研發工程師,擁有超過10年研發經驗,擅長OLAP相關服務研發及分散式系統設計。
分享嘉賓:李陽 京東 資深研發工程師
編輯整理:連志鵬
出品社群:DataFunTalk