关于时间序列数据库的思考——(1)运用hash文件(例如:RRD,Whisper) (2)运用LSM树来备份(例如:LevelDB,RocksDB,Cassandra) (3)运用B-树排序和k/v存储(例如:BoltDB,LMDB)
转自:http://0351slc.com/portal.php?mod=view&aid=12
近期网络上呈现了有关catena、benchmarking boltdb等时刻序列存储办法的介绍,Go社区也有相似的谈论论题,呈现了seriesly、influxDB、prometheus等优异项目。原文作者Jason moiron现在从事Datadog有关工作,文中他关于时刻序列数据库宣布了一些观点,(网友们在Hacker News上也有精彩的谈论)咱们一起来认识下。
时刻序列模型和图形式先于计算机呈现,可是直到90年代初伴随着MRTG的呈现才逐步发展壮大。这些体系的不断老练是有缘由的:“大数据”的“岂止于大”;虚拟化和容器化带来了可观的分布式运用节点增量;云效劳对摩尔定律提出了挑战。
时刻序列存储层(Time-series Storage Layer)
大家常常会这么问自己:
- 有对写入进行优化吗?
- 有对读取进行优化吗?
- 数据库要支援哪种语义学才干运用户得到想要的查询成果呢?
假如前两个疑问的答案是“是”,存储层就必须一起对写入和读取进行优化。
假如你企图对一个已索引的数据库进行多个序列写入,幻想下这是一个富含主键,时刻戳,值等数据的SQL表,那么当要处理读请求时就不得不处理巨大的数据。假如你把序列分隔写入,那么这或许是最差劲的写入形式:高频跨数据写入。
我看到有的开发者的做法是:
- 运用文件(例如:RRD,Whisper)
- 运用LSM树来备份(例如:LevelDB,RocksDB,Cassandra)
- 运用B-树排序和k/v存储(例如:BoltDB,LMDB)
这些做法有长处也有缺点。这儿无妨测验别的办法,时刻序列是一个多点矢量,因而要做的本来很简略:
- 创立一个新矢量
- 找出一个矢量(不一样的)
- 附加到矢量上(0(1))
- 从矢量读取数据
运用文件
显然一切数据库都是“文件式”的,但我这儿所指的是文件即序列(file-as-a-series)的办法。透过该办法,你能够得到高效的缓冲附加并可进行自在的缓存线性读取。关于高档文件体系如zfs,ext4,xfs等来说,目录记录查找是根据hash表的,也即意味着是0(1)。
文件体系越来越杂乱而变得难于了解,因而需求一些黑艺术来对它进行调节。虽然有些体系的规划意图是为了处理百万级的文件,可是还没有专门关于小文件而做的优化处理。这么就致使了关于少数数据查询来说,许多时分都会存在空页浏览的状况。最后,会遍历整个数据集,这关于备份,批量工作等操作都是有主要影响的。
运用根据树的存储办法
当运用根据树的KV存储办法时,能够有几种完成办法。键能够辨认一个单序列,或一个单点,或一个序列中的某个时刻片。无论你的键构造甚或树相似的选择是什么,键查找都会是O(log n),然后在表上会留有许多空白。
关于大规模存储时,假如点的数量过于巨大,这关于CPU缓存是个灾祸;因而把数据看成是{series, timestamp} -> {point}的KV对是不会工作的。关于小规模数据,开源时刻序列存储是测验运用相似的办法来处理,可是我很有信心肠说,换用文件会愈加简略和方便,除非你要常常读取很许多的数据集。关于O(log n)查找,我可不想在读取上花费许多时刻。
所以接下来要重视写入端,这是一个难点。运用双B树的COW办法看起来不适合于许多的随机写入。在实践中这无妨做进一步的研究。一切这些运用mmap及频频微量写入时,会对你的数据库形成许多页阅览,然后致使f/msync的I/O处于高负荷状况。附加在LSM上也许状况会好些,可是树兼并紧缩操作也是一个高强度工作。
总的来说,树关于写入和读取都是能够统筹的,这是极好的互补办法。
查询语义
我以为时刻序列存储所需的仅有语义支撑应该是能够进行批量和并行读取;而其他的如紧缩读取规模,非常好的外部完成,还有对时刻序列存储的束缚等都是加分项。
维度
根据我的开发经验,发现维度是至关主要的;从商品层面看,缺少对它的支撑将会使你的商品被替代。
把一切的元数据都存入衡量键中,然后以键/值(K/V)查找的办法来进行查询不最优的处理办法;你最少要具有or/and和逻辑操作来完成跨维度;例如:eg: az=us-east-1 AND role=db-master, version=2.1 OR version=2.3,若有更丰厚操作的言语则非常好。但关于存储层来说需求支援任何的额定语义来完成这些优化吗?在维度存储中,查询中的索引要么指向了许多无关数据的元组,要么包含了数据自身然后致使写入缓慢。SSD办法或许好些,但仍需读取一切数据页才有效;数据方位仍是个疑问。
聚合,失效等
时刻聚合和数据失效在轮询调度中的主要性显而易见,这仍是开源的规范。例如rrdtool,graphite等。
此外还有几个主要疑问亟需处理。RRD是连续空间,但时刻序列的运用通常包含了许多的稀少序列。别的,关于写入的紧缩/聚合会使写入操作变得巨大。聚合和失效看起来很像维度:能够在一个独立策略层中异步完成。