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

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

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

时间序列数据的读写特点

在实际应用中,时间序列数据通常是持续高并发写入的,例如,需要连续记录数万个设备的实时状态值。同时,时间序列数据的写入主要就是插入新数据,而不是更新一个已存在的数据,也就是说,一个时间序列数据被记录后通常就不会变了,因为它就代表了一个设备在某个时刻的状态值(例如,一个设备在某个时刻的温度测量值,一旦记录下来,这个值本身就不会再变了)。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(59)

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

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

    4
    25
  • 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次数,提升访问性能。
    41
    411
  • 阳明
    存在member重复的问题,会对member覆盖
    5
    75
  • pedro
    Hash 和 Sorted Set 的结合让我想到了 LRU 中的 HashMap 和 LinkedList 的结合,二者均取长处碰撞出了不一样的火花,看看毫不沾边的事物,往往具有相同的内涵。
    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,留言区的收获
    24
  • test
    redis的事务不是完整的事务,当有一个命令失败时还是会继续往下执行,这是个问题。时序数据还是交给时序数据库来保存比较专业
    4
    20
  • Mr.蜜
    Sorted Set还是基于Set集合的,所以如果member值相同,那么ZADD只会更新score,存在数据丢失的风险。我有个问题:既然每三分钟聚合一次计算,为何不直接按时间统计值呢?比方说hincrby,把指定一段时间的温度聚合在一起,可以用lua脚本,实现此类计算,这样既实现了原子性,又不会特别消耗内存,还能实现数据统计。
    13
  • 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
    6
    12
  • Eric.Lee
    有个问题:市面上有成熟的时间序列数据库如:influxdb、Prometheus等。这一讲,我理解是介绍了Redis支持通过加载模块的形式也能支持这种数据类型的存储。单从时间序列管理、功能方面上个人感觉不如专业数据库成熟?还是作者做过这些数据库的比较专门选用的Redis做数据存储?
    4
    10
  • 凯文小猪
    虽然有点泼冷水 但实际上点击流数据 通常是用kafka 作为日志来中转的。这里面涉及几个问题: 1。数据的维度并不总是固定的。比方说今天要聚合统计 明天可能要最值或基数统计。那这时候用redis存储显然不是第一选择。 2. 数据清洗问题。不是所有的数据都是我们期望的 但我们不能要求埋点方来做数据清洗 我们只能要求埋点方尽可能多的上报 才能保证数据是正确的 偏差值 最小。 3. 数据量存储问题。比方说亿级流量 每秒点击流是1W qps ,以一个上送数据1KB估算:那么一天数据量有1KB * 10000 * 3600 * 24 = 864GB 实际上无论是用切片 还是集群都存不下
    2
    9
收起评论
显示
设置
留言
59
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部