Redis 命令及数据类型 -- TimeSeries
摘要
- 本文介绍 Redis 扩展模块 – RedisTimeSeries 中 TimeSeries 数据类型
- 本文基于
redis-7.4.7,springboot-3.5.8 - 操作系统:
Amazon Linux 2023(内核 6.1) - Redis官网:https://redis.io/
- Redis 命令文档:https://redis.io/docs/latest/commands/
- RedisTimeSeries 的安装参见 Redis 扩展模块 -- RedisTimeSeries 的安装方法
TimeSeries 简介
-
TimeSeries 是 Redis 的一个扩展模块,用于处理时间序列数据,RedisTimeSeries | A NoSQL Time Series Database
-
核心设计与数据模型
一个 Redis 时间序列(Time Series) 是有序的一系列采样数据点:
| 组成部分 | 说明 |
|---|---|
| 时间戳(timestamp) | 毫秒级时间标签,可客户端指定或由服务器填充 |
| 值(value) | 64 位浮点数 |
| 元数据(labels) | 一组键值对,可用于过滤与聚合查询 |
| 保留策略(retention) | 数据生命周期控制,过期自动丢弃 |
-
主要功能与特性
| 特性 | 说明 |
|---|---|
| 高吞吐写入 | 支持每秒接收大量数据点,延迟极低 |
| 区间查询 | 可按时间范围检索数据,如 TS.RANGE / TS.MRANGE |
| 聚合查询 | 内建 min、max、avg、sum、count、first、last 等聚合功能 |
| 自动下采样 & 累积规则 | 通过 aggregation rules 自动生成更粗粒度指标 |
| 保留策略(Retention) | 设置最大保存时间或样本数量 |
| 标签索引(Labels) | 支持基于标签的跨序列查询 |
| 高效存储 | 使用压缩与内存结构优化空间成本 |
| 工具整合 | 支持 Grafana、Prometheus、Telegraf 等生态集成 |
-
应用场景
| 场景 | 描述 |
|---|---|
| 物联网(IoT)监控 | 温度、湿度、设备状态等 |
| 系统监控与指标收集 | CPU、内存、网络指标的实时存储与分析 |
| 业务指标分析 | 每日/每小时活跃用户数量、请求延迟等 |
| 金融时间序列 | 股票价格、交易量的快速写入和分析 |
| 实时告警 | 数据越界时触发告警逻辑 |
TimeSeries 命令说明
-
按“生命周期”视角的快速索引
| 阶段 | 对应命令 |
|---|---|
| 创建 | TS.CREATE |
| 修改结构 | TS.ALTER |
| 建立聚合 | TS.CREATERULE / TS.DELETERULE |
| 写入 | TS.ADD / TS.MADD / TS.INCRBY / TS.DECRBY |
| 查询单序列 | TS.GET / TS.RANGE / TS.REVRANGE |
| 查询多序列 | TS.MGET / TS.MRANGE / TS.MREVRANGE / TS.QUERYINDEX |
| 清理数据 | TS.DEL |
| 查看状态 | TS.INFO |
一、时间序列创建与结构管理类
| 命令 | 功能说明 | 典型使用场景 |
|---|---|---|
| TS.CREATE | 创建一个新的时间序列(可指定保留策略、标签、chunk 大小等) | 初始化指标,如创建 CPU、QPS、延迟等指标序列 |
| TS.ALTER | 修改已有时间序列的配置(retention、chunk size、duplicate policy、labels) | 动态调整数据保留周期、标签信息 |
| TS.CREATERULE | 创建压缩 / 聚合规则(从 source series 自动聚合到 dest series) | 原始数据 → 按分钟 / 小时聚合 |
| TS.DELETERULE | 删除已有的压缩 / 聚合规则 | 停止某条自动聚合规则 |
1️⃣ TS.CREATE : 创建时间序列
-
语法:
1 | TS.CREATE key |
-
参数说明:
| 参数 | 作用 | 可选值 / 约束 | 默认值 | 典型使用建议 |
|---|---|---|---|---|
| key | 时间序列的 Redis Key | 任意合法 Redis key | 无 | 建议包含业务语义,如 ts:cpu:node1 |
| RETENTION | 数据保留时长(毫秒),超过自动删除 | ≥ 0,0 表示永久保留 | 0 | 高频指标必须设置,避免内存无限增长 |
| ENCODING | 数据存储编码方式 | COMPRESSED: 内存占用低,CPU 有轻微开销UNCOMPRESSED:查询快,占用内存高 |
COMPRESSED |
绝大多数场景保持默认 |
| CHUNK_SIZE | 每个数据块的大小(字节),影响内存碎片与压缩效率 | ≥ 128 bytes(通常 1KB–64KB) | 4096 | 写入频繁时适当调大 |
| DUPLICATE_POLICY | 同一 timestamp 重复写入时的处理策略 | 见下表 | 全局配置 | 明确指定,避免默认行为变化 |
| IGNORE | 忽略与上一点差异过小的数据 | ignoreMaxTimediff: 最大允许时间差(毫秒)ignoreMaxValDiff: 最大允许的数值差 |
关闭 | 用于降噪和降采样 示例: IGNORE 1000 0.01: 1 秒内,变化小于 0.01 的数据将被忽略 |
| LABELS | 标签键值对,用于索引和过滤 | 任意字符串对LABELS key1 value1 key2 value2 ... |
无 | 强烈建议用于查询 |
-
DUPLICATE_POLICY(重复时间戳策略)
当同一个 timestamp 被多次写入时生效
| 策略 | 处理逻辑 |
|---|---|
| BLOCK | 默认,重复时间戳直接失败 |
| FIRST | 保留已有值,忽略新值 |
| LAST | 覆盖已有值,用新值替代 |
| MIN | 仅当新值更小才覆盖 |
| MAX | 仅当新值更大才覆盖 |
| SUM | 累加值(已有值 + 新值) |
-
示例: 创建一个 CPU 指标时间序列,自动过期 1 小时之前的数据
1 | TS.CREATE ts:cpu:server1 |
2️⃣ TS.ALTER : 修改时间序列配置
-
语法:
1 | TS.ALTER key |
-
示例:修改保留周期和标签
1 | TS.ALTER ts:cpu:server1 |
3️⃣ TS.CREATERULE : 创建自动聚合规则
-
场景说明
- 原始序列:ts:cpu:server1(秒级数据)
- 聚合目标:ts:cpu:server1:avg1m(按 1 分钟平均值聚合)
-
语法:
1 | TS.CREATERULE sourceKey destKey |
-
参数说明
| 参数 | 作用 | 可选值 / 约束 | 是否必填 | 行为说明 | 使用注意事项 |
|---|---|---|---|---|---|
| sourceKey | 源时间序列 Key | 必须是已存在的 TS key | 是 | 新写入数据从该序列触发聚合 | 必须先创建 |
| destKey | 目标聚合时间序列 Key | 必须是已存在的 TS key | 是 | 聚合结果写入该序列 | 通常 retention 更长 |
| aggregator | 聚合函数 | 见下表 | 是 | 定义每个 bucket 内如何计算 | 不同函数计算成本不同 |
| bucketDuration | 聚合时间桶宽度(毫秒) | > 0 | 是 | 控制聚合粒度 | 决定数据降采样程度 |
| alignTimestamp | 对齐时间戳基准 | 毫秒时间戳 | 否 | 控制 bucket 起始对齐方式 | 跨系统对齐时非常重要 |
-
aggregator(聚合函数)
| 聚合器 | 说明 |
|---|---|
| AVG | 平均值 |
| SUM | 求和 |
| MIN | 最小值 |
| MAX | 最大值 |
| COUNT | 样本数量 |
| FIRST | 第一个样本 |
| LAST | 最后一个样本 |
| RANGE | MAX - MIN |
| STD.P | 总体标准差 |
| STD.S | 样本标准差 |
| VAR.P | 总体方差 |
| VAR.S | 样本方差 |
-
alignTimestamp(对齐时间戳基准)
| 类型 | 示例值 | 含义 |
|---|---|---|
| 0(Unix Epoch)(推荐做法) | 0 |
从 1970-01-01 00:00:00 UTC 对齐 |
| 任意固定时间戳 | 1700000000000 |
从指定时间点对齐 |
| 当前时间戳 | $(date +%s%3N) |
从创建规则时刻对齐 |
| 业务时间边界 | 某天 00:00 的毫秒值 | 对齐到业务周期 |
| 不指定 | (参数省略) | 自动使用首条写入时间 |
-
示例: 每 60,000ms(1分钟)做一次平均聚合
1 | # 1.创建目标聚合序列 |
4️⃣ TS.DELETERULE : 删除自动聚合规则
-
语法:
1 | TS.DELETERULE sourceKey destKey |
-
示例:删除自动聚合规则
1 | TS.DELETERULE ts:cpu:server1 ts:cpu:server1:avg1m |
二、数据写入与更新类
| 命令 | 功能说明 | 典型使用场景 |
|---|---|---|
| TS.ADD | 向时间序列追加一个样本点(timestamp, value) | 实时写入监控数据 |
| TS.MADD | 批量向多个时间序列追加样本 | 高吞吐场景,减少网络 RTT |
| TS.INCRBY | 对最新时间戳的值做自增(不存在则创建新样本) | 计数器、累计指标 |
| TS.DECRBY | 对最新时间戳的值做自减(不存在则创建新样本) | 库存、余额类递减指标 |
1️⃣ TS.ADD : 向时间序列追加一个样本点
-
语法:
1 | TS.ADD key timestamp value |
-
如果 key 不存在,TS.ADD 会 隐式创建时间序列(类似 TS.CREATE)。
-
参数说明
| 参数 | 作用 | 可选值 / 约束 | 是否覆盖已有配置 | 生效范围 | 使用注意事项 |
|---|---|---|---|---|---|
| key | 时间序列 Key | 合法 Redis key | — | — | 不存在时自动创建 |
| timestamp | 样本时间戳 | 毫秒整数 / * |
— | 当前写入 | * 表示服务器当前时间 |
| value | 样本值 | 浮点数 | — | 当前写入 | NaN / Inf 不允许 |
| RETENTION | 设置保留周期 | ≥ 0(毫秒) | 仅首次创建生效 | 序列级 | 已存在 key 不会被修改 |
| ENCODING | 存储编码 | COMPRESSED / UNCOMPRESSED | 仅首次创建生效 | 序列级 | 生产推荐 COMPRESSED |
| CHUNK_SIZE | 数据块大小 | ≥ 128 bytes | 仅首次创建生效 | 序列级 | 不影响已有 chunk |
| DUPLICATE_POLICY | 设置默认重复策略 | BLOCK / FIRST / LAST / MIN / MAX / SUM | 仅首次创建生效 | 序列级 | 与 ON_DUPLICATE 有优先级关系 |
| ON_DUPLICATE | 本次写入的重复策略 | 同上 | 覆盖序列级策略 | 当前写入 | 推荐用于临时覆盖 |
| IGNORE | 忽略微小变化写入 | 两个阈值 | 仅首次创建生效 | 序列级 | 用于降噪 |
| LABELS | 设置标签 | 键值对 | 仅首次创建生效 | 序列级 | 已存在 key 不会修改 |
-
示例:写入一个时间序列
1 | TS.ADD ts:cpu:server1 * 80.5 |
2️⃣ TS.MADD : 批量向多个时间序列追加样本
-
语法
1 | TS.MADD key timestamp value [key timestamp value ...] |
-
示例:批量写入多个时间序列
1 | # 批量写入三个时间序列,时间序列必须存在 |
3️⃣ TS.INCRBY : 对最新时间戳的值做自增(不存在则创建新样本)
-
语法:
1 | TS.INCRBY key addend |
-
参数说明
| 参数 | 作用 | 可选值 / 约束 | 是否覆盖已有配置 | 生效范围 | 使用注意事项 |
|---|---|---|---|---|---|
| key | 时间序列 Key | 合法 Redis key | — | — | 不存在会自动创建 |
| addend | 增量值 | 浮点数 | — | 当前写入 | 支持负数(等价 DECR) |
| TIMESTAMP | 指定写入时间戳 | 毫秒整数 | — | 当前写入 | 默认使用服务器时间 |
| RETENTION | 设置保留周期 | ≥ 0(毫秒) | 仅首次创建生效 | 序列级 | 已存在 key 不生效 |
| ENCODING | 存储编码 | COMPRESSED / UNCOMPRESSED | 仅首次创建生效 | 序列级 | 推荐 COMPRESSED |
| CHUNK_SIZE | 数据块大小 | ≥ 128 bytes | 仅首次创建生效 | 序列级 | 高频写入可调大 |
| DUPLICATE_POLICY | 默认重复时间戳策略 | BLOCK / FIRST / LAST / MIN / MAX / SUM | 仅首次创建生效 | 序列级 | 对计数器通常设 SUM |
| IGNORE | 忽略微小变化 | 两个阈值 | 仅首次创建生效 | 序列级 | 计数器一般不使用 |
| LABELS | 标签 | 键值对 | 仅首次创建生效 | 序列级 | 用于 MGET / MRANGE |
-
如果 key 不存在,TS.INCRBY 会 隐式创建时间序列。
-
如果没有指定 TIMESTAMP,则自动使用服务器当前时间。
-
写入逻辑等价于:读取最新值 + addend → 写回一个新样本。
-
示例
1 | # 对最新时间戳的值做自增 |
4️⃣ TS.DECRBY : 对最新时间戳的值做自减(不存在则创建新样本)
-
与
TS.INCRBY相似,不再赘述。 -
实际上
TS.INCRBY中设置addend为负数 就是TS.DECR
三、数据查询(单序列)类
| 命令 | 功能说明 | 典型使用场景 |
|---|---|---|
| TS.GET | 获取某个时间序列最新(最大 timestamp)的样本 | 获取当前最新指标值 |
| TS.RANGE | 按时间正序查询一个时间序列的区间数据 | 绘图、趋势分析 |
| TS.REVRANGE | 按时间逆序查询一个时间序列的区间数据 | 获取最近 N 条数据 |
1️⃣ TS.GET : 获取某个时间序列最新(最大 timestamp)的样本
-
语法:
1 | TS.GET key [LATEST] |
-
参数说明:
| 参数 | 作用 |
|---|---|
| key | 时间序列 Key |
| LATEST | 获取最新样本 |
-
LATEST 说明
- 当一个时间序列是经过聚合(compaction)处理的时,LATEST 参数会生效。使用 LATEST 时,TS.GET 会返回最新(可能是部分的)桶的聚合值。不使用 LATEST 时,TS.GET 不会返回最新(可能是部分的)桶的值。当时间序列不是聚合的时,LATEST 会被忽略。
- 最新桶中的数据可能是不完整的。只有当有新的样本到来并开启一个新的最新桶时,原桶才会被关闭并进行聚合。然而,在某些情况下,也需要获取最新(可能是部分的)桶的聚合值,此时就可以使用 LATEST。
-
示例:
1 | TS.GET ts:cpu:server1 LATEST |
2️⃣ TS.RANGE : 按时间正序查询一个时间序列的区间数据
-
语法:
1 | TS.RANGE key fromTimestamp toTimestamp |
-
参数说明:
| 参数 | 类型 | 说明 | 可选值 / 说明 |
|---|---|---|---|
key |
string | 时间序列的键名 | 必选 |
fromTimestamp |
integer | 查询起始时间戳,-: 最小值 |
必选 |
toTimestamp |
integer | 查询结束时间戳 ,+: 最大值 |
必选 |
LATEST |
flag | 当时间序列是 compaction 时,返回最新(可能部分)的桶的聚合值 | 可选 |
FILTER_BY_TS ts... |
list of integers | 只返回指定时间戳的样本 | 可选 |
FILTER_BY_VALUE min max |
range | 只返回值在 [min, max] 区间的样本 |
可选 |
COUNT count |
integer | 限制返回的样本数量(最多 count 个) |
可选 |
ALIGN align |
string | 对齐聚合桶的时间戳(如 start、end、自定义时间戳) |
可选,需与 AGGREGATION 一起使用 |
AGGREGATION aggregator bucketDuration |
aggregation | 对数据进行聚合计算,aggregator 为聚合函数(如 avg, sum, min, max 等),bucketDuration 为桶的时长 |
可选 |
BUCKETTIMESTAMP bt |
string | 聚合桶时间戳选择,bt 可为 start 或 end |
可选 |
EMPTY |
flag | 即使桶为空也返回结果 | 可选 |
-
示例:
1 | # 查询时间序列 ts:cpu:server1 的区间数据 |
3️⃣ TS.REVRANGE : 按时间逆序查询一个时间序列的区间数据
-
与 TS.RANGE 类似,只是返回结果是倒序的
-
示例
1 | TS.REVRANGE ts:cpu:server1 0 1767778308126 |
四、数据查询(多序列 / 聚合)类
| 命令 | 功能说明 | 典型使用场景 |
|---|---|---|
| TS.MGET | 根据标签过滤,获取多个时间序列的最新值 | 批量获取多个实例的当前指标 |
| TS.MRANGE | 按标签过滤,正序查询多个时间序列的区间数据 | 多维指标分析、聚合 |
| TS.MREVRANGE | 按标签过滤,逆序查询多个时间序列的区间数据 | 最近数据聚合分析 |
| TS.QUERYINDEX | 根据标签过滤,返回匹配的时间序列 key 列表 | 发现有哪些指标符合条件 |
1️⃣ TS.MGET : 根据标签过滤,获取多个时间序列的最新值
-
语法:
1 | TS.MGET [LATEST] [WITHLABELS | <SELECTED_LABELS label...>] FILTER filterExpr... |
-
参数说明:
| 参数 | 类型 | 说明 | 可选值 / 说明 |
|---|---|---|---|
LATEST |
flag | 对 compaction 类型的时间序列,返回最新(可能部分)的样本值 | 可选 |
WITHLABELS |
flag | 返回样本的同时附带时间序列的所有标签 | 可选 |
<SELECTED_LABELS label...> |
list | 返回样本时只附带指定标签 | 可选,不能与 WITHLABELS 一起使用 |
FILTER filterExpr... |
list of expressions | 过滤时间序列,根据标签匹配规则筛选出符合条件的序列 | 必选,支持标签匹配表达式,如 sensor=temperature 或 region=* |
-
示例:
1 | # 获取所有时间序列的最新值,根据标签过滤 |
2️⃣ TS.MRANGE : 按标签过滤,正序查询多个时间序列的区间数据
-
语法:
1 | TS.MRANGE fromTimestamp toTimestamp |
-
参数说明:
| 参数 | 类型 | 说明 | 可选值 / 说明 |
|---|---|---|---|
fromTimestamp |
integer | 查询起始时间戳,-: 最小值 |
必选 |
toTimestamp |
integer | 查询结束时间戳,+: 最大值 |
必选 |
LATEST |
flag | 对 compaction 类型的时间序列,返回最新(可能部分)的桶的聚合值 | 可选 |
FILTER_BY_TS ts... |
list of integers | 只返回指定时间戳的样本 | 可选 |
FILTER_BY_VALUE min max |
range | 只返回值在 [min, max] 区间的样本 |
可选 |
WITHLABELS |
flag | 返回样本的同时附带时间序列的所有标签 | 可选 |
<SELECTED_LABELS label...> |
list | 返回样本时只附带指定标签 | 可选,不能与 WITHLABELS 一起使用 |
COUNT count |
integer | 限制返回的样本数量(最多 count 个) |
可选 |
ALIGN align |
string | 对齐聚合桶的时间戳(如 start、end 或自定义时间戳) |
可选,需与 AGGREGATION 一起使用 |
AGGREGATION aggregator bucketDuration |
aggregation | 对数据进行聚合计算,aggregator 为聚合函数(如 avg, sum, min, max 等),bucketDuration 为桶的时长 |
可选 |
BUCKETTIMESTAMP bt |
string | 聚合桶时间戳选择,bt 可为 start 或 end |
可选 |
EMPTY |
flag | 即使桶为空也返回结果 | 可选 |
FILTER filterExpr... |
list of expressions | 过滤时间序列,根据标签匹配规则筛选出符合条件的序列 | 必选 |
GROUPBY label REDUCE reducer |
aggregation | 对返回结果按指定标签分组并应用 reducer 聚合函数(如 SUM, MIN, MAX 等) |
可选 |
-
示例:
1 | TS.MRANGE - + FILTER metric=cpu |
3️⃣ TS.MREVRANGE : 按标签过滤,逆序查询多个时间序列的区间数据
-
与 TS.MRANGE 类似,只是查询结果是逆序的
4️⃣ TS.QUERYINDEX : 根据标签过滤,返回匹配的时间序列 key 列表
-
语法:
1 | S.QUERYINDEX filterExpr... |
-
示例:
1 | TS.QUERYINDEX metric=cpu host=server1 |
五、数据删除与维护类
| 命令 | 功能说明 | 典型使用场景 |
|---|---|---|
| TS.DEL | 删除某个时间序列在指定时间范围内的样本 | 清理异常数据、历史数据修正 |
-
语法
1 | TS.DEL key fromTimestamp toTimestamp |
-
示例:
1 | TS.DEL ts:cpu:server1 0 1767777965870 |
六、元数据与状态查询类
| 命令 | 功能说明 | 典型使用场景 |
|---|---|---|
| TS.INFO | 返回时间序列的元信息与统计信息 | 排查问题、容量评估、监控状态 |
-
语法
1 | TS.INFO key [DEBUG] |
-
示例:
1 | TS.INFO ts:cpu:server1 |
真实案例
场景说明
-
假设我们有一个 IoT 设备监控系统,每台设备每分钟会上报一次温度和湿度数据。我们希望:
- 存储每台设备的时间序列数据。
- 查询最近一小时的数据。
- 统计每 5 分钟的平均温度和湿度。
- 获取最新的温度值。
步骤
-
- 创建时间序列
1 | # 创建设备 device:1001 的温度时间序列 |
-
- 插入数据
1 | # 假设时间戳为当前毫秒 |
-
- 查询时间范围数据
1 | # 获取 过去一小时的温度数据: |
-
- 聚合查询(Downsampling)
1 | # 统计 每 5 分钟平均温度: |
-
- 获取最新值
1 | # 获取最新的温度值: |
-
- 按标签查询
1 | # 如果我们想获取 所有设备的温度平均值(假设有很多设备): |