Part 1 - 背景

Redis作为一个灵便的高性能 key-value数据结构存储,能够用来作为数据库、缓存和音讯队列。Redis 比照其余 key-value缓存产品有以下特点:

Redis 反对数据的长久化,能够将内存中的数据保留在磁盘中,重启的时候能够再次加载到内存应用。

Redis 反对字符串(String)、哈希(Hash)、列表(list)、汇合(sets)和有序汇合(sorted sets)等数据结构的存储。

时序数据是指一串依照工夫维度索引的数据,其特点是没有严格的关系模型,记录的信息能够示意成键和值的关系,因而并不需要关系型数据库进行保留。在理论利用中,时序数据通常是继续高并发写入的。针对时序数据的这一个性,Redis基于本身数据结构和扩大模块,提供了用于保留工夫序列数据的两种计划:

1、基于Hash和Sorted Set数据保留工夫序列数据;

2、基于RedisTimeSeries模块实现。

1.基于Hash保留工夫序列数据

基于Hash保留工夫序列数据的特点是能够实现对单键的疾速查问,可能满足对工夫序列数据的单键查问需要。Redis的Hash实现形式是将外部存储的value作为一个HashMap,并提供了用于直接存取Map成员的接口,将工夫戳作为Hash汇合的key,设施状态值作为Hash汇合的value,因而对数据的批改和存取都可间接通过其外部Map的Key来实现操作对应属性数据,既不须要反复存储数据,也不会带来序列化和并发批改管制的问题。

然而,基于Hash保留工夫序列数据的短板在于无奈反对对数据的范畴查问,尽管工夫序列是依照工夫程序插入Hash汇合的,然而Hash类型的底层构造是Hash表,并没有实现对数据的有序索引,因而要对Hash类型进行范畴查问,则须要扫描Hash汇合中的所有数据,再将这些数据取回客户端进行排序,之后能力在客户端失去查问范畴内的数据,查问效率很低。

2、基于Sorted Set保留工夫序列数据

基于Sorted Set保留工夫序列数据的特点是可能同时反对按工夫戳范畴的查问,可能依据元素的权重值来排序,在时序数据的状况下,将工夫戳作为Sorted Set汇合的权重值,后跟工夫点上记录的测量数据,例如:<工夫戳>:<测量值>。RedisSorte Set的外部应用Hash Map和SkipList来保证数据的存储有序,应用SkipList的构造能够保障具备较高的查问效率,并且在实现上比较简单。

然而,基于Sorted Set保留工夫序列数据策略的短板在于其仅仅能反对范畴查问,无奈间接实现对时序数据的聚合计算。因而,只能先把工夫范畴内的数据取回到客户端,而后在客户端自行实现聚合计算。这个办法尽管能实现聚合计算,然而会带来肯定的潜在危险,也就是大量数据在Redis实例和客户端间频繁传输,这会和其余操作命令竞争网络资源,导致其余操作变慢。因而SortedSets 不是一种节约内存的数据结构,其插入的工夫复杂度是 O(log(N)),因而集群越大,写入耗时越长。

综合来讲,基于Hash和SortedSet保留工夫序列的策略短板次要蕴含两个方面:其一是当执行聚合计算时,须要把数据读取到客户端内再进行聚合,当存在大量数据须要聚合时,数据传输开销大;其二是当应用该策略时,所有的数据会在两个数据类型中各保留一份,内存开销大。

2、基于RedisTimeSeries保留工夫序列数据

RedisTimeSeries作为Redis的一个扩大模块,它补救了Redis基于Hash和Sorted Set保留工夫序列数据内存和数据传输开销大的缺点,它专门面向工夫序列数据提供了数据类型和拜访接口,并且反对在Redis端上间接对数据进行工夫范畴的聚合计算。它应用固定大小的内存块作为工夫序列样本,采纳与Redis Streams 雷同的Radix Tree来实现索引。RedisTimeSeries 的底层数据结构应用了链表,范畴查问的复杂度是 O(N) 级别。这种基于RedisTimeSeries保留工夫序列数据的策略具备以下特点:

保障大容量插入,低提早读取;

按开始工夫和完结工夫查问;

反对任何工夫桶的聚合查问(min、max、avg、sum、range、count、first、last);反对配置保留工夫;

下采样/压缩-自动更新的聚合工夫序列;

二级索引-每个工夫序列都有标签,容许按标签查问。

Part 2 - RedisTimeSeries存储构造

RedisTimeSeries将所有的时序数据存储在chunks中。每个chunks均由双向链表中的两个相干数组组成(一个用于工夫戳,一个用于样本值)。每个chunks都有预约义的样本大小,当chunks填满的时候,其余数据将主动存储到下一个chunks。chunks size能够通过参数 CHUNK_SIZE进行设置。(CHUNK_SIZE的设置必须为8的倍数,默认值:4096)

RedisTimeSeries的Key由metric指标和tags组成,其中每个Sample是工夫和值的组合。标签是咱们附加到数据点的键值元数据,容许咱们进行分组和过滤。它们能够是字符串或数值,并在创立时增加到工夫序列。

Part 3 - RedisTimeSeries的应用

当用于工夫序列数据存取时,RedisTimeSeries的操作次要蕴含以下几个方面:

1、TS.CREATE命令

TS.CREATE命令用于创立工夫序列数据汇合,应用时须要设置工夫序列数据汇合的key和数据过期工夫(以毫秒为单位)。还能够为数据汇合设置标签,来示意数据汇合的属性。阐明:

RETENTION:选填,数据保留工夫,默认:0;

ENCODING:选填,指定系列样本编码格局,分为COMPRESSED、UNCOMPRESSED两种格局;

CHUNK_SIZE:选填,块的大小;

DUPLICATE_POLICY:选填,配置对反复样本执行的操作,默认BLOCK梗塞状态。状态类型:(BLOCK,FIRST,LAST,MIN,MAX,SUM)

LABELS:必填,数据标签。

实例1:

2、TS.ADD命令

TS.ADD命令用于向工夫序列汇合中插入数据,其中包含工夫戳和具体的数值。若先前尚未应用TS.CREATE创立工夫序列,将主动创立时序数据汇合。

留神:不能向最初一次应用的工夫戳之前增加数据。应用 TS.ADD 命令增加值的工夫戳必须要大于最初一个值的工夫戳。

实例2:

也能够应用 * 让Redis将主动生成工夫戳。

实例3:

TS.MADD命令用于向已存在的工夫序列汇合中插入新样本数据。

实例4:

3、TS.GET命令

TS.GET命令用于读取工夫序列汇合的最新数据。

实例5:

TS.MGET命令用于按标签查问汇合中的最新数据。在应用TS.CREATE创立数据汇合时,能够给汇合设置标签属性。当进行查问时,就能够在查问条件中依据汇合标签属性对数据样本进行匹配,其查问后果只返回满足匹配汇合的最新数据。

实例6:

下列TS.MGET命令,以及FILTER设置(这个配置项用来于设置汇合标签的过滤条件),查问area_id等于32的所有数据汇合,并返回各自汇合中最新一条数据。

4、TS.RANGE/TS.RERANGE命令

TS.RANGE/RERANGE命令用于反对工夫序列汇合聚合计算的范畴查问;

阐明:

[FILTER_BY_TS]:选填,依照工夫戳过滤样本数据;

[FILTER_BY_VALUES]:选填,依照value值过滤样本数据;

[COUNT]:选填,返回样本的最大数量。

[AGGREGATION]:选填,指定要执行的聚合计算类型,RedisTimeSeries反对的聚合计算类型很丰盛,包含AVG、MAX、MIN、SUM、COUNT、LAST、FIRST。

实例7:

TS.MRANGE命令通过FILTERS过滤查问跨多个工夫序列的范畴。

阐明:

[GROUPBY]:汇总不同工夫序列的后果,按提供的label名称分组;

[REDUCE]:用于聚合具备雷同标签值得系列的reducer类型。

实例:


5、RedisTimeSeries其余命令

TS.DEL KEY_NAME FROM_TIMESTAMP TO_TIMESTAMP:删除给定KEY_NAME的工夫戳范畴内的值;

DEL KEY_NAME:删除已创立的KEY;

TS.ALTER KEY_NAME [RETENTION] LABELS:更改已创立键的元数据,包含label和保留值;

TS.INCREBY/TS.DECREBY:在最新数据上减少/缩小某个值;

TS.INFO: 返回工夫序列的信息和统计数据;

KEYS *:获取所有KEY;

EXISTS KEY_NAME: 查看给定KEY是否存在,若存在返回1,否返回0。

Part 4 - 总结

RedisTimeSeries作为Redis的一种扩大模块,它的呈现为时序数据的存取提供了一种新办法,具备高效的查问性能,并且在存取过程中仅需很小的开销,便可能实现时序数据实时剖析的欲望。