乐趣区

关于数据库:深入浅出RedisTimeSeries分布式数据库

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

退出移动版