天天看點

正确設計Hologres實時數倉,性能提升10倍+背景11月1日現場還原問題定位和優化手段優化後業務效果後續規劃

概要:天貓雙11對于零售通團隊來說也是全年最大的一場戰役,資料響應需要更實時,但也會相應增加更多的個性化名額,業務面臨的挑戰也會更大。本文将會講述阿裡巴巴零售通資料平台如何優化Hologres實時數倉,達到性能提升10倍+的效果,完美支撐雙11營銷活動、實時資料大屏等核心場景。也希望通過此文對Hologres新使用者起到一定的幫助作用,通過合理的數倉設計實作事半功倍的性能效果。

作者:

曹泰銘(潇銘) 阿裡巴巴資料技術産品部-B系資料業務-零售通資料-進階資料工程師

汪宇(旋宇) 阿裡巴巴資料技術産品部-B系資料業務-零售通資料-進階資料工程師

背景

阿裡巴巴零售通團隊是阿裡巴巴B2B事業群針對線下零售小店(便利店/小超市)推出的一個為城市社群零售店提供訂貨、物流、營銷、增值服務等的網際網路一站式進貨平台,實作網際網路對線下零售業的更新,同時也為有志于線上線下零售業的創業群體提供創業平台。

整個平台的架構圖如下所示,是一個流批分離且以離線為主的架構。零售通資料團隊負責對離線MaxCompute數倉和實時Flink數倉的建設和維護,對内部小二和外部生态夥伴提供決策支援,資料服務和資料産品建設。

因為Hologres與MaxCompute有着極好的相容性,并且能夠對MaxCompute毫秒級加速,财年初零售通資料團隊作為業務資料中台基于Hologres在業務上進行了大量的嘗試,包括實時數倉公共層,冷熱混合計算,查詢加速等場景,因為Hologres的加入,相同的需求量,以前的架構需要2天才能完成,而現在在2小時内就能完成,大大提升了開發效率,得到了研發們的一緻好評。

天貓雙11對于零售通團隊來說也是全年最大的一場戰役,資料響應需要更實時,但也會相應增加更多的個性化名額,業務面臨的挑戰也會更大。基于Hologres日常在業務的優秀表現,團隊也決定使用Hologres作為雙11核心開發産品,應用于雙11核心場景包括營銷活動中心,實時資料大屏等。

在10月份對全鍊路進行了幾次壓測,Hologres在100%壓測壓力下CPU和記憶體資源在100%線上徘徊,屬于壓線通過。本以為能順利通過大促考驗,但在2020-11-01這天,在大量查詢QPS和高并發的資料寫入峰值下,Hologres的RT延遲一度達到90秒,沒有達到預期。在Hologres團隊的緊急支援下,通過整體結構的調整以及相關性能調優,整體性能提升了10倍+,順利扛住2020-11-01的流量洪峰,同時通過此次調整也平穩的支援了整個雙11期間的流量洪峰(包括2020-11-11當天的波峰),為雙11劃下了圓滿句号。

事後我們針對整個事件做了全鍊路複盤,發現主要問題還是出在對于Hologres的原理了解不夠深入,包括技術原理、Table Group、表結構設計等,導緻某些用法還不是最優,這也導緻在實際業務場景中,Hologres的性能沒有發揮到最大化。

我們将會通過此文講訴阿裡巴巴零售通團隊如何根據業務場景合理的設計Hologres實時數倉,包括表結構、Table Group設計等,以到達更優的性能表現。也希望通過此文對Hologres新使用者起到一定的幫助作用,通過合理的資源利用實作事半功倍的性能效果。

11月1日現場還原

首先我們先來還原一下11月1日的現場回報,以更直覺的方式來看看當時Hologres承受的壓力和相關表現(注:監控頁面為Hologres在阿裡内部的監控頁面,與公有雲的監控頁面和名額項略有不同):

查詢QPS: 每秒完成query的數量,一般代表資料庫性能和壓力,23:30後的增長代表壓力負荷增長(業務方開始大量關注/查詢報表),00:15分的驟降代表性能降低,1點之後的降低代表業務水位下降。

查詢延遲(RT):15分左右陡升到25s,大概持續15分鐘;Hologres超負荷運作,性能下降。

CPU使用率:代表正在運轉的core數量。我們的執行個體有幾百個core用于計算,但在峰值嚴重超負載50%+;

Woker CPU使用率:Woker的CPU負載情況,和CPU使用率基本一緻,峰值超負載50%+。

這兩個名額代表大量Query将會無法及時處理,在隊列中等待,延遲将會較大增加,執行個體也有停擺的風險。

Blink寫入RPS:代表每秒實時資料的寫入量,0點是實時訂單寫入的峰值。當時有較多資料導入,對Worker産生較大的負荷,影響執行個體性能(比如RT,CPU使用率等),是以對部分blink寫入腳本采取緊急降級操作,峰值過後1:10恢複降級,産生第二波較大的寫入。

問題定位和優化手段

在Hologres團隊的幫助下,經過反複的排查,發現問題主要有以下幾個原因:

1)主要問題: Table Group&Shards數設定不合理,在高并發讀取和寫入峰值時,造成叢集資源浪費和性能下降。

零售通Hologres執行個體總計有幾百core的計算資源,幾TB的記憶體資源,和十幾TB的存儲資源。在執行個體建立後會根據執行個體規格生成預設數量的Table Group,然後每個Table Group會自動建立對應的Shard數(按照現有的規格,Shard數有300個),執行個體中存儲的表都會被預設分發至這些Shard中。

開發視角的Table Group和Shard

首先,先從開發者視角來了解一下Table Group和Shard的相關概念和原理:

在Hologres中,1個DB包含多個Table Group,每個Table Group包含多個Table,每個Table隻能屬于一個Table Group。一個Table Group唯一對應一組Shard,由這組Shard來負責其中表的資料存儲和查詢,其包含的Shard個數稱為Shard Count,Table Group一旦建立,Shard數不可調整。

一個Table Group擁有的Shard數量(即Shard Count,後同)是它的一個重要屬性。Shard數多的Table Group,其資料寫入和查詢分析處理可以得到更大的并行度,一定範圍内,增大Shard數可以加快資料寫入和查詢分析的速度,但Shard數也并非越多越好,更多Shard數需要更多的節點間通信資源、計算資源以及記憶體資源,在資源不滿足的時候,或者Query很小時可能會導緻适得其反的效果。

再結合具體的業務場景,當一個雙表Join的SQL執行時,按照現有Shard數,執行計劃會産生一個300*300 Shard的笛卡爾積(兩張表都被分散300份),這在shuffle階段對CPU和記憶體産生巨大的壓力,也就意味着需要更多的節點間通信資源、計算資源以及記憶體資源。除此之外,單表的資料随機分散到300個Shard的過程中容易出現資料傾斜的問題,如下圖所示

設定Table Group和Shard建議

零售通團隊的業務場景大都是資料量偏少、表大小也非常不均勻,對于保障的優先級也不一緻,是以上面将的所有表都放在一個300個Shard的Table Group中對實際業務并不适用,這就導緻當流量增大時,沒有辦法有效利用Hologres的Local Join能力,導緻CPU的開銷劇增。

正确的做法是按照使用場景、Join頻次、表大小,分裂設計成不同的Table Group中存放資料;一方面可以提升叢集性能提高計算速度,另一方面可以節省資源同時一定程度上實作資源合理配置設定隔離。

建立Table Group的原則:

  • 資料量過大,可建立獨立的較大Shard數的Table Group。當察覺寫入性能變慢 or 讀取200萬行一個Shard時建議建立Table Group;
  • 有大量資料量很小的表,可适當獨立出一個小Shard數的Table Group,減小Query啟動開銷;
  • 需要Join的表,盡量放在同一個Table Group;

為Table Group設定合理的Shard數:Shard數不是越大越好,過大的Shard數會造成資源的浪費&負載過高,過小的Shards數會導緻大資料量下讀寫性能不足以及不能抵擋較大的并發,下面也是經驗總結出來的Shard數設定(僅供參考,實際需要根據執行個體規格和業務要求來設定)

  • 查詢性能要求:若是業務對于查詢要求較高,Shard數的設定是表在SQL中掃描的分區範圍内的總行數的均值/200萬 = 1 Shard
  • 寫入性能需求:Shard數和資料寫入性能呈一定的正相關性,單個Shard的寫入能力是相對固定的,Shard越多,寫入的并發越多,寫入的吞吐越高。是以,如果表有較高RPS的寫入需求,需要增大Shard數。

具體完整的計算方法參考

如何選擇合适的Shard數

,也可以咨詢Hologres技術小哥。

Table Group重構設計

針對Table Group的設計,零售通對目前Hologres執行個體的期待是作為分析型OLAP實時資料庫,在财年不擴充資源的情況下對現有表和業務需求梳理後有以下訴求:

  • 存放數倉中公共明細層,公共彙總層,維表;并能對公共層較明細的資料進行快速分析&開發(Local Join);表單分區一般在數千萬行量級
  • 營銷活動分析資料産品的接口層存儲,表格行數較少一般在單分區3000行以下,表格數量較少(10個以下)的Local Join,并發較高但不太會和外部表格頻繁關聯
  • 經營管理中心資料産品的接口層存儲,表格行數較大,單分區可以到4億行,不需要in,一般做靈活多元度彙總,并發較低
  • 商品評估中心資料産品的接口層存儲,表格行數單分區千萬行,一般不需要Join,不需要彙總,但需要根據條件在where中進行明細篩選

最後決定設立4個Table Group:

  • 公共層TG: 存放維表,明細表,公共彙總表,Local Join 以及彙總,配置設定較多資源
  • 營銷+大屏TG:大屏及營銷活動應用,資料量較少,主要用于曆史對比,實時應用并發讀寫較大;采用20個Shard, 之前300個Shard是極大的資源浪費
  • 經營管理中心TG:經營管理中心各明細粒度表格,設定50個Shard
  • 商品or行業TG:存放商品和類目結果資料,設定40個Shard
    正确設計Hologres實時數倉,性能提升10倍+背景11月1日現場還原問題定位和優化手段優化後業務效果後續規劃

2)次要問題1:表結構設計

數倉建設中,最重要的一個環節就是合理的設計表結構,包括表的資料類型、表的索引等。尤其是索引,合理的索引設計将會提高幾倍甚至幾十倍的性能。通過重新梳理表結構,發現業務并沒有合理的設定表索引,這是導緻性能不符合預期的原因之一,于是我們也對索引進行了改造。值得注意的是,目前和資料布局有關的索引的建立必須要在建表初期完成,後面不可以更改/新增,獨立于資料布局的索引,比如bitmap,可以後面再按需修改。是以需要提前根據場景設計好表結構,以免做重複工作。

distribution_key
  • 如果建立了Primary Key索引(也是唯一性限制,用于資料更新),預設為distribution_key。Distribution_key如果為空,預設是随機分發。
  • 如果distribution_key設定不合理,資料會不均勻分布于Shard中。計算過程中會産生Redistribute Motion算子資料重新分布打散,帶來備援的網絡開銷。 如設定合理,則可以避免這種情況。
  • 通常設定關聯(Join)的列或Group by的列或分散更随機的列作為distribution_key,來盡量打散資料到不同的Shard。請注意這裡選擇單列作為distribution_key即可。
Segment_key

分段鍵,用于檔案塊的邊界劃分,查詢時基于Segment_key可以快速定位資料所在檔案塊,選擇與寫入時間戳相關的字段在查詢時有加速的效果。一般用于時間戳這樣的時序資料,Segment_key通常隻用一列,遵循左對齊原則。Segment_key使用的限制比較多,要求檔案在向Hologres寫入時是按照Segment_key的順序排序完成後再寫入,即select後按照Segment_key進行order_by再寫入,才會生效;一般适用于純實時寫入的自增/類自增字段(e.g.下單時間)。

Clustering_key

聚簇索引,是檔案内的排序列,用于範圍查詢(RangeQuery)的快速過濾。與MySQL的聚簇索引不同,Hologres用來布局資料,不是布局索引,是以修改Clustering_key,需要重新資料導入,且隻有一組Clustering_key,一般Clustering_key不超過2列。通常建議将where條件裡面的篩選列設定為Clustering_key

Bitmap

位圖索引,對于等值過濾場景有明顯的優化效果,多個等值過濾條件,通過向量高效計算; 适用于啞變量(基數低)的列,相當于啞變量一列變多列的實作。

Dictionary_encoding

字典編碼列索引,可以将字元串的比較轉為數字的比較,對于字元串類型可以有效壓縮,特别是基數低的列,達到加速Group by,Filter的效果。Hologres在建表時會自動給text類型加上Bitmap索引和字典編碼列索引,以實作更優的性能,但是需要注意的是,在不滿足需要的場景下需要根據業務場景添加或删除相應的索引,因為dictionary_encoding會消耗編碼解碼的資源。

下圖是Hologres索引比對原則,可以通過該圖了解一下索引的執行原理:

正确設計Hologres實時數倉,性能提升10倍+背景11月1日現場還原問題定位和優化手段優化後業務效果後續規劃
  • 可以通過執行analyze參數,來擷取表的統計資訊,幫助Hologres在讀取計算時将執行計劃優化。
analyze tablename;           

下面結合具體的示例展示怎樣優化表結構:

正确設計Hologres實時數倉,性能提升10倍+背景11月1日現場還原問題定位和優化手段優化後業務效果後續規劃

table1是一個數千萬到億行的明細表,對其他表(維表)有頻繁Local Join的需求,和較大的并發寫入;

1)根據業務查詢和寫入需求,将表放在公共層的Table Group中并配置設定60個Shard來滿足讀寫需求。

2)因為是明細表,有大量的關聯和等值/篩選場景,添加了較為全面索引配置:

  • 分析場景應用較多,有大量聚合,Group by操作,選擇列存。
  • distribution_key:正常來講應該滿足常用Join的列+能盡量分散的列作為distribution_key;這張表作為明細表,很多列都會用于關聯,是以不太好選一個key出來,選多個key的話反而會造成性能下降(要全部key都被使用才有效),最後決定選擇較符合條件的id3作為distribution_key;
  • 這裡像id1和id2是啞變量字段,适合同時配置Bitmap索引和字典編碼列索引,友善Group by 和等值查詢;
  • 對于日期(ds)設定為分區字段。明細表在查詢和使用時日期都是必不可免的字段,通過設定分區,可以有效縮小每次查詢的掃描範圍;另一方面也可以較安全的進行運維和排查問題。
  • 目前表不适用Segment_key,因資料離線/實時兩種插入模式,排序成本較高,暫不設定。
  • 對于Clustering_key,按照使用頻次,目前的選擇是id1+id2。
  • 最終DDL如下(因涉及業務敏感資料,隻展示部分DDL):
BEGIN;
CREATE TABLE public.table1 (
 "stat_date" text,
 "id0" text,
 .....,
 "id3" text,
 "id2" text,
 "name2" text,
 ...,
 "id1" text,
....,
 "ds" text NOT NULL
)
PARTITION BY LIST (ds);
--如果是用來建立TableGroup,則需要下面第一句,已有TableGroup則不需要
call set_table_property('table1', 'shard_count', '60');
CALL set_table_property('table1', 'distribution_key', 'id3');
CALL SET_TABLE_PROPERTY('public.table1', 'orientation', 'column');
CALL SET_TABLE_PROPERTY('public.table1', 'clustering_key', 'id1,id2');
CALL SET_TABLE_PROPERTY('public.table1', 'bitmap_columns', '...,id1,id2,...');
CALL SET_TABLE_PROPERTY('public.table1', 'dictionary_encoding_columns', '...,id1,id2,...');
CALL SET_TABLE_PROPERTY('public.table1', 'time_to_live_in_seconds', '7776000');
COMMIT;           

3)次要問題2:應用緩存

對于重要高頻報表添加合适的緩存來緩解資料庫壓力,離線報表可以設定時間較長的緩存,實時報表可以考慮在應用端增加 5s, 10s, 30s,1min等多個檔位的緩存。

4)次要問題3:不合理壓測計劃

在之前幾次全鍊路壓測中,對于Hologres執行個體進行讀和查的多方面壓測,雖然壓測讀的量到位了,但是沒有同步壓測資料庫寫入峰值,在實際場景中讀的性能會受到寫入資料洪流的壓力和影響;尤其Hologres存在兩種主要的寫入方式(外表同步内表,實時寫入内表);在壓測和實際使用的過程中需要特别注意讀寫峰值一起壓測。

優化後業務效果

通過優化後,在雙11這天0點的流量高峰期,在0點寫入和Query讀取同時達到業務峰值的情況下,Hologres支援的資料産品的RT平均響應時間穩定在100ms左右,為使用資料産品的業務同學/分析同學,在雙11提供穩定毫秒級的實時OLAP決策資料支援。同時也非常平穩的支援了營銷活動中心&實時大屏等核心的高并發業務産品,以及BI同學實時取數分析等場景,CPU水位穩定在30%以下,記憶體水位也穩定在50%以下。

正确設計Hologres實時數倉,性能提升10倍+背景11月1日現場還原問題定位和優化手段優化後業務效果後續規劃

同時通過本次天貓雙11,我們也發現Hologres作為實時資料存儲,在分析方面有巨大的潛力,在滿足寫入性能的同時,一方面可以和現有離線資料關聯分析,另一方面是能支援高性能的OLAP分析資料。這也團隊後續使用Hologres作為資料團隊新實時數倉架構的核心元件奠定了基礎。

後續規劃

經過雙11之後,研發團隊下個階段将利用Hologres進行更大範圍的實時數倉改造:

  1. Hologres作為行存實時公共層(替代之前timetunnel作為新中間件)開放下遊資料庫訂閱, 保持對内整個架構和對外多個架構的資料一緻性,以及解決實時結果資料在timetunnel中不可見,二次操作成本高的痛點。
  2. 下遊應用層訂閱公共層實時資料,應用層資料按照保障級别和local_Join的需要進行執行個體級别分割,資源隔離。

    舉例:以管道資料化執行個體為例,這部分資料大部分對外開放給CRM系統和生态三方合作夥伴,對一緻性,及時性和并發都有較高的要求,容易出現資料故障;在資料層面上也會有較頻繁的Local Join訴求;綜合來看作為單獨執行個體分割,包給予充足的資源保障。

    正确設計Hologres實時數倉,性能提升10倍+背景11月1日現場還原問題定位和優化手段優化後業務效果後續規劃