作者簡介:陶王飛,58快狗打車資深大數據開發工程師,長期專注於實時計算和數據應用。
前言
數據的實時化是最近幾年數據行業很重要的趨勢,我們在去年底也建立起新一代的實時數倉,但是在數據應用上一直沒有取得很大的突破,我們希望實時數倉不僅僅是支撐大屏、核心實時報表、個別實時應用等簡單的場景,希望更大的發揮實時數倉的價值,更方便、更快速、更大規模的對外提供數據服務是我們一直思考的問題。
基於阿里雲Hoogres 所建設的統一數據服務,在一定程度上幫助我們實現了這個目標。
通過這套系統整合離線和實時數據,對外提供統一的數據服務,目前已經支撐了實時報表、用戶司機實時標籤系統,push系統、運力調度、營銷活動實時監控、公司內部的客服後臺系統等幾十個數據需求,實現實時用戶精細化運營。在數據易用性、交付週期、數據的準確性上都比以往有了很大的提升。
公司介紹
快狗打車(原58速運)是一家拉貨的短途貨運打車平臺,解決比如搬家、買大傢俱家電、買各種大件、批發市場商家發貨等場景對貨車的需求,同時為藍領司機師傅提供一個可以接單的平臺,也就是貨運版的“滴滴”,來實現幫助1000w人解決就業問題的目標。
數據服務的發展背景
原始階段
在早期,我們的數據服務常見的場景,根據每一個需求加工數據。
如果是離線需求,通過Hive加工數據,使用Sqoop將結果數據導出到業務提供的MySQL表中,供業務查詢。
如果是實時需求,開發一個實時項目將處理的數據落表或者發送MQ(Kafka或DMQ(自研組件)),提供到業務方使用。
這種從底到頂的煙囪式開發,導致的開發成本高、邏輯分散 、數據不一致、管理維護困難等問題,隨著業務的發展,已經難以接受。
1.0階段
18年我們基於Spark Streaming 和Spark SQL所實現的實時數倉,對落地表進行分層、建設大寬表,將計算好的數據統一存放到HBase中,使用ES給HBase做索引,並仿照SQL接口設計了一個較為簡單的查詢API,對外提供統一的查詢接口。所有需要實時數據的任務都可以從這套系統獲取數據,不再根據具體需求做定製化開發。
這種方式,在一定程度上降低了開發成本,增加了數據的複用、緩解了數據不一致問題,並且應用在多個實時程序上。但是因為計算層面Spark Streaming 狀態支持有限很難做較複雜計算、開發修改成本高。存儲和服務層面,通過接口查詢在HBase中的數據,只能做明細查詢和簡單聚合查詢,靈活性不足,能對外提供的功能有限,同時也沒有能解決針對離線數據需求的問題,所以大部分應用主要是在部門內,為部門內提效。
2.0階段
在去年底實現的基於Blink的實時數倉,藉助於Blink SQL的實時ETL能力,重新設計了實時數倉的數據模型,完善了層級劃分和主題建設,能對外提供的數據比之前多得多。
在存儲層,我們選擇有較好實時OLAP性能的阿里雲AnalyticDB MySQL(下稱ADB),和開源Doris類似,接口層面都是兼容MySQL,對於一些不是太複雜的OLAP查詢,可以在秒級甚至亞秒級返回結果。但是由於ADB並不是太好的實時寫入性能、存儲成本昂貴以及一些內部原因,我們將一部分查詢場景簡單、數據量大、查詢QPS特別高的表輸出到HBase中,使用ES做索引。
底層存儲的割裂,只能在數據服務層做統一。為此我們設計了一套查詢接口,無論數據存放在ADB、HBase、MYSQL、Maxcompute中,都可以通過接口的SQL查詢出來。但是接口層並沒有完全屏蔽底層存儲,要根據數據存儲位置不同,寫不同的查詢SQL。不同存儲之間,也不能做跨庫join,在使用上還是有很多的侷限性。雖然承接了一些數據需求,但是這些侷限還是約束了不能更大規模的推廣,我們希望提供給到用戶的是一個使用起來足夠簡單、豐富的數據服務。
3.0 階段
底層存儲的不一致導致的一系列問題一直困擾著我們 ,期望有一種引擎,具有幫助我們統一實時數據存儲的能力。
我們是在Hologres(下面稱Holo) 剛剛商業化的時候注意到Holo的,Holo提出的HSAP概念統一了服務的點查詢和實時OLAP查詢,在存儲上也沒有ADB翻倍厲害的情況。通過一週多的測試、對Holo的系統架構有了一定了解之後,明確了預期收穫、風險點、成本等因素後,寫了一篇Holo的測試文章之後,將實時數倉的數據存儲全部遷移到Holo。
同時基於Holo重新修改了數據服務接口,由於統一的數據存儲、更完善的數據建設、以及Holo很強的實時OLAP能力、統一的數據服務,我們的需求交付能力相比以往有了很大的提升。很多以往要做幾天的需求,現在只需要配置一條SQL,效率的提升是巨大的。系統上線兩個月,接到了很多外部數據需求,目前每天請求百萬次,高峰期實時OLAP 查詢QPS上百(和OLTP的QPS不可比,可以想象1s向Hive提交100個查詢),大部分週期查詢平均耗時幾十毫秒、兩三百毫秒,很少有超過1s的。單個週期查詢最大耗時很少有超過1s。雖然從請求量上看,並不是太大,但是考慮到公司體量和我們上線的時間,這個數據還是很可觀的。目前公司新上的實時數據需求基本上都是在使用這套數據服務。
Hologres簡介
下面是個人在使用Hologres過程中結合官網資料對Hologres的理解:
阿里雲官網對Hologres 的介紹是:交互式分析(Hologres)是一款兼容PostgreSQL協議的實時交互式分析產品,與大數據生態無縫打通,支持對PB級數據進行高併發、低延時的分析處理。 是基於阿里提出的HSAP(hybrid serving and analytical processing)理念而設計的一種ROLAP系統。相對於HTAP(Hybrid transaction/analytical processing)來說,HSAP弱化了對事務的要求,追求更強的性能和更快的響應時間。
一般來說,為了應對不同的數據使用場景,我們會將高QPS的點查請求的數據存放在kv存儲中,比如說Redis、HBase、Tair等系統中,分析型的數據存放在Druid、Clickhouse、Doris等系統中,有些場景還會使用ES、MySQL等。比如說下圖美團到店的實時數倉存儲分層圖,就是目前常見的實時數倉存儲架構。
HSAP理念的主要目標,將以上的這些存儲統一成一種存儲引擎,主要分為兩種場景:點查(point query)和OLAP的查詢,Holo的點查詢實現很類似於HBase,使用很小的資源就可以支撐起很高的QPS,實時OLAP查詢則是基於MPP的實時交互式查詢,針對兩種場景分別使用了行存和列存兩種不同的存儲格式。
在存儲上,Hologres採取雲原生設計,存儲計算分離,數據存儲在阿里雲分佈式文件系統pangu中(類比開源HDFS),方便按需單獨擴展計算或者存儲,讀寫分離的設計,以同時支持高併發讀取和高吞吐的寫入。
Holo的數據寫入也是使用LSM tree ,寫入即可見,定期刷新,但是碎片文件會分為多個級別。弱化一致性,僅支持原子寫和Read-your-writes以實現高吞吐和低延遲的讀取和寫入。
宣傳的是寫入可以達到數億的TPS,比起ADB數萬的TPS高出了很多。我們在壓測時,沒有遇到寫入瓶頸。
在查詢上,Hologres使用LBS做查詢負載均衡,查詢請求發送到Hologres FE,做查詢優化,生成並行化的很多片段的執行計算DAG,提交給Blackhole執行。
Holo設計了稱為HOS的用戶態線程調度系統,執行上下文之間的切換成本幾乎忽略不計,同時可以實現更高的並行。Holo的調度策略中,還考慮到大型分析查詢不應阻止對低敏感的服務查詢,此處的服務查詢也就是點查詢(point query)。和Clickhouse、Doris底層一樣,Holo也是使用C++實現,使用native方法,以及向量化引擎等提供更好的性能。
我們在實際的使用中,還發現Holo的硬掃的能力很強,幾百萬級別的數據,不需要要索引就很快返回。
另外,Holo還提供了多種索引,可以手動添加,比如聚簇索引、分段索引、bitmap索引、字典索引等等。要注意的是,除bitmap和字典索引,其他索引都需要在建表時指定,不能修改。
如果對Holo的實現感興趣,文末附有Holo發表在vldb上的論文鏈接。
場景實踐
下面是58快狗打車基於Hologres的場景架構圖,主要的架構思路是:
- 實時數據由Blink做實時ETL,寫入Hologres。
- 使用Hologres統一實時數據存儲。
- 基於Hologres和離線倉庫之上,提供統一數據服務,對接業務層的各種報表、分析系統等
可以看到,整個架構主要有主要分為3個部分:數據服務、實時數倉和數據存儲。下面將會就這3個部分仔細講訴。
1.數據服務
主要基於Holo,我們做了一套對外提供的統一數據服務。從上面的架構圖可以看到,用戶提交的查詢請求到統一數據服務接口,經過安全校驗解析、別名映射後,提交到Holo等執行。
使用Holo為我們解決了兩個半問題:
- 第一,相對於ADB,Holo很大程度上降低了存儲的成本。
- 第二,Holo解決了數據存儲不統一的問題,同時提供了高性能的實時OLAP能力。
- 第三:Holo提供了無需搬移數據,加速查詢離線數據的功能,但是由於是以資源消耗為代價,性能會比直接查詢Holo內部表差10倍,同時有較多的限制(例如單次query命中的數據量為200G、分區限制512個等)。所以,算是解決了半個問題。
然後,我們在數據服務接口做了更進一步的統一,數據服務接口以Holo為主,同時兼容一些歷史上存放在MySQL中的任務。對於特別複雜,同時對響應時長不敏感的查詢,也可以使用數據服務接口直接查詢離線數據。所以,我們希望數據服務接口是作為整個數據部門統一的數據服務,統一對外的所有數據接口。
Blink任務修改後,可能會導致之前的狀態不可用,狀態清空,直接修改上線落表數據正確性會有影響。同時Holo大部分索引需要在建表時指定,如果一開始表設計不合理, 或者之前的表設計不再滿足現有需求。這時候物理表如果被寫入很多任務中,是很難修改的。所以我們設計了別名映射的mapping系統,mapping中會指定物理表,庫名、連接等信息,用戶只需要知道別名就可以使用,無需關心具體位置,同時別名是相對固定的。Blink修改任務時,可以新建任務寫到新建表,待補齊數據,藉助推送系統,一鍵切換,立即生效,所有的查詢馬上切換到新物理表,線上業務無感知,類似於一個主備切換的過程。另外如果一旦發生較大改動,也可以在我們這邊控制。
服務保障方面,通過監控每次的查詢,建立查詢異常報警機制,監控整體服務的穩定性,對於不合理查詢可以及時提供修改意見,保障整體服務持續穩定和高效。
2.實時數倉
實時數倉原始數據源來自日誌數據和MySQL binlog訂閱,我們開發了數據訂閱平臺,通過平臺配置,將數據統一發送到Kafka中,使用Blink SQL做實時ETL,數據的輸出主要有兩種,表(Holo)和MQ(Kafka)。
在建模上,參考了離線的已有的數據模型,但是又不完全一樣,主要體現在分層和表字段設計,這是因為離線、實時數據的本身的屬性不同。離線每天拉取一次,一次性計算,跑一次,當天都可以一直使用,同時離線計算能力強,所以可以建設高內聚低耦合複雜的數據模型 ,使用邏輯下沉、複雜模型、完善分層和更完整維度抽象等方式,來更好的保障數據一致性和數據易用性。對外提供的也是聚合數據為主,明細為輔。
但是實時任務是24小時運行,更高的層級抽象意味著使用起來不靈活、鏈路長穩定性差、維護代價大、時效性差等。
所以,相較於離線,實時的層級更輕。很多公司在實時數倉會有較多的維度退化,我們基於Holo較好的join 性能,在一定程度上減少維度退化的設計,提高了靈活性和開發效率。
更重要的是,藉助於Holo很好的實時OLAP性能,很多任務可以實時OLAP 現算,而不用針對具體任務加工具體的應用層數據,使用實時Join也不用做大寬表,這對效率的提升是巨大的。以前,很多實時需求需要專門寫實時加工任務,而且如果需求修改,修改實時任務的代價也是很大的,整個開發週期好幾天,現在可能使用統一數據服務接口,基於我們體系的數據建設,可能幾分鐘就可以交付了。
當然,也並不能過度的依賴於實時OLAP,在我們的最終實踐上,為了更高的效率和一定的數據一致性。我們預處理了部分比較固化的計算在聚合層,對外提供的數據,優先使用固化的聚合層,對於比較靈活的查詢和不好固化的統計,使用明細層,總體來說,以明細為主,需求交付效率有較大提升。
可能在很多公司,實時數倉更多應用在實時報表等運營實時監控等場景,對於風控等場景,會有獨立的數據流程。我們認為實時數倉的優勢在於,數據建設完整、開發效率高、對聚合類數據有不可替代的優勢,雖然有數據處理鏈路長的劣勢,如果僅僅是用在實時報表有一點浪費。 所以,我們雖然在大量的推廣實時數據應用,但是一直是有所節制,場景主要限制在一些內部需求或者靈敏度不是特別高的業務場景,比如說我們準備做的,將取消訂單等相關的信息、用戶統計數據推送到客服系統等需求。對於個別像反作弊之類的線上業務,也會限制只提供低層的Kafka基礎數據。
3.數據存儲
Lambda架構不僅會導致了計算的冗餘,也導致了存儲的冗餘。而Kappa架構在目前的技術下,過於理想化。行業內還很少聽到有完全的Kappa架構落地的案例,目前主要是以Lambda為主,個別地方會做調整優化的方式。
計算的冗餘其實比較難以解決,雖然這幾年實時計算技術發展迅速,但是實時計算還遠遠不能完全替代掉離線程度,實時任務修改的複雜度也遠遠高於離線任務。Flink的流批一體的方案,使用一套代碼同時運行離線和實時計算的方案,目前也是在初期發展中,雖然沒有用過,但是能想到應該有很多困難的地方。
相對而言,存儲的一致性能做的事情更多。不考慮實際,理想情況下,離線和實時的數據都存儲在一個存儲引擎中,同時能跑批任務,也具有對外提供數據服務的能力。
Holo在這個方向上往前走了一步,除了解決了實時數倉存儲統一的問題,還提供了離線外表的功能,可以將離線表作為Holo的外部表,藉助於Holo比較強大的硬掃能力,來加快離線數據的查詢,使用一套系統就能同時查詢離線和實時的數據。上面也講過,這種硬掃是以大量的磁盤IO和CPU資源為代價的,所以會有較多的限制,比如說為了更好的性能,對於外表的分區數量和MaxCompute數據量有一定的約束。這種做法可以理解為一種冷數據的處理,官方給的字眼是 ”離線加速“。
在實際使用中,我們測試對2億數據的點查大約在2s左右,官方給到的數據是,相比於內部表,外部表性能會差10倍,可以滿足一些對時效要求不高、查詢頻率不高的數據需求,在高時效性的任務這種性能表現可能不能滿足需求,可以通過導入內表來解決。
具體到我們的實踐上,對於一部分需要離線數據、對時效性要求不是特別高同時離線查詢分鐘級的響應時長不能滿足、查詢頻率不高的需求,我們會以外部表的形式對外提供,語法還是和Holo內表相同的語法,對於需要一部分離線數據、同時時效性要求很高、查詢頻率很高的查詢場景,我們選擇將一部分離線數據導入到Holo中,有時會和實時對應任務放在同一個表中,對外提供服務,這種做法事實上造成數據冗餘,是一種妥協。
總的來說,Holo 並沒有完全解決實時和離線統一存儲的問題,但是往前做了一些探索性的工作。目前,Holo和離線Maxcompute開發團隊已經融合,期待下一步看到更多的融合。
業務價值
總結來講,從業務開始接觸Hologres並上線,在實戰場景中帶來的主要優勢有以下幾點:
1.統一了實時存儲,解決了實時數據孤島等問題
2.加速離線數據查詢,簡單查詢可以數秒返回,但還是會有一些使用限制,需要根據實際使用場景來做調整。
3.數據模型的變化,一定程度上減少了以往實時過多的維度冗餘,幫助我們建設更低耦合的實時數倉
4.加速了需求的交付,不需要做數據開發的需求,甚至只需要十幾分鍾就能交付任務,大大的提升了效率。交付的提升,我們可以將數據更大範圍的推廣。
同時,Holo作為新生事物,基於新型的架構設計,提供了非常強大的性能。我們在測試和使用的過程中,也發現了一些不足之處,也希望這些不足/訴求能幫助Holo走得更快更遠:
1)目前Holo升級配置和版本需要停服,需要停服幾分鐘的時間,需要提前有準備,後續版本會解決。
2)Holo gis 功能目前不支持索引,在大量數據下效率較低,我們測試2億數據下地理距離查詢大約幾秒鐘。目前索引功能開發中。
3)Holo支持分區子表,有點類似於Hive的分區表,比較適合增量數據,在數據刪除和查詢上有一定的優勢。但是目前每個分區子表必須手動提前建表,手動刪除,當前的解決辦法是通過調度任務來自動建表,期待Holo團隊能夠實現這個功能
4)資源隔離,在我們調研測試中,就發現高吞吐查詢會影響到對延時要求高的小查詢,在後來的實測中,發現即使是大查詢沒有完全跑滿資源的情況,也會影響到小查詢的響應時長。這個問題很早就和Holo溝通過,算是一個比較普遍的問題,開源引擎也會遇到,有些公司會使用獨立集群對不同查詢做物理隔離。Holo也已經明確給答覆後面會徹底解決這個問題。由於我們很早就意識到這個問題,所以從一開始的整體設計就有預防和控制,目前還好。
5)在測試使用過程中,還發現一些小bug ,作為新產品,我們在享受便利的同時,也肯定會有一些不足的地方,我們也願意同Holo一起成長。
未來規劃
Holo幫助我們實現在實時數據數據存儲方面,只使用一套存儲,在一定程度上緩解了數據不一致的問題,算是前進了一大步。
但是更遠期來說,我們希望在未來可以徹底解決數據一致的問題,真正的讓一份數據只存儲在一個地方。
具體到眼前,我們的主要精力在系統的穩定性、規範化沉澱、工具提效、並通過需求來完善我們的數據服務體系,更好的易用性、更強的穩定性、更快的交付週期,會更多的在內部的建設上。
參考
Alibaba Hologres: A Cloud-Native Service for Hybrid Serving/Analytical Processing:http://www.vldb.org/pvldb/vol13/p3272-jiang.pdf