• redis之如何存储时间序列数据


    写在前面

    在这里插入图片描述
    本文一起来看下redis如何处理时序数据。

    1:什么是时序数据

    随着时间的推移不断产生的数据,就是时序数据,比如设备的运行状态,每隔一分钟产生一组状态指标,这些标记了设备不同时刻运行状态的数据,就是时序数据的一种,而专门用来存储这些数据的数据库我们可以叫做是TSDB(time series database,即时序数据库),比如InfluxDB,TDengine,就是这一类的数据库,本文所包含的RedisTimeSeries准确来说也属于这个范畴,但是是通过redis扩展模块方式实现的。

    2:提出需求

    假设现在有这样的需求,需要收集设备的运行信息,包括设备温度,湿度,压强等信息,而这些信息每隔3分钟就会上报一次,并且需要满足如下要求:

    1:数据插入速度快
    2:支持点查询,即查询一个点的数据
    3:支持范围查询,即查询某时间范围内的数据
    4:支持聚合操作,如max,avg等
    
    • 1
    • 2
    • 3
    • 4

    对于"1:数据插入速度快 “,正常情况下redis满足需求,对于"2:支持点查询,即查询一个点的数据”,我们可以使用hash存储,像下图:
    在这里插入图片描述
    对于"3:支持范围查询,即查询某时间范围内的数据"我们可以使用set来实现,比如使用时间当分数,然后使用ZRANGEBYSCORE 就可以实现范围查询了,如下图:
    在这里插入图片描述

    因此到这里,我们需要将数据在hash结构和sorted set结构中各存储一份,接下来就需要考虑原子性的问题,两边的数据如果是不一致的,则会出现业务上的错误,为了解决这个问题,我们需要用到redis提供的简单事务支持 ,如下原理和实例:
    在这里插入图片描述在这里插入图片描述

    对于"4:支持聚合操作,如max,avg等",我们就需要将数据读取到客户端来计算结果了,而这种方式有个问题就是,如果数据过大的话会大量占用服务器的网络资源,可能会影响到正常业务请求,此时我们可以考虑使用RedisTimeSeries了,这也正是本文我们要分析的重点,RedisTimeSeries是redis的扩展模块,需要获取对应的动态链接库,然后加载模块到redis的功能中,这里的动态链接库是redistimeseries.so,可以通过如下的几种方式获取:

    1:编译源代码
    2:从对应的docker镜像中获取
    3:下载我已经获取的
    
    • 1
    • 2
    • 3

    对于1,我没有成功,因为github我访问不了o(╥﹏╥)o,对于2 操作如下:

    [root@localhost RedisTimeSeries]# docker pull redislabs/redistimeseries
    Using default tag: latest
    Trying to pull repository docker.io/redislabs/redistimeseries ... 
    latest: Pulling from docker.io/redislabs/redistimeseries
    6ec7b7d162b2: Pull complete 
    ...
    50e2b1edfcc3: Pull complete 
    Digest: sha256:98e18d974673da04f009bb36e403ee797faed24560a291bf57b9e8a727e3151d
    Status: Downloaded newer image for docker.io/redislabs/redistimeseries:latest
    
    [root@localhost RedisTimeSeries]# docker run docker.io/redislabs/redistimeseries
    1:C 08 Nov 2022 08:35:39.196 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    ...
    1:M 08 Nov 2022 08:35:39.198 * Module 'timeseries' loaded from /usr/lib/redis/modules/redistimeseries.so
    1:M 08 Nov 2022 08:35:39.198 * Ready to accept connections
    
    [root@localhost ~]# docker cp heuristic_cori:/usr/lib/redis/modules/redistimeseries.so /root/study
    [root@localhost ~]# cd /root/study/
    [root@localhost study]# ll
    total 152
    ...
    -rwxr-xr-x.  1 root root 147576 Jul  5  2021 redistimeseries.so
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    对于3可以从这里 下载。动态链接库准备完毕后,需要配置到redis.conf中如下:

    loadmodule /root/study/redistimeseries.so DUPLICATE_POLICY LAST
    
    • 1

    具体路径注意修改成自己的,接下来看下具体数据操作。

    • 插入数据
      插入数据前必须先通过TS.CREATE来创建集合,格式TS.CREATE key RETENTION 超时毫秒数 LABELS 标签名称 标签值 标签名称 标签值,集合创建完毕后通过TS.ADD来向集合中插入数据,格式TS.ADD key 秒值 值,如下我们测试创建记录4个设备的温度信息的集合,四个设备的设备ID假设分别为AAAA,BBBB,CCCC,DDDD,如下首先创建集合:
    127.0.0.1:6379> TS.CREATE device:temperature:AAAA RETENTION 600000 LABELS device_id AAAA
    OK
    127.0.0.1:6379> TS.CREATE device:temperature:BBBB RETENTION 600000 LABELS device_id BBBB
    OK
    127.0.0.1:6379> TS.CREATE device:temperature:CCCC RETENTION 600000 LABELS device_id CCCC
    OK
    127.0.0.1:6379> TS.CREATE device:temperature:DDDD RETENTION 600000 LABELS device_id DDDD
    OK
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    然后向其中分别插入一些测试数据:

    127.0.0.1:6379> TS.ADD device:temperature:AAAA 1667980462 66.5
    (integer) 1667980462
    127.0.0.1:6379> TS.ADD device:temperature:AAAA 1667980463 69.3
    (integer) 1667980463
    127.0.0.1:6379> TS.ADD device:temperature:BBBB 1667980468 79.3
    (integer) 1667980468
    127.0.0.1:6379> TS.ADD device:temperature:BBBB 1667980469 79.5
    (integer) 1667980469
    127.0.0.1:6379> TS.ADD device:temperature:CCCC 1667980470 79.4
    (integer) 1667980470
    127.0.0.1:6379> TS.ADD device:temperature:CCCC 1667980471 77.4
    (integer) 1667980471
    127.0.0.1:6379> TS.ADD device:temperature:DDDD 1667980477 79.4
    (integer) 1667980477
    127.0.0.1:6379> TS.ADD device:temperature:DDDD 1667980478 79.9
    (integer) 1667980478
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 查询最新的一条数据
      命令TS:GET,格式TS:GET key options,会返回最新的一条数据,如下:
    127.0.0.1:6379> TS.GET device:temperature:AAAA
    1) (integer) 1667980463
    2) 69.3
    127.0.0.1:6379> TS.GET device:temperature:BBBB
    1) (integer) 1667980469
    2) 79.5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 查询一批最新数据
      命令TS.MGET ,格式TS.MGET FILTER 基于标签的表达式,如下:
    127.0.0.1:6379> TS.MGET filter device_id=DDDD
    1) 1) "device:temperature:DDDD"
       2) (empty list or set)
       3) 1) (integer) 1667980478
          2) 79.9
    127.0.0.1:6379> TS.MGET withlabels filter device_id=DDDD
    1) 1) "device:temperature:DDDD"
       2) 1) 1) "device_id"
             2) "DDDD"
       3) 1) (integer) 1667980478
          2) 79.9
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 聚合运算
      使用命令TS.RANGE,格式TS.RANGE key 开始时间 结束时间 AGGREGATION [avg|max|min|sum等] 时间窗口毫秒数,其中时间窗口毫秒数意思是,指定的时间范围内多长的时间区间执行指定的聚合运算,如下:
    127.0.0.1:6379> TS.RANGE device:temperature:AAAA 1667980462 1667980463 AGGREGATION sum 180000
    1) 1) (integer) 1667880000
       2) 135.8
    
    • 1
    • 2
    • 3

    写在后面

    参考文章列表:

    时间序列数据库 (TSDB)

  • 相关阅读:
    06-JS字符串
    Spring Cloud Stream消息驱动组件
    Java编程练习题:面向对象练习
    Mysql集群及高可用-Gtid模式2
    本地客户端连接阿里云Redis服务器
    算法---水壶问题(DFS)
    【LeetCode】310c:将区间分为最少组数
    华为7年经验的软件测试总监,给所有想转行学软件测试的朋友几点建议
    数组对象中某个值累加reduce
    java计算机毕业设计-图片展示及购买网站-源程序+mysql+系统+lw文档+远程调试
  • 原文地址:https://blog.csdn.net/wang0907/article/details/127772897