Redis 核心技术与实战
蒋德钧
中科院计算所副研究员
81696 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 53 讲
开篇词 (1讲)
实践篇 (28讲)
Redis 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

14 | 如何在Redis中保存时间序列数据?

优劣势
不足
优势
TS.RANGE命令
TS.MGET命令
TS.GET命令
TS.ADD命令
TS.CREATE命令
EXEC命令
MULTI命令
需要保证写入Hash和Sorted Set是一个原子性的操作
支持范围查询
不支持范围查询
单键查询
聚合计算
时间范围内数据查询
单条记录查询
选择的数据类型要求
插入数据快
每课一问
第二种方案
第一种方案
RedisTimeSeries的操作
Redis的事务支持和原子性保证
Sorted Set类型
Hash类型
数据读取特点
数据写入特点
小结
基于RedisTimeSeries模块保存时间序列数据
基于Hash和Sorted Set保存时间序列数据
时间序列数据的读写特点
如何在Redis中保存时间序列数据?

该思维导图由 AI 生成,仅供参考

你好,我是蒋德钧。
我们现在做互联网产品的时候,都有这么一个需求:记录用户在网站或者 App 上的点击行为数据,来分析用户行为。这里的数据一般包括用户 ID、行为类型(例如浏览、登录、下单等)、行为发生的时间戳:
UserID, Type, TimeStamp
我之前做过的一个物联网项目的数据存取需求,和这个很相似。我们需要周期性地统计近万台设备的实时状态,包括设备 ID、压力、温度、湿度,以及对应的时间戳:
DeviceID, Pressure, Temperature, Humidity, TimeStamp
这些与发生时间相关的一组数据,就是时间序列数据。这些数据的特点是没有严格的关系模型,记录的信息可以表示成键和值的关系(例如,一个设备 ID 对应一条记录),所以,并不需要专门用关系型数据库(例如 MySQL)来保存。而 Redis 的键值数据模型,正好可以满足这里的数据存取需求。Redis 基于自身数据结构以及扩展模块,提供了两种解决方案。
这节课,我就以物联网场景中统计设备状态指标值为例,和你聊聊不同解决方案的做法和优缺点。
俗话说,“知己知彼,百战百胜”,我们就先从时间序列数据的读写特点开始,看看到底应该采用什么样的数据类型来保存吧。

时间序列数据的读写特点

在实际应用中,时间序列数据通常是持续高并发写入的,例如,需要连续记录数万个设备的实时状态值。同时,时间序列数据的写入主要就是插入新数据,而不是更新一个已存在的数据,也就是说,一个时间序列数据被记录后通常就不会变了,因为它就代表了一个设备在某个时刻的状态值(例如,一个设备在某个时刻的温度测量值,一旦记录下来,这个值本身就不会再变了)。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Redis提供了多种方案来保存和查询时间序列数据,包括基于Hash和Sorted Set的组合以及RedisTimeSeries模块。这些方案各有优劣,适用于不同的使用场景。基于Hash和Sorted Set的组合适合单个时间点和时间范围内的数据查询,具有稳定性和高性能的优势,但在聚合计算需求下可能影响性能。相比之下,RedisTimeSeries模块专门为时间序列数据访问设计,能够在Redis实例上直接进行聚合计算,减少数据传输对网络性能的影响。因此,对于不同的需求,读者可以根据网络带宽和内存资源等因素选择合适的方案。总的来说,本文详细介绍了Redis中保存和查询时间序列数据的多种方案,为读者提供了全面的技术指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(60)

  • 最新
  • 精选
  • Geek_1e8830
    老师,你好,问个问题,基于redis的单线程原理lua脚本到底可不可以保证原子性?

    作者回复: Redis会用单线程方式执行Lua脚本,保证脚本执行过程中不被其他命令打断,一般我们称之为以原子性的方式执行。但是有个地方要注意,如果脚本中用redis.call函数时出错了,会导致执行中断,此时,Lua脚本是不会回滚的。

    2021-01-31
    4
    28
  • Kaito
    使用Sorted Set保存时序数据,把时间戳作为score,把实际的数据作为member,有什么潜在的风险? 我目前能想到的风险是,如果对某一个对象的时序数据记录很频繁的话,那么这个key很容易变成一个bigkey,在key过期释放内存时可能引发阻塞风险。所以不能把这个对象的所有时序数据存储在一个key上,而是需要拆分存储,例如可以按天/周/月拆分(根据具体查询需求来定)。当然,拆分key的缺点是,在查询时,可能需要客户端查询多个key后再做聚合才能得到结果。 如果你是Redis的开发维护者,你会把聚合计算也设计为Sorted Set的内在功能吗? 不会。因为聚合计算是CPU密集型任务,Redis在处理请求时是单线程的,也就是它在做聚合计算时无法利用到多核CPU来提升计算速度,如果计算量太大,这也会导致Redis的响应延迟变长,影响Redis的性能。Redis的定位就是高性能的内存数据库,要求访问速度极快。所以对于时序数据的存储和聚合计算,我觉得更好的方式是交给时序数据库去做,时序数据库会针对这些存储和计算的场景做针对性优化。 另外,在使用MULTI和EXEC命令时,建议客户端使用pipeline,当使用pipeline时,客户端会把命令一次性批量发送给服务端,然后让服务端执行,这样可以减少客户端和服务端的来回网络IO次数,提升访问性能。
    2020-09-07
    42
    419
  • 阳明
    存在member重复的问题,会对member覆盖
    2020-09-07
    5
    76
  • pedro
    Hash 和 Sorted Set 的结合让我想到了 LRU 中的 HashMap 和 LinkedList 的结合,二者均取长处碰撞出了不一样的火花,看看毫不沾边的事物,往往具有相同的内涵。
    2020-09-07
    35
  • 注定非凡
    1,作者讲了什么? 根据时间序列数据的特点,选择合适的存储方案 2,作者是怎么把这事给讲明白的? 结合具体场景,探讨解决方案 1,介绍需求背景,用户行为,设备监控数据分析 2,介绍数据特点,时间线连续,没有逻辑关系,数据量大 3,介绍操作场景,插入多且快,常单点查询,分组统计聚合 3,作者为了把这事给讲清楚,讲了那些要点?有哪些亮点? 1,亮点1:先讲清楚需求背景,从实际问题出发,推演出存储时间序列数据适合使用sort set 和hash解决点查询和范围查询的需求 2,要点1:同时写入sort set和hash 两种数据类型的存储,需要使用原子操作,可以借助MULTI和 EXEC命令 3,要点2:大数据量的聚合统计,会非常消耗网络带宽,所以可以使用RedisTimeSeries模块处理 4,对于作者所讲,我有哪些发散性思考? 5,在未来的那些场景中,我能够使用它? 6,留言区的收获
    2020-10-14
    24
  • test
    redis的事务不是完整的事务,当有一个命令失败时还是会继续往下执行,这是个问题。时序数据还是交给时序数据库来保存比较专业
    2020-09-07
    4
    20
  • Mr.蜜
    Sorted Set还是基于Set集合的,所以如果member值相同,那么ZADD只会更新score,存在数据丢失的风险。我有个问题:既然每三分钟聚合一次计算,为何不直接按时间统计值呢?比方说hincrby,把指定一段时间的温度聚合在一起,可以用lua脚本,实现此类计算,这样既实现了原子性,又不会特别消耗内存,还能实现数据统计。
    2020-09-19
    14
  • dfuru
    hash和sorted set类型的key不能相同,文件是相同的。 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> ZADD dev:temp4 2020092201 26.8 QUEUED 127.0.0.1:6379> HSET dev:temp4 2020092201 26.8 QUEUED 127.0.0.1:6379> EXEC 1) (integer) 1 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> MULTI OK 127.0.0.1:6379> HSET dev:temp5 2020092201 26.8 QUEUED 127.0.0.1:6379> ZADD dev:temp6 2020092201 26.8 QUEUED 127.0.0.1:6379> EXEC 1) (integer) 1 2) (integer) 1
    2020-09-22
    6
    12
  • Eric.Lee
    有个问题:市面上有成熟的时间序列数据库如:influxdb、Prometheus等。这一讲,我理解是介绍了Redis支持通过加载模块的形式也能支持这种数据类型的存储。单从时间序列管理、功能方面上个人感觉不如专业数据库成熟?还是作者做过这些数据库的比较专门选用的Redis做数据存储?
    2020-10-27
    5
    10
  • 凯文小猪
    虽然有点泼冷水 但实际上点击流数据 通常是用kafka 作为日志来中转的。这里面涉及几个问题: 1。数据的维度并不总是固定的。比方说今天要聚合统计 明天可能要最值或基数统计。那这时候用redis存储显然不是第一选择。 2. 数据清洗问题。不是所有的数据都是我们期望的 但我们不能要求埋点方来做数据清洗 我们只能要求埋点方尽可能多的上报 才能保证数据是正确的 偏差值 最小。 3. 数据量存储问题。比方说亿级流量 每秒点击流是1W qps ,以一个上送数据1KB估算:那么一天数据量有1KB * 10000 * 3600 * 24 = 864GB 实际上无论是用切片 还是集群都存不下
    2021-05-26
    2
    9
收起评论
显示
设置
留言
60
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部