得物基于StarRocks的OLAP需求實踐詳解
1. 什么是 StarRocks
- 新一代極速全場景MPP數(shù)據(jù)庫,可以用 StarRocks 來支持多種數(shù)據(jù)分析場景的極速分析;
- 架構(gòu)簡潔,采用了全面向量化引擎,并配備全新設(shè)計的 CBO 優(yōu)化器,查詢速度(尤其是多表關(guān)聯(lián)查詢);
- 很好地支持實時數(shù)據(jù)分析,并能實現(xiàn)對實時更新數(shù)據(jù)的高效查詢, 還支持現(xiàn)代化物化視圖,以進一步加速查詢;
- 用戶可以靈活構(gòu)建包括大寬表、星型模型、雪花模型在內(nèi)的各類模型;
- 兼容 MySQL 協(xié)議,支持標準 SQL 語法,易于對接使用,全系統(tǒng)無外部依賴,高可用,易于運維管理。
2. 系統(tǒng)架構(gòu)
核心進程:FE(Frontend)、BE(Backend)。
注:所有節(jié)點都是有狀態(tài)的。
FE(Frontend)負責管理元數(shù)據(jù),管理客戶端連接,進行查詢規(guī)劃、查詢調(diào)度等工作。
- Leader:Follower會通過類Paxos的BDBJE協(xié)議選主出一個Leader,所有事務(wù)的提交都是由Leader發(fā)起,并完成;
- Follower:提高查詢并發(fā),同時參與投票,參與選主操作。
Follower
Observer:不參與選主操作,只會異步同步并且回放日志,主要用于擴展集群的查詢并發(fā)能力。
BE(Backend)負責數(shù)據(jù)存儲以及SQL執(zhí)行等工作。
3. 存儲架構(gòu)
在StarRocks里,一張表的數(shù)據(jù)會被拆分成多個Tablet,而每個Tablet都會以多副本的形式存儲在BE節(jié)點中,如下圖:
Table數(shù)據(jù)劃分 + Tablet三副本的數(shù)據(jù)分布:
StarRocks支持Hash分布、Range-Hash的組合數(shù)據(jù)分布(推薦)。
為了等到更高的性能,強烈建議使用Range-Hash的組合數(shù)據(jù)分布,即先分區(qū)后分桶的方式。
- Range分區(qū)可動態(tài)添加和刪減;
- Hash分桶一旦確定,不能再進行調(diào)整,只有未創(chuàng)建的分區(qū)才能設(shè)置新的分桶數(shù)。
分區(qū)和分桶的選擇是非常關(guān)鍵的。在建表時選擇好的分區(qū)分桶列,可以有效提高集群整體性能。
以下是針對特殊應(yīng)用場景下,對分區(qū)和分桶選擇的一些建議:
- 數(shù)據(jù)傾斜:業(yè)務(wù)方如果確定數(shù)據(jù)有很大程度的傾斜,那么建議采用多列組合的方式進行數(shù)據(jù)分桶,而不是只單獨采用傾斜度大的列做分桶。
- 高并發(fā):分區(qū)和分桶應(yīng)該盡量覆蓋查詢語句所帶的條件,這樣可以有效減少掃描數(shù)據(jù),提高并發(fā)。
- 高吞吐:盡量把數(shù)據(jù)打散,讓集群以更高的并發(fā)掃描數(shù)據(jù),完成相應(yīng)計算。
3.1 表的存儲
對表進行存儲時,會對表進行分區(qū)和分桶兩層處理,將表的數(shù)據(jù)分散到多臺機器進行存儲和管理。
分區(qū)機制:高效過濾,提升查詢性能。
- 分區(qū)類似分表,是對一個表按照分區(qū)鍵進行分割,可以按照時間分區(qū),根據(jù)數(shù)據(jù)量按照天/月/年劃分等等。可以利用分區(qū)裁剪對少數(shù)訪問量,也可以根據(jù)數(shù)據(jù)的冷熱程度把數(shù)據(jù)分到不同介質(zhì)上。
分桶機制:充分發(fā)揮集群性能,避免熱點問題。
- 使用分桶鍵Hash以后,把數(shù)據(jù)均勻的分布到所有的BE上,不要出現(xiàn)bucket數(shù)據(jù)傾斜的情況,分桶鍵的選擇原則就是高基數(shù)的列或者多個列組合成為一個高基數(shù)的列,盡量將數(shù)據(jù)充分打散。
- 注:Bucket數(shù)量的需要適中,如果希望充分發(fā)揮性能可以設(shè)置為:BE數(shù)量 * CPU core/2,最好tablet控制在1GB左右,tablet太少并行度可能不夠,太多可能遠數(shù)據(jù)過多,底層scan并發(fā)太多性能下降。
Tablet:最小的數(shù)據(jù)邏輯單元,可以靈活設(shè)置并行計算資源。
- 一張表被切分成了多個Tablet,StarRocks在執(zhí)行SQL語句時,可以對所有Tablet實現(xiàn)并發(fā)處理,從而充分的利用多機、多核提供的計算能力。
- 表在創(chuàng)建的時候可以指定副本數(shù),多副本夠保證數(shù)據(jù)存儲的高可靠,以及服務(wù)的高可用。
Rowset:每一次的數(shù)據(jù)變更就會產(chǎn)生一個Rowset。
- 就是以組列存方式組織的的一些文件,每次的commit都會產(chǎn)生一個新的版本,每個版本包含哪些Rowset。
- 每次寫入都會增加一個版本(無論是單條、還是stream load幾個G的文件)。
Segment:如果一個Rowset數(shù)據(jù)量比較大,則拆分成多個Segment數(shù)據(jù)斷落盤。
4. 需求背景
案例一:
- 業(yè)務(wù)背景
指標工廠服務(wù)主要面向業(yè)務(wù)人員,通過對業(yè)務(wù)指標的采集和處理,實時反映產(chǎn)品狀態(tài),為運營提供數(shù)據(jù)支撐、檢測產(chǎn)品漏洞或服務(wù)異常、提供指標異常告警功能等。
- 業(yè)務(wù)場景分析
業(yè)務(wù)指標埋點方式多樣,并不局限于某種方式,只要符合埋點標識明確、業(yè)務(wù)參數(shù)豐富、數(shù)據(jù)滿足可解析的基本要求皆可作為數(shù)據(jù)源,大致可以分為:SDK、MySQL BinLog、業(yè)務(wù)日志、阿里云ODPS數(shù)據(jù)分析。
存在的挑戰(zhàn),各種業(yè)務(wù)場景眾口難調(diào),歸納數(shù)據(jù)特征如下:
- 需要全量日志明細;
- 需要數(shù)據(jù)可以始終是最新的,即滿足實時更新場景;
- 需要對數(shù)據(jù)做層級聚合的,即可能是月、周、日、小時等;
- 需要可以承載更大的寫入量;
- 每個業(yè)務(wù)數(shù)據(jù)都要靈活的配置數(shù)據(jù)的保存時間;
- 數(shù)據(jù)源來源多,報表定制化比較高,有多個數(shù)據(jù)源合并成一個大寬表的場景、也有多表連接的的需求;
- 各種監(jiān)控圖、報表展示、業(yè)務(wù)實時查詢等,即較高的并非查詢。
引入StarRocks
幸運的是StarRocks有比較豐富的數(shù)據(jù)模型,覆蓋了上面的所有業(yè)務(wù)場景的需求,即:明細模型、更新模型、聚合模型、主鍵模型,同時選擇更為靈活的星型模型代替大寬表的方式,即直接使用多表關(guān)聯(lián)來查詢。
- 明細模型:
- 埋點數(shù)據(jù)經(jīng)過結(jié)構(gòu)化處理后按明細全量存儲;
- 該場景對DB在億級數(shù)據(jù)量下查詢性能有較高的要求;
- 數(shù)據(jù)可以通過配置動態(tài)分區(qū)來配置過期策略;
- 場景使用時從結(jié)構(gòu)化數(shù)據(jù)選擇個別字段維度在線聚合查詢。
- 聚合模型:
- 埋點數(shù)據(jù)數(shù)據(jù)量巨大,且對明細數(shù)據(jù)不要求溯源,直接做聚合計算,比如計算PV、UV場景;
- 數(shù)據(jù)可以通過配置動態(tài)分區(qū)來配置過期策略。
- 更新模型:
- 埋點數(shù)據(jù)狀態(tài)會發(fā)生變動,且需要實時更新數(shù)據(jù),更新數(shù)據(jù)范圍不會跨度多個分區(qū)的,比如:訂單、優(yōu)惠券狀態(tài)等;
- 數(shù)據(jù)可以通過配置動態(tài)分區(qū)來配置過期策略。
基于以上業(yè)務(wù)場景的分析,這三種模型可以完美解決數(shù)據(jù)的問題。
需要實時的數(shù)據(jù)寫入場景,我也沿用了業(yè)內(nèi)流行的解決方案,即數(shù)據(jù)采集到 Kafka 之后,使用Flink做實時寫入到StarRocks。StarRocks提供了非常好用的Flink-connector插件。
小tips:
1. 雖然StarRocks已經(jīng)很好的優(yōu)化了寫入性能,當寫入壓力大,仍會出現(xiàn)寫入拒絕,建議可適當增大單次導入數(shù)據(jù)量,降低頻率,但同時也會導致數(shù)據(jù)落庫延遲增加。所以需要做好一定的取舍,做到收益最大化。
2. Flink的sink端不建議配置過大,會引起并發(fā)事務(wù)過多的報錯,建議每個flink任務(wù)source可以配置多些,sink的連接數(shù)不能過大。
小結(jié)
集群規(guī)模:5FE(8c32GB)、5BE(32c128GB)
目前該方案已支持數(shù)百個業(yè)務(wù)指標的接入,涉及幾十個大盤的指標展示和告警,數(shù)據(jù)存儲TB級,每日凈增長上百G,總體運行穩(wěn)定。
案例二:
- 業(yè)務(wù)背景
內(nèi)部系統(tǒng)業(yè)務(wù)看板,主要服務(wù)于全公司員工,提供項目及任務(wù)跟蹤等功能。
- 業(yè)務(wù)場景分析
分析業(yè)務(wù)特點:
- 數(shù)據(jù)變更頻繁(更新),變更時間跨度長
- 查詢時間跨度多
- 報表需準實時更新
- 關(guān)聯(lián)維表查詢多,部門/業(yè)務(wù)線/資源域等
- 冷熱數(shù)據(jù),最近數(shù)據(jù)查詢頻繁
- 歷史架構(gòu)與痛點
當初數(shù)據(jù)庫選型時,結(jié)合業(yè)務(wù)特點,用戶需要動態(tài)、靈活的增刪記錄自己的任務(wù),因而選擇了JOSN 模型減少了應(yīng)用程序代碼和存儲層之間的阻抗,選擇MongoDB作為數(shù)據(jù)存儲。
伴隨著公司快速快發(fā),當需要報表展示,特別是時間跨度比較大,涉及到多部門、多維度、細粒度等報表展示時,查詢時間在MongoDB需要執(zhí)行10s甚至更久。
- 引入StarRocks
調(diào)研了StarRocks、ClickHouse兩款都是非常優(yōu)秀的分析型數(shù)據(jù)庫,在選型時,分析了業(yè)務(wù)應(yīng)用場景,主要集中在單表聚合查詢、多表關(guān)聯(lián)查詢、實時更新讀寫查詢。維度表更新頻繁,即存儲在MySQL中,StarRocks比較好的支持外表關(guān)聯(lián)查詢,很大程度上降低了開發(fā)難度,最終決定選用StarRocks作為存儲引擎。
改造階段,將原先MongoDB中的一個集合拆分成3張表。使用明細模型,記錄每天的對應(yīng)人員的任務(wù)信息,按天分區(qū),由之前的每人每天一條記錄改為,以事件為單位,每人每天可以多條記錄。
實現(xiàn)頻繁更新的維表,則選擇使用外部表,減少維度數(shù)據(jù)同步到StarRocks的復雜度。
小結(jié)
改造前,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 -- 更多維表關(guān)聯(lián) 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之間數(shù)據(jù)對比:
- StarRocks: 1次查詢聚合,可完全通過復雜SQL聚合函數(shù)計算,耗時 295ms
- Mongodb: 需分2次查詢+計算,共耗時3s+9s=12s
5. 經(jīng)驗分享
在使用StarRocks時遇到的一些報錯和解決方案(網(wǎng)上資料較少的報錯信息):
a.數(shù)據(jù)導入Stream Load報錯:“current running txns on db 13003 is 100, larger than limit 100”
原因:超過了每個數(shù)據(jù)庫中正在運行的導入作業(yè)的最大個數(shù),默認值為100??梢酝ㄟ^調(diào)整max_running_txn_num_per_db參數(shù)來增加每次導入作業(yè)的個數(shù),最好是通過調(diào)整作業(yè)提交批次。即攢批,減少并發(fā)。
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 語言編寫用戶定義函數(shù) UDF,在執(zhí)行函數(shù)報錯:“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環(huán)境變量,即使是BE節(jié)點也是需要調(diào)用Java的一些函數(shù),也可以直接將BE啟動腳本增加JAVA_HOME環(huán)境變量配置。\
d. 執(zhí)行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數(shù)據(jù)的時候產(chǎn)生了大量隨機group_id
建議:建routine load的時候指定一下group name。
f. StarRocks連接超時,查詢語句報錯:“ERROR 1064(HY000):there is no scanNode Backend”,當重新啟動BE節(jié)點后,短暫的恢復。日志報錯如下:
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。臨時解決方案是找到問題任務(wù),暫停任務(wù),即可恢復。
6. 未來規(guī)劃
接下來我們會有更多業(yè)務(wù)接入 StarRocks,替換原有 OLAP 查詢引擎;運用更多的業(yè)務(wù)場景,積累經(jīng)驗,提高集群穩(wěn)定性。未來希望 StarRocks 優(yōu)化提升主鍵模型內(nèi)存占用,支持更靈活的部分列更新方式,持續(xù)優(yōu)化提升 Bitmap 查詢性能,同時優(yōu)化多租戶資源隔離。今后我們也會繼續(xù)積極參與 StarRocks 的社區(qū)討論,反饋業(yè)務(wù)場景。
以上就是得物基于StarRocks的OLAP需求實踐詳解的詳細內(nèi)容,更多關(guān)于得物StarRocks OLAP需求的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
你應(yīng)該知道的區(qū)塊鏈運作7個核心技術(shù)
這篇文章主要為大家詳細介紹了你應(yīng)該知道的區(qū)塊鏈運作7個核心技術(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01淺談關(guān)系型數(shù)據(jù)庫中如何進行事務(wù)管理
這篇文章主要介紹了淺談關(guān)系型數(shù)據(jù)庫中如何進行事務(wù)管理,事務(wù)是一組數(shù)據(jù)庫操作,它們必須全部執(zhí)行或全部回滾,這意味著如果在事務(wù)執(zhí)行期間出現(xiàn)錯誤,所有的更改都將撤銷,數(shù)據(jù)庫將被恢復到事務(wù)開始之前的狀態(tài),需要的朋友可以參考下2023-07-07Sql Server 和 Access 操作數(shù)據(jù)庫結(jié)構(gòu)Sql語句小結(jié)
Sql Server 和 Access 操作數(shù)據(jù)庫結(jié)構(gòu)Sql語句小結(jié)...2007-06-06數(shù)據(jù)庫建立索引的一般依據(jù)小結(jié)
以下是一些普遍的建立索引時的判斷依據(jù)。一言以蔽之,索引的建立必須慎重,對每個索引的必要性都應(yīng)該經(jīng)過仔細分析,要有建立的依據(jù)2012-05-05數(shù)據(jù)庫設(shè)計技巧[轉(zhuǎn)]
數(shù)據(jù)庫設(shè)計技巧[轉(zhuǎn)]...2007-01-01Navicat Premium 16最新永久激活教程(NavicatCracker)
最新版的Navicat Premium 16 已經(jīng)發(fā)布,今天小編給大家分享Navicat Premium 16最新永久激活教程(NavicatCracker),感興趣的朋友跟隨小編一起看看吧2023-06-06