RedisTimeSeries TS.ADD 的 ON_DUPLICATE LAST 和 SUM 有什么区别
我第一次遇到这个问题,是在补采一段 RedisTimeSeries 数据时发现某个时间点的数值突然翻倍。写入请求本身没有报错,时间戳也没有变化,真正改变结果的是重试请求里带了 ON_DUPLICATE SUM。如果这类重试代表“同一条采样再次送达”,应该覆盖旧值;如果每次上报代表一笔需要累计的增量,才应该相加。
官方地址:https://redis.io/docs/latest/commands/ts.add/
一句话判断:ON_DUPLICATE LAST把同一时间戳的新值当作修正版,覆盖原值;ON_DUPLICATE SUM把新值当作同一时间戳下的新增量,与旧值相加。两者都只覆盖当前这一次TS.ADD调用,不会替你修改时间序列的长期配置。
一次重复上报为什么会影响整段指标
这类异常的影响面通常不在所有时间点,而只集中在重复写入的时间戳。设备采样、消息重放、网络重试和补数据脚本都可能把同一条记录送来两次。若原始采样是 10,重试请求又带着 12:
- 用
LAST,这个时间点最终表达“最新一次收到的值”,结果是 12; - 用
SUM,这个时间点最终表达“两个值的累计”,结果是 22。
所以排查时不要只看命令是否成功,还要先回答:重复请求是同一采样的重放,还是两次应该累计的增量?这个业务含义决定策略。

时间线里真正的触发条件:时间戳相同
TS.ADD 的时间戳以毫秒为单位,也可以使用 * 让服务端生成当前时间。只有两次采样落在同一个时间戳时,重复策略才会参与决定如何处理旧值。时间戳不同,就不是这篇文章讨论的重复点。
用两个独立的时间序列做对照,可以避免把前一个实验的结果混到后一个实验里:
# 固定一个毫秒时间戳,模拟同一条采样的首次写入 redis-cli TS.ADD meter:last 1710000000000 10 # 同一时间戳再次到达时,用新值覆盖旧值 redis-cli TS.ADD meter:last 1710000000000 12 ON_DUPLICATE LAST # 读取这个时间点,观察 LAST 的最终值 redis-cli TS.RANGE meter:last 1710000000000 1710000000000
这个例子中,第二次写入表达“12 是这个采样点的修正版”,因此最终值应按 12 理解。这里的关键不是第二次请求更新了整条序列,而是它在同一个时间戳上覆盖了原来的样本。
根因对比:LAST 是替换,SUM 是累计
我后来把异常请求拆成两个最小场景:一个场景模拟设备重试,另一个场景模拟电量脉冲或订单件数这类增量。命令结构很像,但读数含义完全不同。
# 首次写入 10,准备一个可以被重试覆盖的采样点 redis-cli TS.ADD meter:last 1710000000000 10 # 重试带来修正值 12,LAST 只保留这次新值 redis-cli TS.ADD meter:last 1710000000000 12 ON_DUPLICATE LAST # 首次写入 10,准备一个需要累加增量的采样点 redis-cli TS.ADD meter:sum 1710000000000 10 # 第二个请求代表新增 12,SUM 将旧值和新值相加 redis-cli TS.ADD meter:sum 1710000000000 12 ON_DUPLICATE SUM # 分别读取两个点,确认比较的是业务语义而不是命令返回格式 redis-cli TS.RANGE meter:last 1710000000000 1710000000000 redis-cli TS.RANGE meter:sum 1710000000000 1710000000000
对这组输入,meter:last 的点应理解为 12,meter:sum 的点应理解为 22。官方命令语义也是如此:LAST 用新值覆盖,SUM 在已有样本时计算“旧值 + 新值”;如果该时间戳还没有旧样本,SUM 就直接使用新值。
这解释了故障的根因:把“重复送达”误判成“新增事件”,会让 SUM 在消息重试时重复计数;反过来,把本应累加的脉冲数据改成 LAST,又会丢掉前一次增量。
修复动作:把策略限制在当前一次 TS.ADD
ON_DUPLICATE 是一次命令级覆盖参数。它只影响当前这条 TS.ADD 如何处理同一时间戳的重复样本,不会把时间序列的长期重复策略永久改掉。这一点很适合修复边界明确的回放任务:你可以让一次补数任务使用 LAST,而不必把整个序列的后续写入逻辑一起改掉。
修复时我会先给数据源分类,再把策略写在调用点:
| 数据来源 | 重复请求代表什么 | 单次 TS.ADD 建议 |
|---|---|---|
| 设备心跳、周期采样 | 同一采样的重试或重放 | ON_DUPLICATE LAST |
| 补采脚本修正历史值 | 人工确认后的新版本 | ON_DUPLICATE LAST |
| 脉冲计数、订单件数增量 | 应该合并的新增量 | ON_DUPLICATE SUM |
| 无法确定的混合来源 | 请求身份和业务含义不清 | 先暂停自动累加,补齐来源字段 |
需要特别注意:如果命令同时负责创建一个不存在的时间序列,ON_DUPLICATE 对这次创建没有可比较的旧样本,因此不会产生覆盖或累加效果。真正的策略差异出现在目标时间序列已经存在、且目标时间戳已有样本时。

防复发:让重试和新增量在入口就分开
只替换命令参数还不够。下一次排查时,至少要保留采样来源、业务事件标识和采样时间戳,让读者能判断两个请求是不是同一条数据。对于可重试的采样上报,调用方应保持同一个时间戳和事件身份;对于累计事件,应该明确每次请求到底代表一个新事件还是同一个事件的重放。
- 在日志中同时记录序列 key、时间戳、上报来源和选择的重复策略;
- 把“消息重试”与“业务新增量”分成不同的写入路径,不要只靠调用方口头约定;
- 修复历史数据前,先确认同一时间戳的旧值是否已经包含部分累计量;
- 将
LAST或SUM写入代码注释和接口文档,避免后续维护者把它当成可互换参数。
最后的判断
如果你面对的是“同一采样再次送达”,选 ON_DUPLICATE LAST;如果你面对的是“同一时间点还要合并一笔新发生的增量”,选 ON_DUPLICATE SUM。两者的命令形式几乎只差一个单词,但它们表达的是覆盖模型和累计模型的区别。发布修复前,先根据数据来源确认重复请求的业务含义,再把策略限定在需要它的那次 TS.ADD。
相关问题
ON_DUPLICATE SUM 第一次写入会不会把值加倍?
不会。指定时间戳没有旧样本时,SUM 使用新值;只有已有样本时才进行旧值与新值相加。
ON_DUPLICATE LAST 会修改整个时间序列的默认策略吗?
不会。它是当前命令的覆盖参数,文章讨论的范围只包括这一次 TS.ADD 的重复样本处理。
两个请求时间戳不同,还需要比较 LAST 和 SUM 吗?
如果时间戳不同,就不属于同一时间戳重复写入。此时应先检查采样时间是否被错误转换、截断或回退,再判断是否需要重复策略。
Pixi 怎么在 CI 中检查 pixi.lock 是否和项目配置同步
- 上一篇
- Pixi 怎么在 CI 中检查 pixi.lock 是否和项目配置同步
- 下一篇
- Pixi 怎么按 feature 建隔离环境并运行同一个项目任务
-
- 数据库 · Redis | 29分钟前 | Redis · redis Redis Cluster CLUSTER BUMPEPOCH current epoch configEpoch 集群拓扑
- Redis CLUSTER BUMPEPOCH 什么时候适合修正拓扑纪元
- 364浏览 收藏
-
- 数据库 · Redis | 29分钟前 | Redis · 命令行工具 · 运维 · redis 内存测试 redis-server 硬件诊断 --test-memory Redis排障
- redis-server --test-memory 怎么判断内存测试结果
- 166浏览 收藏
-
- 数据库 · Redis | 29分钟前 |
- RediSearch FT.CREATE 的 FILTER 怎么只索引满足条件的文档
- 194浏览 收藏
-
- 数据库 · Redis | 32分钟前 |
- redis_exporter 怎么配置 HTTP 监听地址和 metrics 路径
- 109浏览 收藏
-
- 数据库 · Redis | 36分钟前 | Redis · 故障排查 · docker redis NAT Redis Cluster MOVED cluster-announce-ip cluster bus
- Redis Cluster 容器部署时 cluster-announce-ip 怎么填写节点可达地址
- 242浏览 收藏
-
- 数据库 · Redis | 37分钟前 | Redis · 故障排查 · redis timeout redis.conf 客户端连接 半开连接 tcp-keepalive
- Redis tcp-keepalive 和 timeout 有什么区别
- 116浏览 收藏
-
- 数据库 · Redis | 40分钟前 |
- Redis redis-cli --askpass 怎么避免密码出现在进程参数中
- 485浏览 收藏
-
- 数据库 · Redis | 1天前 |
- Redis LATENCY DOCTOR怎样从延迟报告定位事件类型
- 246浏览 收藏
-
- 数据库 · Redis | 1天前 |
- Redis WAITAOF怎样等待写入到 AOF 磁盘
- 499浏览 收藏
-
- 数据库 · Redis | 1天前 |
- Redis HPEXPIRE 怎样按毫秒设置哈希字段过期时间
- 487浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 893次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 894次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 978次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 966次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 793次使用
-
- Redis Stream XTRIM 如何避免消费组积压无限增长
- 2026-09-12 501浏览
-
- Redis AOF rewrite 期间如何判断磁盘与内存压力
- 2026-09-12 501浏览
-
- Redis RDB 和 AOF 怎么按可接受数据丢失量选择
- 2026-09-08 501浏览
-
- Redis XAUTOCLAIM 之后为什么仍有 pending:JUSTID、PEL 与消息删除边界
- 2026-08-29 501浏览
-
- Redis SET 的 GET 与 KEEPTTL 怎么一起验收:旧值返回、续期与回滚边界
- 2026-08-20 501浏览

