redis操作时序类DataFrame

1. DataFrame写入到redis

  我们在处理大数据量时,经常使用pandas操作数据,绝大部分数据格式为DataFrame,如何将其写入到redis?

"""
dataframe_handled 格式如下:
name      report_time    energy_cost    part_num
mach1      2021-01-01	     125.8		     0
mach2      2021-01-01	     225.2		     1
mach3      2021-01-01	     182.6		     2
mach4      2021-01-01	     99.25		     3
"""

prefixs = "local_a"

dataframe_handled.apply(
	lambda x: pipeline.hset(f"{prefix}:part{x['part_num']}:{x['name']}",
	key=x["report_time"],
	value=x["energy_cost"]), axis=1
)
pipeline.execute()

2. 什么是时序类数据

  时序类数据,就是时间序列数据,即一串按时间维度索引的数据,简单讲就是这类数据描述了某个被测量的主体在一个时间范围内的每个时间点上的测量值,主要包括三个重要部分:主体、时间点、测量值。通过这类时序数据,找出样本内时间序列的统计特性和发展规律性,构建时间序列模型,进行样本外预测

3. 时序类数据的特点

  1. 数据模式:时序数据随时间增长,相同维度重复取值,指标平滑变化(某设备上传的温度值在某时间段内的规律变化);
  2. 写入:持续高并发写入,无更新操作(时序数据库面对的往往是百万甚至千万数量级终端设备的实时数据写入);
  3. 查询:按不同维度对指标进行统计分析,且存在明显的冷热数据,一般只会频繁查询近期数据。

4. 时序类数据如何存储

1. 使用 hash 存储
  hash类型的优点就是可以实现对某个单键的快速查询。
  使用 hash 存储时序类数据时,可以将该时刻的字符串(“2021-01-07 00:00:00”)、或时间戳、或该时刻的数字格式(“2020010700”)作为 filed,将该时刻的上报值作为 value 进行存储。
  hash 这种存储格式,只适合对存储的数据进行全量运算,不适合对存储数据进行再分段的操作。

127.0.0.1:6379> hmset temp "2021-01-07 00:00:00" 23.5 "2021-01-07 00:05:00" 25.1 "2021-01-07 00:10:00" 23.6
OK
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> hgetall temp
1) "2021-01-07 00:00:00"
2) "23.5"
3) "2021-01-07 00:05:00"
4) "25.1"
5) "2021-01-07 00:10:00"
6) "23.6"

2. 使用 sorted set 存储
  sorted set 内部实现用的是一种叫做 “跳跃列表” 的数据结构。sorted set 和 set 相比,增加了一个权重参数score,使得集合中的元素能够按score进行有序排列,支持对数据进行范围查询(zrangebyscore),业务上能迅速从上千万行数据中筛选出某个时间段内的数据。

  使用有序集合存储时序类数据时,我们可以将时间戳作为 score,该时间戳上报的值作为 member,这样存储数据时默认按照 score 时间戳进行有序排列,业务上就很方便地查询某段时间内的上报值。

  注意:score必须为数字类型,不能再存储时间字符串,比如 “2021-01-07 00:00:00” ,redis 储存时会直接报错,但是我们可以将之转换为时间戳,或 “20210107000000”,“20210107000500” 这种纯数字的类型。

127.0.0.1:6379> zadd temp "2021-01-07 00:00:00" 23.5 "2021-01-07 01:00:00" 24.7
(error) ERR value is not a valid float
127.0.0.1:6379> zadd temp 2021010700 23.7 2021010701 24.7 2021010702 22.9 2021010703 25.1
(integer) 2
127.0.0.1:6379> zrangebyscore temp 2020010700 2021010800
1) "23.7"
2) "24.7"
3) "22.9"
4) "25.1"
127.0.0.1:6379> zrangebyscore temp 2020010700 2021010800 withscores
1) "23.7"
2) "2021010700"
3) "24.7"
4) "2021010701"
5) "22.9"
6) "2021010702"
7) "25.1"
8) "2021010703"

5. keys *

  keys * 命令,返回所有键的集合,它会返回一个安全迭代器,来遍历整个键空间。在遍历的同时,筛选出那些匹配我们pattern以及非过期的键,然后返回给客户端。由于其遍历的时间复杂度是和字典的大小成正比的,这样就会导致一个问题,当键非常多的时候,这个键空间字典可能会非常大,我们一口气使用 keys * 把字典从上到下遍历一遍,会消耗非常多的时间。由于redis是单进程单线程的应用,执行 keys * 会长时间阻塞redis进程,造成redis服务对外不可用状态,所以很多公司都会禁止 keys * 命令。

  那如果换上其他范围比较小的 pattern 去替换之前的 * ,不就可以避免一次性去遍历全部的键空间了吗?并非如此,由于在遍历每一个key的时候,都会判断当前key是否与传入的pattern所匹配,所以并不是像我们想象的那样,只遍历我们传入的pattern的键空间,而是需要遍历完成的键空间集合,在遍历的同时筛选出符合条件的key值。其实遍历的初始范围条件并没有缩小,时间复杂度仍然是O(n),n为键空间字典的大小。

  在生产环境上,如果redis中数据量特别大时,keys * 会消耗非常多的时间,阻塞redis进程,造成redis服务对外不可用状态,会引起redis数据库雪崩,从而发生重启,造成生产事故,所以, 生 产 环 境 上 杜 绝 使 用 k e y s ∗ \color{red}{生产环境上杜绝使用keys *} 使keys

解决方案
  1. 使用 scan 获取数据
  2. 使用集合或有序集合,将分类的数据放入集合里,再遍历该集合,取每个类别对应的数据。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值