使用zrange按周期查询Redis时间序列

时间:2017-07-28 16:04:46

标签: caching redis

我搜索并做了一些阅读,但无法找到答案。我相信我可能错误地想到了缓存实现。

我有一套历史和当前的金融股票数据,我希望将其缓存以便快速访问API,这些数据遵循以下格式:

id: uuid
timestamp: unix_timestamp
data: {...}

目的是允许由缓存提供服务的用户请求数据,但我希望用户能够提供时间范围,例如1483142400 - 1493510400以及表单中的句点秒(例如300,900,1800,3600,86400)。

我现在处于如何解决这个问题的困境,我最初的想法是使用zadd将所有时间戳存储在每个库存的单个有序集中,然后使用zrange进行查询。然而,这将是昂贵的,因为我要查询太多不必要的数据,除非Redis能够在一段时间内“逐步”通过(如果我可以提供所有密钥,因为它们遵循非随机的一致格式)。

我的第二个想法是改为使用单独的密钥,因为我的财务数据是针对股票XYZ:

ZADD XYZ_300 1501200300 'data' 1501200600 'data'
ZADD XYZ_900 1501200900 'data' 1501201800 'data'
ZADD XYZ_1800 1501201800 'data' 1501203600 'data'
ZADD XYZ_3600 1501203600 'data' 1501207200 'data'

这意味着我有一些冗余数据正在进行,因为所有集合都有300秒表中也可用的数据。

此外,我可能会有一些股票,例如XYZABCDEF。我希望能够查询3天前至2天前所有上述股票的小时数据,我不确定我是否应该使用ZUNIONSTORE或某种类型的管道,可以有效地一次性查询多个范围。

现在唯一的保证是我确切知道我的密钥是什么,因为它们总是四舍五入到最接近的00:00,05:00,15:00和30:00分钟的unix时间戳。缓存本身是从运行Django的Python(存储json)中设置/查询的。可能我最好将其存储在文件而不是缓存中(因为我正在使用AWS,我可以利用新的EFS存储系统为多个服务器共享相同的底层'硬盘/卷')

2 个答案:

答案 0 :(得分:3)

据我了解,您有两个基本要求:  1.能够查询任何随机时间范围  2.按时间跨度查询结果聚合

ZRANGE基本上是一个排序集,具有(非常)高效的查询运行时。 来自Redis manual

  

O(log(N)+ M),其中N是有序集合中元素的数量,M是返回的元素数量。

许多人的常见用例是将时间序列数据保存在有序集合中:

  • 每个时间戳添加一个数据键(哈希类型),其中包含值及其标识(例如,库存)。
  • 每个ZSET项目数据必须是唯一的,因此您必须将数据保存在单独的哈希键中
  • 通过密钥查询特定库存并获得具有相当好性能的ZRANGE的特定时间。 关于这项技术的好文章可以在这里找到:https://www.infoq.com/articles/redis-time-series

关于性能,我们需要查看插入和读取:

  1. 写性能:ZADD是O(log(N))+哈希写入性能O(N),其中N是数据键的数量(例如股票)。
  2. 读取性能:ZRANGE O(log(N)+ M)+ HGET表示特定键O(1) 如果您有大量样本(M),您的阅读性能将会降低。
  3. 关于要求#2: 没有简单的方法可以在redis中进行聚合。

    总而言之,时间序列没有最优的数据结构,你可以使用ZSET(很多人都这样做)它会起作用但是不是非常优化而且也不是空间效率。

    您可以通过以下方式改进:

    • 使用LUA代码查询原始排序集,并在不将大量数据移动到客户端的情况下做一些魔术。
    • 使用新的modules API编写您自己的数据结构。

    或者您可以尝试使用我编写和维护的模块:https://github.com/danni-m/redis-timeseries。 功能是:

    • 时间序列的高效数据存储(目前每个样本为16个字节,我正在进行大猩猩压缩,这会降低空间)
    • 按时间段汇总的查询(要求#1)
    • 使用不同聚合方法(最大值,最小值,平均值,总和值)进行自动压缩/下采样(一对多)
    • 用于添加和查询时间序列的非常简单的命令。

答案 1 :(得分:0)

您需要拥有table_name,data,timestamp_in_unix

添加

zadd table_name data timestamp_in_unix

检索所有值

zrangebyscore table_name -inf +inf 

在特定范围内检索

zrangebyscore table_name from_unix_timestamp to_unix_timestamp

我希望这会有所帮助。如果你遇到任何问题,请告诉我。