用TiKV存儲時序數(shù)據(jù)與InfluxDB對比
TiDB是目前當(dāng)紅的NewSQL數(shù)據(jù)庫,在提供高性能讀寫的同時又兼容傳統(tǒng)的RDBMS,其底層的存儲是TiKV。這里我們看一下如果用TiKV存儲時序數(shù)據(jù),其底層數(shù)據(jù)組織形式是怎么樣的,與InfluxDB的數(shù)據(jù)存儲模式相比有何優(yōu)缺點。
時序數(shù)據(jù)庫與傳統(tǒng)數(shù)據(jù)庫對比 首先從上層應(yīng)用的角度對比一下時序數(shù)據(jù)庫與通用型數(shù)據(jù)庫所面對的需求。關(guān)于時序數(shù)據(jù)的細(xì)節(jié),數(shù)據(jù)模型,以及InfluxDB的實現(xiàn),可以參考本人前面有一篇文章:
1. 寫入/讀取操作比例:對于通用的場景,這個比例是比較低的,就算是在高并發(fā)的互聯(lián)網(wǎng)應(yīng)用中,平均比例可能不會超過3:7。但是對于時序數(shù)據(jù)來說,這個比例很可能會超過5:5。而且時序數(shù)據(jù)一旦丟失,就找不回來了,因為時序數(shù)據(jù)都是一次性生成的。所以時序數(shù)據(jù)庫對寫入性能的要求更高。
2. 數(shù)據(jù)刪除:時序數(shù)據(jù)會面臨著大量時間久遠、價值低的數(shù)據(jù)需要清除,需要刪除的數(shù)據(jù)量大致等于新生成的數(shù)據(jù)量。傳統(tǒng)數(shù)據(jù)庫是不會大規(guī)模刪除數(shù)據(jù)的。
3. 數(shù)據(jù)更新:TiDB中存在大量的數(shù)據(jù)更新,比如商品的庫存數(shù)據(jù)、賬戶余額數(shù)據(jù)等。但是時序數(shù)據(jù)都是一次性生成的,不需要更新。而且時序中單點數(shù)據(jù)是沒有意義的,就算錯誤也沒必要修正。對于這個特征,如果將數(shù)據(jù)根據(jù)時間進行range sharding,就會導(dǎo)致冷熱數(shù)據(jù)相對分離,方便于數(shù)據(jù)管理。但是也造成在數(shù)據(jù)寫入時會形成熱點,容易造成單點壓力。
4. 數(shù)據(jù)模型:就目前面對的場景來說,時序數(shù)據(jù)的模型是相對固定的,主要包含timestamp,tags和fields三個部分,而且序列值可以通過timestamp進行組織。相對于RDBMS,這帶來一個優(yōu)勢就是對事務(wù)的支持需求更小。這里需要事務(wù)支持只有一點:數(shù)據(jù)寫入和刪除時同一timestamp對應(yīng)的各個field要一致。
5. 數(shù)據(jù)運算:時序數(shù)據(jù)的應(yīng)用更偏向于在時間軸上進行聚合,或者統(tǒng)計,很少對原始數(shù)據(jù)直接取出來使用。從這一個角度來說,時序數(shù)據(jù)庫的需求有點偏向OLAP。關(guān)于TSDB和OLAP的對比,也有博文進行了詳述[Time series databases vs OLAP](https://medium.com/@itz100ji/time-series-databases-vs-olap-57e8d70309c8)。 所以,時序數(shù)據(jù)庫需要提供高吞吐量、高可用性,但是對事務(wù)支持的需求較小。所以是不是可以說時序數(shù)據(jù)庫是OLTP和OLAP各自的部分結(jié)合,也算是HTAP?
用TiKV存儲時序數(shù)據(jù) 如果直接用TiKV存儲時序數(shù)據(jù),底層存儲結(jié)構(gòu)是什么樣呢?這里我們只討論數(shù)據(jù)在單個TiKV節(jié)點的組織形式,暫時先不管分布式架構(gòu)。 TiKV底層使用的是RocksDB來存儲數(shù)據(jù),RocksDB是基于LSM Tree,是一個Key-Value存儲引擎。TiKV的數(shù)據(jù)存儲原理細(xì)節(jié)建議參考以下博文,里面做了很詳細(xì)的描述,包括底層的組件,以及如何從傳統(tǒng)的RDBMS的數(shù)據(jù)存儲映射到TiKV:
1. [TiKV 是如何存取數(shù)據(jù)的(上)]
2. [TiKV 是如何存儲數(shù)據(jù)的(下)] 所以,這里需要確定的就是怎么設(shè)計RocksDB中數(shù)據(jù)條目的key和value。如前文所說,對于時序數(shù)據(jù),需要存儲的內(nèi)容包括timestamp,tags和fields,還需要在tags上做索引,提高通過tags的檢索的效率。首先是存儲每一個point的數(shù)據(jù),每一個point可以通過measurement,所涉及的所有tags,和timestamp來定位,這三個信息的組合等價于MySQL中的primary key,可以唯一確定一個point。存儲的value就是point的fields。如果我們寫入的數(shù)據(jù)是: ``` Labs,location=SH,host=server1 CUP=73,Mem=16.067 1574179200s Labs,location=SH,host=server2 CUP=31,Mem=32.087 1574179200s Labs,location=SZ,host=server1 CUP=11,Mem=8.021 1574179200s Labs,location=SZ,host=server2 CUP=43,Mem=16.779 1574179200s ``` 在RocksDB里存儲的數(shù)據(jù)條目就是: ``` # Primary Key, 前綴t表示table, 數(shù)據(jù)條目 t_Labs_location=SH,host=server1_1574179200s ==> (73, 16.067) t_Labs_location=SH,host=server2_1574179200s ==> (31, 32.087) t_Labs_location=SZ,host=server1_1574179200s ==> (11, 8.021) t_Labs_location=SZ,host=server2_1574179200s ==> (43, 16.779) ``` 通過primary key定位數(shù)據(jù)非常簡單,直接在RocksDB做查詢。 接著,還需要存儲基于tags的索引。TiKV中索引的組織結(jié)構(gòu)跟InfluxDB的原理是一樣的,也是反向索引。也就是說,給定一組`tag name`和`tag value`對,記錄哪些point與它相關(guān)。所以,索引的key既要包含涉及到的tag,還要包含對應(yīng)的point的primary key。而索引條目的value是無關(guān)緊要的,只需要判斷key是否存在。 ``` # Tags Index, 前綴i表示index, 索引條目 i_location=SH___t_Labs_location=SH,host=server1_1574179200s ==> nil i_host=server1___t_Labs_location=SH,host=server1_1574179200s ==> nil i_location=SH___t_Labs_location=SH,host=server2_1574179200s ==> nil i_host=server2___t_Labs_location=SH,host=server2_1574179200s ==> nil i_location=SZ___t_Labs_location=SZ,host=server1_1574179200s ==> nil i_host=server1___t_Labs_location=SZ,host=server1_1574179200s ==> nil i_location=SZ___t_Labs_location=SZ,host=server2_1574179200s ==> nil i_host=server2___t_Labs_location=SZ,host=server2_1574179200s ==> nil ``` 當(dāng)我們需要通過索引查找時,比如`location=SH`,首先構(gòu)建key前綴`i_location_SH___`,找到以這個前綴開頭的數(shù)據(jù),這個過程在TiKV里面是很高效的,因為它使用了基于key的range sharding。這些查找出來的索引條目的key的后半部分,就是跟給定tag相關(guān)的所有數(shù)據(jù)條目primary key,然后通過這些primary key來檢索對應(yīng)的數(shù)據(jù)條目。
可以看到TiKV的索引和數(shù)據(jù)混合在一起進行存儲,但它們的key-value條目是分開的,所以當(dāng)把MySQL的innodb表轉(zhuǎn)到TiKV后面應(yīng)該會占用更大的空間。
與InfluxDB存儲的對比
1. 索引的構(gòu)建,InfluxDB是使用一個超大的map實現(xiàn)的,這一點我覺得TiKV的構(gòu)建方式更加直觀簡單,也充分利用了kay-value存儲引擎的優(yōu)勢,特別是適合巨量的tags。
2. 時序數(shù)據(jù)常規(guī)操作的性能: - 寫入:二者差不多。首先會寫入數(shù)據(jù)條目,然后會對每一個涉及的tag創(chuàng)建一個索引條目。 - 讀取:時序數(shù)據(jù)最多的是基于tag和timestamp區(qū)間進行檢索。在TiDB里面,第一步需要返回所有的primary key,第二步取出每一個primary key的數(shù)據(jù)條目。InfluxDB的組織方式是基于entry進行存儲,第一步是找到相關(guān)的series,這一步返回數(shù)據(jù)量更少,第二步根據(jù)series找出給定timestamp范圍內(nèi)的數(shù)據(jù)條目,只需要基于少量series輪詢在數(shù)據(jù)庫中檢索。 - 清除:使用TiKV,數(shù)據(jù)的過期刪除策略效率很差,需要遍歷所有數(shù)據(jù)和索引條目,判斷所對應(yīng)的timestamp是否到期。頻繁刪除會影響到數(shù)據(jù)寫入性能。InfluxDB基于timestamp進行sharding,舊的數(shù)據(jù)會存儲在相近的shard里面,很簡單就可以刪除。
3. 存儲空間壓縮效率,InfluxDB的同field的內(nèi)容會按列存儲,同一數(shù)據(jù)類型,有利于壓縮。
4. 分布式解決方案。因為InfluxDB Cluster是閉源的,而TiDB又開源支持,所以TiDB勝。 根據(jù)上面的對比,對于時序數(shù)據(jù)的存儲,InfluxDB更專業(yè)。但是如果需要其分布式解決方案,要么得買,要么得自己實現(xiàn)解決。
聲明:免責(zé)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻自行上傳,本網(wǎng)站不擁有所有權(quán),也不承認(rèn)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內(nèi)容,請發(fā)
送郵件至:operations@xinnet.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,本站將立刻刪除涉嫌侵權(quán)內(nèi)容。本站原創(chuàng)內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時
需注明出處:新網(wǎng)idc知識百科