caching - 使用 zrange 按时间段查询 Redis 时间序列

标签 caching redis

我进行了搜索并进行了大量阅读,但找不到答案。我相信我可能对这里的缓存实现有错误的想法。

我有一组历史和当前的金融股票数据,我想将它们缓存起来以供快速 API 访问,这些数据遵循以下格式:

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

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

我现在陷入了如何处理这个问题的两难境地,我最初的想法是使用 zadd 将所有时间戳存储在每个股票的单个排序集中,然后使用 查询它>z范围。然而,这将是昂贵的,因为我会查询太多不必要的数据,除非 Redis 能够在一段时间内“单步执行”(如果我可以提供所有键,因为它们遵循非随机的一致格式)。

我的第二个想法是使用单独的 key ,因为我的财务数据是针对股票 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 或某种管道可以有效地一次性查询多个范围。

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

最佳答案

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

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

O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.

很多人的一个常见用例是将时间序列数据保存在一个排序集中:

  • 为每个时间戳添加一个数据键(哈希类型),其中包含值及其标识(例如股票)。
  • 每个 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),您的读取性能将会降低。

关于要求 #2: 在 Redis 中没有简单的聚合方法。

总而言之,时间序列没有最佳的数据结构,您可以使用 ZSET(很多人都这样做),它可以工作,但不是很理想,而且空间效率不高。

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

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

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

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

关于caching - 使用 zrange 按时间段查询 Redis 时间序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45377935/

相关文章:

c# - 无法使用 ASP.NET session 状态提供程序连接到 Redis 服务器

redis - 通过 Sentinel 连接到 Redis 集群

php - Socket.io、PHP、Node 和 Redis 聊天室

.net - EntLib 缓存应用程序 block 的替代方案?

caching - 服务器正在提供旧版本的静态文件,但经过修剪或填充以匹配新版本的长度

python - 在 docker 构建中使用 pip 缓存目录

python - django redis 与 django 显示 ulimit 错误

node.js - 分布式 worker 的架构

caching - Webpack:重新捆绑后 Object(...) 不是函数

php - Apache、mod_cache 和 Cookies