日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

得物基于StarRocks的OLAP需求實踐詳解_數據庫其它

作者:得物技術 ? 更新時間: 2022-11-21 編程語言

1. 什么是 StarRocks

  • 新一代極速全場景MPP數據庫,可以用 StarRocks 來支持多種數據分析場景的極速分析;
  • 架構簡潔,采用了全面向量化引擎,并配備全新設計的 CBO 優化器,查詢速度(尤其是多表關聯查詢);
  • 很好地支持實時數據分析,并能實現對實時更新數據的高效查詢, 還支持現代化物化視圖,以進一步加速查詢;
  • 用戶可以靈活構建包括大寬表、星型模型、雪花模型在內的各類模型;
  • 兼容 MySQL 協議,支持標準 SQL 語法,易于對接使用,全系統無外部依賴,高可用,易于運維管理。

2.?系統架構

核心進程:FE(Frontend)、BE(Backend)。

注:所有節點都是有狀態的。

FE(Frontend)負責管理元數據,管理客戶端連接,進行查詢規劃、查詢調度等工作。

?- ? Leader:Follower會通過類Paxos的BDBJE協議選主出一個Leader,所有事務的提交都是由Leader發起,并完成;

?- ? Follower:提高查詢并發,同時參與投票,參與選主操作。

Follower

Observer:不參與選主操作,只會異步同步并且回放日志,主要用于擴展集群的查詢并發能力。

BE(Backend)負責數據存儲以及SQL執行等工作。

3.?存儲架構

在StarRocks里,一張表的數據會被拆分成多個Tablet,而每個Tablet都會以多副本的形式存儲在BE節點中,如下圖:

Table數據劃分 + Tablet三副本的數據分布:

StarRocks支持Hash分布、Range-Hash的組合數據分布(推薦)。

為了等到更高的性能,強烈建議使用Range-Hash的組合數據分布,即先分區后分桶的方式。

  • Range分區可動態添加和刪減;
  • Hash分桶一旦確定,不能再進行調整,只有未創建的分區才能設置新的分桶數。

分區和分桶的選擇是非常關鍵的。在建表時選擇好的分區分桶列,可以有效提高集群整體性能。

以下是針對特殊應用場景下,對分區和分桶選擇的一些建議:

  • 數據傾斜:業務方如果確定數據有很大程度的傾斜,那么建議采用多列組合的方式進行數據分桶,而不是只單獨采用傾斜度大的列做分桶。
  • 高并發:分區和分桶應該盡量覆蓋查詢語句所帶的條件,這樣可以有效減少掃描數據,提高并發。
  • 高吞吐:盡量把數據打散,讓集群以更高的并發掃描數據,完成相應計算。

3.1 表的存儲

對表進行存儲時,會對表進行分區和分桶兩層處理,將表的數據分散到多臺機器進行存儲和管理。

分區機制:高效過濾,提升查詢性能。

  • 分區類似分表,是對一個表按照分區鍵進行分割,可以按照時間分區,根據數據量按照天/月/年劃分等等。可以利用分區裁剪對少數訪問量,也可以根據數據的冷熱程度把數據分到不同介質上。

分桶機制:充分發揮集群性能,避免熱點問題。

  • 使用分桶鍵Hash以后,把數據均勻的分布到所有的BE上,不要出現bucket數據傾斜的情況,分桶鍵的選擇原則就是高基數的列或者多個列組合成為一個高基數的列,盡量將數據充分打散。
  • 注:Bucket數量的需要適中,如果希望充分發揮性能可以設置為:BE數量 * CPU core/2,最好tablet控制在1GB左右,tablet太少并行度可能不夠,太多可能遠數據過多,底層scan并發太多性能下降。

Tablet:最小的數據邏輯單元,可以靈活設置并行計算資源。

  • 一張表被切分成了多個Tablet,StarRocks在執行SQL語句時,可以對所有Tablet實現并發處理,從而充分的利用多機、多核提供的計算能力。
  • 表在創建的時候可以指定副本數,多副本夠保證數據存儲的高可靠,以及服務的高可用。

Rowset:每一次的數據變更就會產生一個Rowset。

  • 就是以組列存方式組織的的一些文件,每次的commit都會產生一個新的版本,每個版本包含哪些Rowset。
  • 每次寫入都會增加一個版本(無論是單條、還是stream load幾個G的文件)。

Segment:如果一個Rowset數據量比較大,則拆分成多個Segment數據斷落盤。

4.?需求背景

案例一:

  • 業務背景

指標工廠服務主要面向業務人員,通過對業務指標的采集和處理,實時反映產品狀態,為運營提供數據支撐、檢測產品漏洞或服務異常、提供指標異常告警功能等。

  • 業務場景分析

業務指標埋點方式多樣,并不局限于某種方式,只要符合埋點標識明確、業務參數豐富、數據滿足可解析的基本要求皆可作為數據源,大致可以分為:SDK、MySQL BinLog、業務日志、阿里云ODPS數據分析。

存在的挑戰,各種業務場景眾口難調,歸納數據特征如下:

  • 需要全量日志明細;
  • 需要數據可以始終是最新的,即滿足實時更新場景;
  • 需要對數據做層級聚合的,即可能是月、周、日、小時等;
  • 需要可以承載更大的寫入量;
  • 每個業務數據都要靈活的配置數據的保存時間;
  • 數據源來源多,報表定制化比較高,有多個數據源合并成一個大寬表的場景、也有多表連接的的需求;
  • 各種監控圖、報表展示、業務實時查詢等,即較高的并非查詢。

引入StarRocks

幸運的是StarRocks有比較豐富的數據模型,覆蓋了上面的所有業務場景的需求,即:明細模型、更新模型、聚合模型、主鍵模型,同時選擇更為靈活的星型模型代替大寬表的方式,即直接使用多表關聯來查詢。

  • 明細模型:
  • 埋點數據經過結構化處理后按明細全量存儲;
  • 該場景對DB在億級數據量下查詢性能有較高的要求;
  • 數據可以通過配置動態分區來配置過期策略;
  • 場景使用時從結構化數據選擇個別字段維度在線聚合查詢。
  • 聚合模型:
  • 埋點數據數據量巨大,且對明細數據不要求溯源,直接做聚合計算,比如計算PV、UV場景;
  • 數據可以通過配置動態分區來配置過期策略。
  • 更新模型:
  • 埋點數據狀態會發生變動,且需要實時更新數據,更新數據范圍不會跨度多個分區的,比如:訂單、優惠券狀態等;
  • 數據可以通過配置動態分區來配置過期策略。

基于以上業務場景的分析,這三種模型可以完美解決數據的問題。

需要實時的數據寫入場景,我也沿用了業內流行的解決方案,即數據采集到 Kafka 之后,使用Flink做實時寫入到StarRocks。StarRocks提供了非常好用的Flink-connector插件。

小tips:

1.?雖然StarRocks已經很好的優化了寫入性能,當寫入壓力大,仍會出現寫入拒絕,建議可適當增大單次導入數據量,降低頻率,但同時也會導致數據落庫延遲增加。所以需要做好一定的取舍,做到收益最大化。?

2.?Flink的sink端不建議配置過大,會引起并發事務過多的報錯,建議每個flink任務source可以配置多些,sink的連接數不能過大。

小結

集群規模:5FE(8c32GB)、5BE(32c128GB)

目前該方案已支持數百個業務指標的接入,涉及幾十個大盤的指標展示和告警,數據存儲TB級,每日凈增長上百G,總體運行穩定。

案例二:

  • 業務背景

內部系統業務看板,主要服務于全公司員工,提供項目及任務跟蹤等功能。

  • 業務場景分析

分析業務特點:

  • 數據變更頻繁(更新),變更時間跨度長
  • 查詢時間跨度多
  • 報表需準實時更新
  • 關聯維表查詢多,部門/業務線/資源域等
  • 冷熱數據,最近數據查詢頻繁
  • 歷史架構與痛點

當初數據庫選型時,結合業務特點,用戶需要動態、靈活的增刪記錄自己的任務,因而選擇了JOSN 模型減少了應用程序代碼和存儲層之間的阻抗,選擇MongoDB作為數據存儲。

伴隨著公司快速快發,當需要報表展示,特別是時間跨度比較大,涉及到多部門、多維度、細粒度等報表展示時,查詢時間在MongoDB需要執行10s甚至更久。

  • 引入StarRocks

調研了StarRocks、ClickHouse兩款都是非常優秀的分析型數據庫,在選型時,分析了業務應用場景,主要集中在單表聚合查詢、多表關聯查詢、實時更新讀寫查詢。維度表更新頻繁,即存儲在MySQL中,StarRocks比較好的支持外表關聯查詢,很大程度上降低了開發難度,最終決定選用StarRocks作為存儲引擎。

改造階段,將原先MongoDB中的一個集合拆分成3張表。使用明細模型,記錄每天的對應人員的任務信息,按天分區,由之前的每人每天一條記錄改為,以事件為單位,每人每天可以多條記錄。
實現頻繁更新的維表,則選擇使用外部表,減少維度數據同步到StarRocks的復雜度。

小結

改造前,MongoDB查詢,寫法復雜,多次查詢。

db.time_note_new.aggregate(
    [
       {'$unwind': '$depart'},
       {'$match': {
           'depart': {'$in': ['部門id']},
           'workday': {'$gte': 1609430400, '$lt': 1646064000},
           'content.id': {'$in': ['事項id']}, 
           'vacate_state': {'$in': [0, 1]}}
       }, 
       {'$group': { 
           '_id': '$depart', 
           'write_hour': {'$sum': '$write_hour'}, 
           'code_count': {'$sum': '$code_count'}, 
           'all_hour': {'$sum': '$all_hour'}, 
           'count_day_user': {'$sum': {'$cond': [{'$eq': ['$vacate_state', 0]}, 1, 0]}}, 
           'vacate_hour': {'$sum': {'$cond': [{'$eq': ['$vacate_state', 0]}, '$all_hour', 0]}}, 
           'vacate_write_hour': {'$sum': {'$cond': [{'$eq': ['$vacate_state', 0]}, '$write_hour', 0]}}}
           -- ... more field
       }, 
       {'$project': {
           '_id': 1, 
           'write_hour': {'$cond': [{'$eq': ['$count_day_user', 0]}, 0, {'$divide': ['$vacate_write_hour', '$count_day_user']}]}, 
           'count_day_user': 1, 
           'vacate_hour': 1, 
           'vacate_write_hour': 1, 
           'code_count': {'$cond': [{'$eq': ['$count_day_user', 0]}, 0, {'$divide': ['$code_count', '$count_day_user']}]}, 
           'all_hour': {'$cond': [{'$eq': ['$count_day_user', 0]}, 0, {'$divide': ['$vacate_hour', '$count_day_user']}]}}
           -- ... more field
       }
    ]
)

改造后,直接兼容SQL,單次聚合。

WITH cont_time as (
    SELECT b.depart_id, a.user_id, a.workday, a.content_id, a.vacate_state
        min(a.content_second)/3600 AS content_hour,
        min(a.write_second)/3600 AS write_hour,
        min(a.all_second)/3600 AS all_hour
    FROM time_note_report AS a
    JOIN user_department AS b ON a.user_id = b.user_id
    -- 更多維表關聯
    WHERE b.depart_id IN (?)  AND a.content_id IN (?) 
      AND a.workday >= '2021-01-01' AND a.workday < '2022-03-31' 
      AND a.vacate_state IN (0, 1)
    GROUP BY b.depart_id, a.user_id, a.workday, a.content_id,a.vacate_state
)
SELECT M.*, N.*
FROM ( 
    SELECT t.depart_id,
         SUM(IF(t.content_id = 14, t.content_hour, 0))   AS content_hour_14,
         SUM(IF(t.content_id = 46, t.content_hour, 0))   AS content_hour_46,
         -- ...more
    FROM cont_time t
    GROUP BY t.depart_id
) M
JOIN ( 
    SELECT depart_id                                  AS join_depart_id,
      SUM(write_hour)                                 AS write_hour,
      SUM(all_hour)                                   AS all_hour
      -- 更多指標
    FROM cont_time
    GROUP BY depart_id
) N ON M.depart_id = N.join_depart_id
ORDER BY depart_id ASC

以查詢報表2021/01/01~2022/03/01之間數據對比:

  • StarRocks: 1次查詢聚合,可完全通過復雜SQL聚合函數計算,耗時 295ms
  • Mongodb: 需分2次查詢+計算,共耗時3s+9s=12s

5. 經驗分享

在使用StarRocks時遇到的一些報錯和解決方案(網上資料較少的報錯信息):

a.數據導入Stream Load報錯:“current running txns on db 13003 is 100, larger than limit 100”

原因:超過了每個數據庫中正在運行的導入作業的最大個數,默認值為100。可以通過調整max_running_txn_num_per_db參數來增加每次導入作業的個數,最好是通過調整作業提交批次。即攢批,減少并發。

b. FE報錯:“java.io.FileNotFoundException: /proc/net/snmp (Too many open files)”

原因:文件句柄不足,這里需要注意,如果是supervisor管理進程,則需要將文件句柄的配置加到fe的啟動腳本中。

if [[ $(ulimit -n) -lt 60000 ]]; then
  ulimit -n 65535
fi

c. StarRocks 支持使用 Java 語言編寫用戶定義函數 UDF,在執行函數報錯:“rpc failed, host: x.x.x.x”,be.out日志中報錯:

start time: Tue Aug 9 19:05:14 CST 2022
Error occurred during initialization of VM
java/lang/NoClassDefFoundError: java/lang/Object

原因:在使用supervisor管理進程,需要注意增加JAVA_HOME環境變量,即使是BE節點也是需要調用Java的一些函數,也可以直接將BE啟動腳本增加JAVA_HOME環境變量配置。\

d. 執行Delete操作報錯如下:

SQL > delete from tableName partition (p20220809,p20220810) where `c_time` > '2022-08-09 15:20:00' and `c_time` < '2022-08-10 15:20:00';
ERROR 1064 (HY000): Where clause only supports compound predicate, binary predicate, is_null predicate and in predicate

原因:目前delete后的where條件不支持between and操作,目前只支持 =、>、>=、<、<=、!=、IN、NOT IN

e. 使用Routine Load消費kakfa數據的時候產生了大量隨機group_id

建議:建routine load的時候指定一下group name。

f. StarRocks連接超時,查詢語句報錯:“ERROR 1064(HY000):there is no scanNode Backend”,當重新啟動BE節點后,短暫的恢復。日志報錯如下:

kafka log-4-FAIL, event: [thrd:x.x.x.x:9092/bootstrap]: x.x.x.x:9092/1: ApiVersionRequest failed: Local: Timed out: probably due to broker version < 0.10 (see api.version.request configuration) (after 10009ms in state APIVERSION_QUERY)

原因:當Routine Load連接kafka有問題時,會導致BrpcWorker線程耗盡,影響正常訪問連接StarRocks。臨時解決方案是找到問題任務,暫停任務,即可恢復。

6. 未來規劃

接下來我們會有更多業務接入 StarRocks,替換原有 OLAP 查詢引擎;運用更多的業務場景,積累經驗,提高集群穩定性。未來希望 StarRocks 優化提升主鍵模型內存占用,支持更靈活的部分列更新方式,持續優化提升 Bitmap 查詢性能,同時優化多租戶資源隔離。今后我們也會繼續積極參與 StarRocks 的社區討論,反饋業務場景。

原文鏈接:https://juejin.cn/post/7148632950844850212

欄目分類
最近更新