最近参加的物联网竞赛有涉及到实时数据统计的大数据分析,mysql可能不太适合,到处找来找去,最后感觉InfluxDB可能比较合适。今天稍微看了下感觉对于时序数据的处理上InfluxDB相对于mysql来说确实有压倒性的优势,稍微做个总结。
1 数据存储形式
measurement:
point = timestamp + tags + fields...
point...
point...
相对于mysql来说,measurement = table,point = raw, timestamp = primaryKeyField,tags = indexField,fields = fields
2 存储结构
2.1 retentionpolicy
InfluxDB通过retentionpolicy设置数据保留时间,每隔这样一段时间会扫描一遍所有shard的时间范围,将过期的shard直接删掉。
2.2 shard
(1)shard创建
在插入第一条数据时,会创建一个shard,并将插入数据的时间戳作为shard的左区间(如果是时序数据的话,并不需要插入时间戳,InfluxDB会跟mysql主键一样生成当前时间戳),然后根据retentionpolicy设置的数据保留时间确定一个shard右区间,在未来这样一段时间区间范围内所插入的数据最终都会被插入到这个shard下的tsmfile中。当插入的数据时间超出这个时间区间后,将创建新的shard。
(2)shard组成
每个shard都有自己的cache、wal、tsmfile、compactor,感觉的话其实就相当于一个微型数据库了。
(3)shard作用
先说下结果,通过shard,对于时序数据,InfluxDB可以实现高性能的增、删、查。下面通过对比mysql对于时序数据的处理进行分析。
InfluxDB中,每个shard下的tsmfile都是在一个时间区间内的,可以确定,shard的时间区间应该是能被retentionpolicy设置的保留数据时间整除的,因此retentionpolicy设置的保留数据时间到了直接删除这个shard下的所有内容即可,就像删除磁盘下的一个目录一样,不必考虑里面装了什么,因此InfluxDB删除性能极高。
Mysql将表数据分成数据页进行存放,且时间不能作为主键,对于存储的时序数据只能通过索引进行查找。这样会造成两点性能上的消耗:
- mysql对时序数据进行批量删除需要到表中进行扫描。而InfluxDB不用。
- 进行扫描时通过索引查找对应数据需要先经过一次B+tree的遍历拿到这条数据的主键,再进行一次B+tree遍历找到这条数据,然后进行删除。而InfluxDB不用。这一点不光对删除性能造成了影响,更是对查询性能造成了影响。
另外,对于插入而言,InfluxDB会将插入的数据会先到缓存的cache中,当cache到达缓存上限之后进行快照,写入tsmfile。对于时序数据而言,cache中的数据最终几乎就是写入当前shard下的tsmfile中的,因此插入性能稳定。
而mysql会将索引加载到缓存中,面对海量数据时,内存的大小几乎就成了mysql插入性能的上限约束。因此对于时序数据而言,InfluxDB的插入性能稳定性相对于mysql更好。
这里提醒一点,使用InfluxDB存放的数据最好是正常的时序数据,即写入时间戳是顺序的而不是凌乱的。因为只有当写入数据是顺序的时候才能使InfluxDB只专注于当前的shard,以及避免数据在快照中的排序。否则数据会根据每条数据的时间戳去路由寻找所属区间的shard下的tsmfile文件进行插入,这会对性能造成一些影响。
2.3 cache
cache在功能上而言其实与mysql中的缓存区差别不大。大小有限制,默认25MB,到达上限后进行一次快照,然后清除这个cache,快照版本中的数据按照timestamp排序后写入tsm文件中。实际上这里的排序在插入时基本是不用排的,因为时序数据的timestamp本来就是顺序的。
之前cache存在一个问题,就是当第一个cache被充满后生成的快照还未写完时,大量数据涌入使cache又达到了阈值,从而生成新的快照,两个快照的数据同时写入当前的tsmfile,会导致最终存储的这部分数据并不是按时间戳顺序的。InfluxDB一直都在更新,笔者并不知道现在这个问题解决没有。
2.4 wal
wal在功能上而言又与mysql中的bin.log相类似。它的内容与cache完全相同,其作用就是为了防止数据丢失,当InfluxDB出问题后可以通过wal将之前的内容copy到cache中。