14 | 如何在Redis中保存时间序列数据?
蒋德钧
该思维导图由 AI 生成,仅供参考
你好,我是蒋德钧。
我们现在做互联网产品的时候,都有这么一个需求:记录用户在网站或者 App 上的点击行为数据,来分析用户行为。这里的数据一般包括用户 ID、行为类型(例如浏览、登录、下单等)、行为发生的时间戳:
我之前做过的一个物联网项目的数据存取需求,和这个很相似。我们需要周期性地统计近万台设备的实时状态,包括设备 ID、压力、温度、湿度,以及对应的时间戳:
这些与发生时间相关的一组数据,就是时间序列数据。这些数据的特点是没有严格的关系模型,记录的信息可以表示成键和值的关系(例如,一个设备 ID 对应一条记录),所以,并不需要专门用关系型数据库(例如 MySQL)来保存。而 Redis 的键值数据模型,正好可以满足这里的数据存取需求。Redis 基于自身数据结构以及扩展模块,提供了两种解决方案。
这节课,我就以物联网场景中统计设备状态指标值为例,和你聊聊不同解决方案的做法和优缺点。
俗话说,“知己知彼,百战百胜”,我们就先从时间序列数据的读写特点开始,看看到底应该采用什么样的数据类型来保存吧。
时间序列数据的读写特点
在实际应用中,时间序列数据通常是持续高并发写入的,例如,需要连续记录数万个设备的实时状态值。同时,时间序列数据的写入主要就是插入新数据,而不是更新一个已存在的数据,也就是说,一个时间序列数据被记录后通常就不会变了,因为它就代表了一个设备在某个时刻的状态值(例如,一个设备在某个时刻的温度测量值,一旦记录下来,这个值本身就不会再变了)。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
Redis提供了多种方案来保存和查询时间序列数据,包括基于Hash和Sorted Set的组合以及RedisTimeSeries模块。这些方案各有优劣,适用于不同的使用场景。基于Hash和Sorted Set的组合适合单个时间点和时间范围内的数据查询,具有稳定性和高性能的优势,但在聚合计算需求下可能影响性能。相比之下,RedisTimeSeries模块专门为时间序列数据访问设计,能够在Redis实例上直接进行聚合计算,减少数据传输对网络性能的影响。因此,对于不同的需求,读者可以根据网络带宽和内存资源等因素选择合适的方案。总的来说,本文详细介绍了Redis中保存和查询时间序列数据的多种方案,为读者提供了全面的技术指导。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》,新⼈⾸单¥68
《Redis 核心技术与实战》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(60)
- 最新
- 精选
- Geek_1e8830老师,你好,问个问题,基于redis的单线程原理lua脚本到底可不可以保证原子性?
作者回复: Redis会用单线程方式执行Lua脚本,保证脚本执行过程中不被其他命令打断,一般我们称之为以原子性的方式执行。但是有个地方要注意,如果脚本中用redis.call函数时出错了,会导致执行中断,此时,Lua脚本是不会回滚的。
2021-01-31428 - 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-0742419
- 阳明存在member重复的问题,会对member覆盖2020-09-07576
- pedroHash 和 Sorted Set 的结合让我想到了 LRU 中的 HashMap 和 LinkedList 的结合,二者均取长处碰撞出了不一样的火花,看看毫不沾边的事物,往往具有相同的内涵。2020-09-0735
- 注定非凡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-1424
- testredis的事务不是完整的事务,当有一个命令失败时还是会继续往下执行,这是个问题。时序数据还是交给时序数据库来保存比较专业2020-09-07420
- Mr.蜜Sorted Set还是基于Set集合的,所以如果member值相同,那么ZADD只会更新score,存在数据丢失的风险。我有个问题:既然每三分钟聚合一次计算,为何不直接按时间统计值呢?比方说hincrby,把指定一段时间的温度聚合在一起,可以用lua脚本,实现此类计算,这样既实现了原子性,又不会特别消耗内存,还能实现数据统计。2020-09-1914
- dfuruhash和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) 12020-09-22612
- Eric.Lee有个问题:市面上有成熟的时间序列数据库如:influxdb、Prometheus等。这一讲,我理解是介绍了Redis支持通过加载模块的形式也能支持这种数据类型的存储。单从时间序列管理、功能方面上个人感觉不如专业数据库成熟?还是作者做过这些数据库的比较专门选用的Redis做数据存储?2020-10-27510
- 凯文小猪虽然有点泼冷水 但实际上点击流数据 通常是用kafka 作为日志来中转的。这里面涉及几个问题: 1。数据的维度并不总是固定的。比方说今天要聚合统计 明天可能要最值或基数统计。那这时候用redis存储显然不是第一选择。 2. 数据清洗问题。不是所有的数据都是我们期望的 但我们不能要求埋点方来做数据清洗 我们只能要求埋点方尽可能多的上报 才能保证数据是正确的 偏差值 最小。 3. 数据量存储问题。比方说亿级流量 每秒点击流是1W qps ,以一个上送数据1KB估算:那么一天数据量有1KB * 10000 * 3600 * 24 = 864GB 实际上无论是用切片 还是集群都存不下2021-05-2629
收起评论