在數(shù)據(jù)分析的實(shí)際場(chǎng)景中,冷熱數(shù)據(jù)往往面臨著不同的查詢(xún)頻次及響應(yīng)速度要求。例如在電商訂單場(chǎng)景中,用戶(hù)經(jīng)常訪問(wèn)近 6 個(gè)月的訂單,時(shí)間較久遠(yuǎn)的訂單訪問(wèn)次數(shù)非常少;在行為分析場(chǎng)景中,需支持近期流量數(shù)據(jù)的高頻查詢(xún)且時(shí)效性要求高,但為了保證歷史數(shù)據(jù)隨時(shí)可查,往往要求數(shù)據(jù)保存周期更為久遠(yuǎn);在日志分析場(chǎng)景中,歷史數(shù)據(jù)的訪問(wèn)頻次很低,但需長(zhǎng)時(shí)間備份以保證后續(xù)的審計(jì)和回溯的工作...往往歷史數(shù)據(jù)的應(yīng)用價(jià)值會(huì)隨著時(shí)間推移而降低,且需要應(yīng)對(duì)的查詢(xún)需求也會(huì)隨之銳減。而隨著歷史數(shù)據(jù)的不斷增多,如果我們將所有數(shù)據(jù)存儲(chǔ)在本地,將造成大量的資源浪費(fèi)。
為了解決滿(mǎn)足以上問(wèn)題,冷熱數(shù)據(jù)分層技術(shù)應(yīng)運(yùn)而生,以更好滿(mǎn)足企業(yè)降本增效的趨勢(shì)。顧名思義,冷熱分層是將冷熱數(shù)據(jù)分別存儲(chǔ)在成本不同的存儲(chǔ)介質(zhì)上,例如熱數(shù)據(jù)存儲(chǔ)在成本更高的 SSD 盤(pán)上、以提高時(shí)效數(shù)據(jù)的查詢(xún)速度和響應(yīng)能力,而冷數(shù)據(jù)則存儲(chǔ)在相對(duì)低成本的 HDD 盤(pán)甚至更為廉價(jià)的對(duì)象存儲(chǔ)上,以降低存儲(chǔ)成本。我們還可以根據(jù)實(shí)際業(yè)務(wù)需求進(jìn)行靈活的配置和調(diào)整,以滿(mǎn)足不同場(chǎng)景的要求。 冷熱分層一般適用于以下需求場(chǎng)景:
數(shù)據(jù)存儲(chǔ)周期長(zhǎng):面對(duì)歷史數(shù)據(jù)的不斷增加,存儲(chǔ)成本也隨之增加;
冷熱數(shù)據(jù)訪問(wèn)頻率及性能要求不同:熱數(shù)據(jù)訪問(wèn)頻率高且需要快速響應(yīng),而冷數(shù)據(jù)訪問(wèn)頻率低且響應(yīng)速度要求不高;
數(shù)據(jù)備份和恢復(fù)成本高:備份和恢復(fù)大量數(shù)據(jù)需要消耗大量的時(shí)間和資源。
.....
更高效率的冷熱分層技術(shù)
自 Apache Doris 0.12 版本引入動(dòng)態(tài)分區(qū)功能,開(kāi)始支持對(duì)表分區(qū)進(jìn)行生命周期管理,可以設(shè)置熱數(shù)據(jù)轉(zhuǎn)冷時(shí)間以及存儲(chǔ)介質(zhì)標(biāo)識(shí),通過(guò)后臺(tái)任務(wù)將熱數(shù)據(jù)從 SSD 自動(dòng)冷卻到 HDD,以幫助用戶(hù)較大程度地降低存儲(chǔ)成本。用戶(hù)可以在建表屬性中配置參數(shù)storage_cooldown_time或者dynamic_partition.hot_partition_num來(lái)控制數(shù)據(jù)從 SSD 冷卻到 HDD,當(dāng)分區(qū)滿(mǎn)足冷卻條件時(shí),Doris 會(huì)自動(dòng)執(zhí)行任務(wù)。而 HDD 上的數(shù)據(jù)是以多副本的方式存儲(chǔ)的,并沒(méi)有做到最大程度的成本節(jié)約,因此對(duì)于冷數(shù)據(jù)存儲(chǔ)成本仍然有較大的優(yōu)化空間。 為了幫助用戶(hù)進(jìn)一步降低存儲(chǔ)成本,社區(qū)在已有功能上進(jìn)行了優(yōu)化,并在 Apache Doris 2.0 版本中推出了冷熱數(shù)據(jù)分層的功能。冷熱數(shù)據(jù)分層功能使 Apache Doris 可以將冷數(shù)據(jù)下沉到存儲(chǔ)成本更加低廉的對(duì)象存儲(chǔ)中,同時(shí)冷數(shù)據(jù)在對(duì)象存儲(chǔ)上的保存方式也從多副本變?yōu)閱胃北?,存?chǔ)成本進(jìn)一步降至原先的三分之一,同時(shí)也減少了因存儲(chǔ)附加的計(jì)算資源成本和網(wǎng)絡(luò)開(kāi)銷(xiāo)成本。 如下圖所示,在 Apache Doris 2.0 版本中支持三級(jí)存儲(chǔ),分別是 SSD、HDD 和對(duì)象存儲(chǔ)。用戶(hù)可以配置使數(shù)據(jù)從 SSD 下沉到 HDD,并使用冷熱分層功能將數(shù)據(jù)從 SSD 或者 HDD 下沉到對(duì)象存儲(chǔ)中。
以公有云價(jià)格為例,云磁盤(pán)的價(jià)格通常是對(duì)象存儲(chǔ)的 5-10 倍,如果可以將 80% 的冷數(shù)據(jù)保存到對(duì)象存儲(chǔ)中,存儲(chǔ)成本至少可降低 70%。 我們使用以下公式計(jì)算節(jié)約的成本,設(shè)冷數(shù)據(jù)比率為 rate,對(duì)象存儲(chǔ)價(jià)格為 OSS,云磁盤(pán)價(jià)格為 CloudDisk
這里我們假設(shè)用戶(hù)有 100TB 的數(shù)據(jù),我們按照不同比例將冷數(shù)據(jù)遷移到對(duì)象存儲(chǔ),來(lái)計(jì)算一下如果使用冷熱分層之后,相較于全量使用普通云盤(pán)、SSD 云盤(pán)可節(jié)約多少成本。
阿里云 OSS 標(biāo)準(zhǔn)存儲(chǔ)成本是 120 元/ T /月
阿里云普通云盤(pán)的價(jià)格是 300 元/ T /月
阿里云 SSD 云盤(pán)的價(jià)格是 1000 元/ T /月
例如在 80% 冷數(shù)據(jù)占比的情況下,剩余 20% 使用普通云盤(pán)每月僅花費(fèi) 80T*120 + 20T * 300 = 15600元,而全量使用普通云盤(pán)則需要花費(fèi) 30000 元,通過(guò)冷熱數(shù)據(jù)分層節(jié)省了48%的存儲(chǔ)成本。如果用戶(hù)使用的是 SSD 云盤(pán),那么花費(fèi)則會(huì)從全量使用需花費(fèi)的 100000 元降低到 80T*120 + 20T * 1000 = 29600元,存儲(chǔ)成本最高降低超過(guò) 70%!
冷熱分層使用指南
若要使用 Doris 的冷熱分層功能,首先需要準(zhǔn)備一個(gè)對(duì)象存儲(chǔ)的 Bucket 并獲取對(duì)應(yīng)的 AK/SK。當(dāng)準(zhǔn)備就緒之后,下面為具體的使用步驟:
1. 創(chuàng)建 Resource
可以使用對(duì)象存儲(chǔ)的 Bucket 以及 AK/SK 創(chuàng)建 Resource,目前支持 AWS、Azure、阿里云、華為云、騰訊云、百度云等多個(gè)云的對(duì)象存儲(chǔ)。
CREATE?RESOURCE?IF?NOT?EXISTS?"${resource_name}" ???
?????PROPERTIES( ???????
?????"type"="s3", ????????
????"s3.endpoint"?=?"${S3Endpoint}", ??????
??????"s3.region"?=?"${S3Region}", ??????????
??"s3.root.path"?=?"path/to/root", ???????
?????"s3.access_key"?=?"${S3AK}", ??????
??????"s3.secret_key"?=?"${S3SK}", ???????
?????"s3.connection.maximum"?=?"50", ????????
????"s3.connection.request.timeout"?=?"3000", ??????
??????"s3.connection.timeout"?=?"1000", ????????
????"s3.bucket"?=?"${S3BucketName}" ?????
???);
CREATE?STORAGE?POLICY?testPolicy PROPERTIES( ??"storage_resource"?=?"remote_s3", ??"cooldown_ttl"?=?"1d" ); 例如上方代碼中名為testPolicy的storage policy設(shè)置了新導(dǎo)入的數(shù)據(jù)將在一天后開(kāi)始冷卻,并且冷卻后的冷數(shù)據(jù)會(huì)存放到remote_s3所表示的對(duì)象存儲(chǔ)的?root path下。除了設(shè)置 TTL 以外,在 Policy 中也支持設(shè)置冷卻的時(shí)間點(diǎn),可以直接設(shè)置為:
CREATE?STORAGE?POLICY?testPolicyForTTlDatatime PROPERTIES( ??"storage_resource"?=?"remote_s3", ??"cooldown_datetime"?=?"2023-06-07?2100" );3. 給表或者分區(qū)設(shè)置 Storage Policy 在創(chuàng)建出對(duì)應(yīng)的 Resource 和 Storage Policy 之后,我們可以在建表的時(shí)候?qū)φ麖埍碓O(shè)置 Cooldown Policy,也可以針對(duì)某個(gè) Partition 設(shè)置 Cooldown Policy。這里以 TPCH 測(cè)試數(shù)據(jù)集中的 Lineitem 表舉例。如果需要將整張表都設(shè)置冷卻的策略,則可以直接在整張表的 Properties 中設(shè)置:
CREATE?TABLE?IF?NOT?EXISTS?lineitem1?( ????????????L_ORDERKEY????INTEGER?NOT?NULL, ????????????L_PARTKEY?????INTEGER?NOT?NULL, ????????????L_SUPPKEY?????INTEGER?NOT?NULL, ????????????L_LINENUMBER??INTEGER?NOT?NULL, ????????????L_QUANTITY????DECIMAL(15,2)?NOT?NULL, ????????????L_EXTENDEDPRICE??DECIMAL(15,2)?NOT?NULL, ????????????L_DISCOUNT????DECIMAL(15,2)?NOT?NULL, ????????????L_TAX?????????DECIMAL(15,2)?NOT?NULL, ????????????L_RETURNFLAG??CHAR(1)?NOT?NULL, ????????????L_LINESTATUS??CHAR(1)?NOT?NULL, ????????????L_SHIPDATE????DATEV2?NOT?NULL, ????????????L_COMMITDATE??DATEV2?NOT?NULL, ????????????L_RECEIPTDATE?DATEV2?NOT?NULL, ????????????L_SHIPINSTRUCT?CHAR(25)?NOT?NULL, ????????????L_SHIPMODE?????CHAR(10)?NOT?NULL, ????????????L_COMMENT??????VARCHAR(44)?NOT?NULL ????????????) ????????????DUPLICATE?KEY(L_ORDERKEY,?L_PARTKEY,?L_SUPPKEY,?L_LINENUMBER) ????????????PARTITION?BY?RANGE(`L_SHIPDATE`) ????????????( ????????????????PARTITION?`p202301`?VALUES?LESS?THAN?("2017-02-01"), ????????????????PARTITION?`p202302`?VALUES?LESS?THAN?("2017-03-01") ????????????) ????????????DISTRIBUTED?BY?HASH(L_ORDERKEY)?BUCKETS?3 ????????????PROPERTIES?( ????????????"replication_num"?=?"3", ????????????"storage_policy"?=?"${policy_name}" ????????????)用戶(hù)可以通過(guò)show tablets獲得每個(gè) Tablet 的信息,其中 CooldownReplicaId 不為 -1 并且 CooldownMetaId 不為空的 Tablet 說(shuō)明使用了 Storage Policy。如下方代碼,通過(guò)show tablets可以看到上面的 Table 的所有 Tablet 都設(shè)置了 ?CooldownReplicaId 和 CooldownMetaId,這說(shuō)明整張表都是使用了 Storage Policy。
???????????????TabletId:?3674797 ??????????????ReplicaId:?3674799 ??????????????BackendId:?10162 ?????????????SchemaHash:?513232100 ????????????????Version:?1 ??????LstSuccessVersion:?1 ???????LstFailedVersion:?-1 ??????????LstFailedTime:?NULL ??????????LocalDataSize:?0 ?????????RemoteDataSize:?0 ???????????????RowCount:?0 ??????????????????State:?NORMAL LstConsistencyCheckTime:?NULL ???????????CheckVersion:?-1 ???????????VersionCount:?1 ??????????????QueryHits:?0 ???????????????PathHash:?8030511811695924097 ????????????????MetaUrl:?http://172.16.0.16:6781/api/meta/header/3674797 ???????CompactionStatus:?http://172.16.0.16:6781/api/compaction/show?tablet_id=3674797 ??????CooldownReplicaId:?3674799 ?????????CooldownMetaId:?TUniqueId(hi:-8987737979209762207,?lo:-2847426088899160152)我們也可以對(duì)某個(gè)具體的 Partition 設(shè)置 Storage Policy,只需要在 Partition 的 Properties 中加上具體的 Policy Name 即可:
CREATE?TABLE?IF?NOT?EXISTS?lineitem1?( ????????????L_ORDERKEY????INTEGER?NOT?NULL, ????????????L_PARTKEY?????INTEGER?NOT?NULL, ????????????L_SUPPKEY?????INTEGER?NOT?NULL, ????????????L_LINENUMBER??INTEGER?NOT?NULL, ????????????L_QUANTITY????DECIMAL(15,2)?NOT?NULL, ????????????L_EXTENDEDPRICE??DECIMAL(15,2)?NOT?NULL, ????????????L_DISCOUNT????DECIMAL(15,2)?NOT?NULL, ????????????L_TAX?????????DECIMAL(15,2)?NOT?NULL, ????????????L_RETURNFLAG??CHAR(1)?NOT?NULL, ????????????L_LINESTATUS??CHAR(1)?NOT?NULL, ????????????L_SHIPDATE????DATEV2?NOT?NULL, ????????????L_COMMITDATE??DATEV2?NOT?NULL, ????????????L_RECEIPTDATE?DATEV2?NOT?NULL, ????????????L_SHIPINSTRUCT?CHAR(25)?NOT?NULL, ????????????L_SHIPMODE?????CHAR(10)?NOT?NULL, ????????????L_COMMENT??????VARCHAR(44)?NOT?NULL ????????????) ????????????DUPLICATE?KEY(L_ORDERKEY,?L_PARTKEY,?L_SUPPKEY,?L_LINENUMBER) ????????????PARTITION?BY?RANGE(`L_SHIPDATE`) ????????????( ????????????????PARTITION?`p202301`?VALUES?LESS?THAN?("2017-02-01")?("storage_policy"?=?"${policy_name}"), ????????????????PARTITION?`p202302`?VALUES?LESS?THAN?("2017-03-01") ????????????) ????????????DISTRIBUTED?BY?HASH(L_ORDERKEY)?BUCKETS?3 ????????????PROPERTIES?( ????????????"replication_num"?=?"3" ????????????)這張 Lineitem1 設(shè)置了兩個(gè)分區(qū),每個(gè)分區(qū) 3 個(gè) Bucket,另外副本數(shù)設(shè)置為 3,可以計(jì)算出一共有 2*3 = 6 個(gè) Tablet,那么副本數(shù)一共是 6*3 = 18 個(gè) Replica,通過(guò)show tablets命令可以查看到所有的 Tablet 以及 Replica 的信息,可以看到只有部分 Tablet 的 Replica 是設(shè)置了CooldownReplicaId 和 CooldownMetaId 。 用戶(hù)可以通過(guò)ADMIN SHOW REPLICA STATUS FROM TABLE PARTITION(PARTITION)查看 Partition 下的 Tablet 以及Replica,通過(guò)對(duì)比可以發(fā)現(xiàn)其中只有屬于 p202301 這個(gè) Partition 的 Tablet 的 Replica 設(shè)置了CooldownReplicaId 和 CooldownMetaId,而屬于 p202302 這個(gè) Partition 下的數(shù)據(jù)沒(méi)有設(shè)置,所以依舊會(huì)全部存放到本地磁盤(pán)。以上表的 Tablet 3691990 為例,該 Tablet 屬于 p202301,截取 show tablets 拿到的部分關(guān)鍵信息如下:
***************************************************************** ???????????????TabletId:?3691990 ??????????????ReplicaId:?3691991 ??????CooldownReplicaId:?3691993 ?????????CooldownMetaId:?TUniqueId(hi:-7401335798601697108,?lo:3253711199097733258) ***************************************************************** ???????????????TabletId:?3691990 ??????????????ReplicaId:?3691992 ??????CooldownReplicaId:?3691993 ?????????CooldownMetaId:?TUniqueId(hi:-7401335798601697108,?lo:3253711199097733258) ***************************************************************** ???????????????TabletId:?3691990 ??????????????ReplicaId:?3691993 ??????CooldownReplicaId:?3691993 ?????????CooldownMetaId:?TUniqueId(hi:-7401335798601697108,?lo:3253711199097733258)? 可以觀察到 3691990 的 3 個(gè)副本都選擇了 3691993 副本作為 CooldownReplica,在用戶(hù)指定的 Resource 上也只會(huì)保存這個(gè)副本的數(shù)據(jù)。
4. 查看數(shù)據(jù)信息
我們可以按照上述 3 中的 Linetem1 來(lái)演示如何查看是使用冷熱數(shù)據(jù)分層策略的 Table 的數(shù)據(jù)信息,一般可以通過(guò)show tablets from lineitem1?直接查看這張表的 Tablet 信息。Tablet 信息中區(qū)分了 LocalDataSize 和 RemoteDataSize,前者表示存儲(chǔ)在本地的數(shù)據(jù),后者表示已經(jīng)冷卻并移動(dòng)到對(duì)象存儲(chǔ)上的數(shù)據(jù)。具體信息可見(jiàn)下方代碼: 下方為數(shù)據(jù)剛導(dǎo)入到 BE 時(shí)的數(shù)據(jù)信息,可以看到數(shù)據(jù)還全部存儲(chǔ)在本地。
***************************?1.?row?***************************
???????????????TabletId:?2749703 ??????????????ReplicaId:?2749704 ??????????????BackendId:?10090 ?????????????SchemaHash:?1159194262 ????????????????Version:?3 ??????LstSuccessVersion:?3 ???????LstFailedVersion:?-1 ??????????LstFailedTime:?NULL ??????????LocalDataSize:?73001235 ?????????RemoteDataSize:?0 ???????????????RowCount:?1996567 ??????????????????State:?NORMAL LstConsistencyCheckTime:?NULL ???????????CheckVersion:?-1 ???????????VersionCount:?3 ??????????????QueryHits:?0 ???????????????PathHash:?-8567514893400420464 ????????????????MetaUrl:?http://172.16.0.8:6781/api/meta/header/2749703 ???????CompactionStatus:?http://172.16.0.8:6781/api/compaction/show?tablet_id=2749703 ??????CooldownReplicaId:?2749704 ?????????CooldownMetaId:? 當(dāng)數(shù)據(jù)到達(dá)冷卻時(shí)間后,再次進(jìn)行?show tablets from table可以看到對(duì)應(yīng)的數(shù)據(jù)變化。
***************************?1.?row?*************************** ???????????????TabletId:?2749703 ??????????????ReplicaId:?2749704 ??????????????BackendId:?10090 ?????????????SchemaHash:?1159194262 ????????????????Version:?3 ??????LstSuccessVersion:?3 ???????LstFailedVersion:?-1 ??????????LstFailedTime:?NULL ??????????LocalDataSize:?0 ?????????RemoteDataSize:?73001235 ???????????????RowCount:?1996567 ??????????????????State:?NORMAL LstConsistencyCheckTime:?NULL ???????????CheckVersion:?-1 ???????????VersionCount:?3 ??????????????QueryHits:?0 ???????????????PathHash:?-8567514893400420464 ????????????????MetaUrl:?http://172.16.0.8:6781/api/meta/header/2749703 ???????CompactionStatus:?http://172.16.0.8:6781/api/compaction/show?tablet_id=2749703 ??????CooldownReplicaId:?2749704 ?????????CooldownMetaId:?TUniqueId(hi:-8697097432131255833,?lo:9213158865768502666)? 除了通過(guò)上述命令查看數(shù)據(jù)信息之外,我們也可以在對(duì)象存儲(chǔ)上查看冷數(shù)據(jù)的信息。以騰訊云為例,可以在 Policy 指定的 Bucket 的 Path 下可以查看冷卻過(guò)后的數(shù)據(jù)的信息:
?
?
進(jìn)入對(duì)應(yīng)文件后可以看到數(shù)據(jù)和元數(shù)據(jù)文件
我們可以看到在對(duì)象存儲(chǔ)上數(shù)據(jù)是單副本
5. 查詢(xún)
假設(shè) Table Lineitem1 中的所有數(shù)據(jù)都已經(jīng)冷卻并且上傳到對(duì)象存儲(chǔ)中,如果用戶(hù)在 Lineitem1 上進(jìn)行對(duì)應(yīng)的查詢(xún),Doris 會(huì)根據(jù)對(duì)應(yīng) Partition 使用的 Policy 信息找到對(duì)應(yīng)的 Bucket 的 Root Path,并根據(jù)不同 Tablet 下的 Rowset 信息下載查詢(xún)所需的數(shù)據(jù)到本地進(jìn)行運(yùn)算。 Doris 2.0 在查詢(xún)上進(jìn)行了優(yōu)化,冷數(shù)據(jù)第一次查詢(xún)會(huì)進(jìn)行完整的 S3 網(wǎng)絡(luò) IO,并將 Remote Rowset 的數(shù)據(jù)下載到本地后,存放到對(duì)應(yīng)的 Cache 之中,后續(xù)的查詢(xún)將自動(dòng)命中 Cache,以此來(lái)保證查詢(xún)效率。(性能對(duì)比可見(jiàn)后文評(píng)測(cè)部分)。
6. 冷卻后繼續(xù)導(dǎo)入數(shù)據(jù)
在某些場(chǎng)景下,用戶(hù)需要對(duì)歷史數(shù)據(jù)進(jìn)行數(shù)據(jù)的修正或補(bǔ)充數(shù)據(jù),而新數(shù)據(jù)會(huì)按照分區(qū)列信息導(dǎo)入到對(duì)應(yīng)的 Partition中。在 Doris 中,每次數(shù)據(jù)導(dǎo)入都會(huì)產(chǎn)生一個(gè)新的 Rowset,以保證冷數(shù)據(jù)的 Rowset 在不會(huì)影響新導(dǎo)入數(shù)據(jù)的 Rowset 的前提下,滿(mǎn)足冷熱數(shù)據(jù)同時(shí)存儲(chǔ)的需求。Doris 2.0 的冷熱分層粒度是基于 Rowset 的,當(dāng)?shù)竭_(dá)冷卻時(shí)間時(shí)會(huì)將當(dāng)前滿(mǎn)足條件的 Rowset 全部上傳到 S3 上并刪除本地?cái)?shù)據(jù),之后新導(dǎo)入的數(shù)據(jù)生成的新 Rowset 會(huì)在到達(dá)冷卻時(shí)間后也上傳到 S3。
查詢(xún)性能測(cè)試
為了測(cè)試使用冷熱分層功能之后,查詢(xún)對(duì)象存儲(chǔ)中的數(shù)據(jù)是否占用會(huì)較大網(wǎng)絡(luò) I/O,從而影響查詢(xún)性能,因此我們以 SSB SF100 標(biāo)準(zhǔn)集為例,對(duì)冷熱分層表和非冷熱分層表進(jìn)行了查詢(xún)耗時(shí)的對(duì)比測(cè)試。 配置:均在 3 臺(tái) 16C 64G 的機(jī)器上部署 1FE、3BE 的集群
如上圖所示,在充分預(yù)熱之后(數(shù)據(jù)已經(jīng)緩存在 Cache 中),冷熱分層表共耗時(shí) 5.799s,非冷熱分層表共耗時(shí) 5.822s,由此可知,使用冷熱分層查詢(xún)表和非冷熱分層表的查詢(xún)性能幾乎相同。這表明,使用 Doris 2.0 提供的冷熱分層功能,不會(huì)對(duì)查詢(xún)性能造成的影響。
冷熱分層技術(shù)的具體實(shí)現(xiàn)
存儲(chǔ)方式的優(yōu)化
在 Doris 之前的版本中,數(shù)據(jù)從 SSD 冷卻到 HDD 后,為了保證數(shù)據(jù)的高可用和可靠性,通常會(huì)將一個(gè) Tablet 存儲(chǔ)多份副本在不同 BE 上,為了進(jìn)一步降低成本,我們?cè)?Apache Doris 2.0 版本引入了對(duì)象存儲(chǔ),推出了冷熱分層功能。由于對(duì)象存儲(chǔ)本身具有高可靠高可用性,冷數(shù)據(jù)在對(duì)象存儲(chǔ)上只需要一份即可,元數(shù)據(jù)以及熱數(shù)據(jù)仍然保存在 BE,我們稱(chēng)之為本地副本,本地副本同步冷數(shù)據(jù)的元數(shù)據(jù),這樣就可以實(shí)現(xiàn)多個(gè)本地副本共用一份冷卻數(shù)據(jù)的目的,有效避免冷數(shù)據(jù)占用過(guò)多的存儲(chǔ)空間,從而降低數(shù)據(jù)存儲(chǔ)成本。 具體而言,Doris 的 FE 會(huì)從 Tablet 的所有可用本地副本中選擇一個(gè)本地副本作為上傳數(shù)據(jù)的 Leader,并通過(guò) Doris 的周期匯報(bào)機(jī)制同步 Leader 的信息給其它本地副本。在 Leader 上傳冷卻數(shù)據(jù)時(shí),也會(huì)將冷卻數(shù)據(jù)的元數(shù)據(jù)上傳到對(duì)象存儲(chǔ),以便其他副本同步元數(shù)據(jù)。因此,任何本地副本都可以提供查詢(xún)所需的數(shù)據(jù),同時(shí)也保證了數(shù)據(jù)的高可用性和可靠性。
冷數(shù)據(jù) Compaction
在一些場(chǎng)景下會(huì)有大量修補(bǔ)數(shù)據(jù)的需求,在大量補(bǔ)數(shù)據(jù)的場(chǎng)景下往往需要?jiǎng)h除歷史數(shù)據(jù),刪除可以通過(guò)delete where實(shí)現(xiàn),Doris 在 Compaction 時(shí)會(huì)對(duì)符合刪除條件的數(shù)據(jù)做物理刪除?;谶@些場(chǎng)景,冷熱分層也必須實(shí)現(xiàn)對(duì)冷數(shù)據(jù)進(jìn)行 Compaction,因此在 Doris 2.0 版本中我們支持了對(duì)冷卻到對(duì)象存儲(chǔ)的冷數(shù)據(jù)進(jìn)行 Compaction(ColdDataCompaction)的能力,用戶(hù)可以通過(guò)冷數(shù)據(jù) Compaction,將分散的冷數(shù)據(jù)重新組織并壓縮成更緊湊的格式,從而減少存儲(chǔ)空間的占用,提高存儲(chǔ)效率。
Doris 對(duì)于本地副本是各自進(jìn)行 Compaction,在后續(xù)版本中會(huì)優(yōu)化為單副本進(jìn)行 Compaction。由于冷數(shù)據(jù)只有一份,因此天然的單副本做 Compaction 是最優(yōu)秀方案,同時(shí)也會(huì)簡(jiǎn)化處理數(shù)據(jù)沖突的操作。BE 后臺(tái)線程會(huì)定期從冷卻的 Tablet 按照一定規(guī)則選出 N 個(gè) Tablet 發(fā)起 ColdDataCompaction。與數(shù)據(jù)冷卻流程類(lèi)似,只有 CooldownReplica 能執(zhí)行該 Tablet 的 ColdDataCompaction。Compaction下刷數(shù)據(jù)時(shí)每積累一定大?。J(rèn)5MB)的數(shù)據(jù),就會(huì)上傳一個(gè) Part 到對(duì)象,而不會(huì)占用大量本地存儲(chǔ)空間。Compaction 完成后,CooldownReplica 將冷卻數(shù)據(jù)的元數(shù)據(jù)更新到對(duì)象存儲(chǔ),其他 Replica 只需從對(duì)象存儲(chǔ)同步元數(shù)據(jù),從而大量減少對(duì)象存儲(chǔ)的 IO 和節(jié)點(diǎn)自身的 CPU 開(kāi)銷(xiāo)。
冷數(shù)據(jù) Cache
冷數(shù)據(jù) Cache 在數(shù)據(jù)查詢(xún)中具有重要的作用。冷數(shù)據(jù)通常是數(shù)據(jù)量較大、使用頻率較低的數(shù)據(jù),如果每次查詢(xún)都需要從對(duì)象中讀取,會(huì)導(dǎo)致查詢(xún)效率低下。通過(guò)冷數(shù)據(jù) Cache 技術(shù),可以將冷數(shù)據(jù)緩存在本地磁盤(pán)中,提高數(shù)據(jù)讀取速度,從而提高查詢(xún)效率。而 Cache 的粒度大小直接影響 Cache 的效率,比較大的粒度會(huì)導(dǎo)致 Cache 空間以及帶寬的浪費(fèi),過(guò)小粒度的 Cache 會(huì)導(dǎo)致對(duì)象存儲(chǔ) IO 效率低下,Apache Doris 采用了以 Block 為粒度的 Cache 實(shí)現(xiàn)。 如前文所述,Apache Doris 的冷熱分層會(huì)將冷數(shù)據(jù)上傳到對(duì)象存儲(chǔ)上,上傳成功后本地的數(shù)據(jù)將會(huì)被刪除。因此,后續(xù)涉及到冷數(shù)據(jù)的查詢(xún)均需要對(duì)對(duì)象存儲(chǔ)發(fā)起 IO 。
為了優(yōu)化性能,Apache Doris 實(shí)現(xiàn)了基于了 Block 粒度的 Cache 功能,當(dāng)遠(yuǎn)程數(shù)據(jù)被訪問(wèn)時(shí)會(huì)先將數(shù)據(jù)按照 Block 的粒度下載到本地的 Block Cache 中存儲(chǔ),且 Block Cache 中的數(shù)據(jù)訪問(wèn)性能和非冷熱分層表的數(shù)據(jù)性能一致(可見(jiàn)前文查詢(xún)性能測(cè)試)。 具體來(lái)講,前文提到 Doris 的冷熱分層是在 Rowset 級(jí)別進(jìn)行的,當(dāng)某個(gè) Rowset 在冷卻后其所有的數(shù)據(jù)都會(huì)上傳到對(duì)象存儲(chǔ)上。而 Doris 在進(jìn)行查詢(xún)的時(shí)候會(huì)讀取涉及到的 Tablet 的 Rowset 進(jìn)行數(shù)據(jù)聚合和運(yùn)算,當(dāng)讀取到冷卻的 Rowset 時(shí),會(huì)把查詢(xún)需要的冷數(shù)據(jù)下載到本地 Block Cache 之中。基于性能考量,Doris 的 Cache 按照 Block 對(duì)數(shù)據(jù)進(jìn)行劃分。Block Cache 本身采用的是簡(jiǎn)單的 LRU 策略,可以保證越是使用程度較高數(shù)據(jù)越能在 Block Cache 中存放的久。
寫(xiě)在最后
Apache Doris 2.0 版本實(shí)現(xiàn)了基于對(duì)象存儲(chǔ)的冷熱數(shù)據(jù)分層,該功能可以幫助我們有效降低存儲(chǔ)成本、提高存儲(chǔ)效率,并提高數(shù)據(jù)查詢(xún)和處理效率。未來(lái),Apache Doris 將會(huì)基于冷熱數(shù)據(jù)分層以及彈性計(jì)算節(jié)點(diǎn),為用戶(hù)提供更好的資源彈性、更低的使用成本以及更靈活的負(fù)載隔離服務(wù)。 在前段時(shí)間推出的 Apache Doris 2.0 Alpha 版本中,已經(jīng)實(shí)現(xiàn)了單節(jié)點(diǎn)數(shù)萬(wàn) QPS 的高并發(fā)點(diǎn)查詢(xún)能力、高性能的倒排索引、高效穩(wěn)定的內(nèi)存管理、基于代價(jià)模型的全新查詢(xún)優(yōu)化器以及 Pipeline 執(zhí)行引擎等,與此同時(shí), Apache Doris 2.0 Beta 版本也將于近兩周上線,除了已知功能外,還會(huì)進(jìn)一步支持 Unique 模型上的部分列更新,并將 Pipeline 執(zhí)行引擎、查詢(xún)優(yōu)化器、主鍵模型 Merge-on-Write 等最新特性作為穩(wěn)定功能默認(rèn)開(kāi)啟,并包含了社區(qū)近期對(duì)性能方面的諸多優(yōu)化,詳細(xì)性能測(cè)試結(jié)果敬請(qǐng)期待后續(xù)社區(qū)動(dòng)態(tài)。
作者介紹:
楊勇強(qiáng),SelectDB?聯(lián)合創(chuàng)始人、技術(shù)副總裁 岳靖、程宇軒,SelectDB 存儲(chǔ)層研發(fā)工程師
編輯:黃飛
評(píng)論
查看更多