feat(mq-starter-redis-stream): 订阅 stream 定时裁剪,复用 redis-stream.trim.* 默认开启

底层中间件的 trim 任务只认自己注册的 handler(无 handler 不启动),mq-starter 不走
handler 体系,此前只经 mq-starter 收发的 topic 无界涨 Redis 内存。driver 现自带
RedisStreamTrimScheduler:订阅时登记 stream,按 trim.interval-ms(默认 60s)对登记过的
stream 执行 XTRIM MAXLEN ~ maxlen(默认 10 万),stop 时随 driver 停止。

- maxlen<=0 视为关闭(XTRIM 0 会清空整条 stream,绝不能发出)
- 只裁订阅过的 stream,纯发送方不裁,与中间件 handler 即消费者的语义对齐
- 单 stream 裁剪失败仅 WARN,不中断其余 stream
- README trim/autoclaim 行改述真实行为,CLAUDE.md 模块描述同步

注意:默认开启,升级后订阅 stream 开始按 maxlen 封顶;裁剪不看消费进度,
堆积超限时最老的未消费消息会被删,容量按可容忍停机时长×生产速率估算。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 10:25:29 +01:00
parent 2b635a4cd7
commit 8bba71236f
5 changed files with 264 additions and 4 deletions

View File

@@ -301,8 +301,8 @@ Redis 连接走标准 `spring.redis.*`。另有一组更底层的参数(前缀
| `block-ms` | 2000 | 拉取无消息时的阻塞等待毫秒数到点空手返回进下一轮 |
| `consumer-name` | | 组内消费者名留空则每次启动生成随机名推荐重启遗留的 PEL reclaim 拿回写死会让多实例同名PEL 归属混在一起 |
| `max-retry` | 3 | 兜底重试次数 `@MqListener` `maxRetry` 配成 0/负数时才用到 |
| `trim.maxlen` / `trim.interval-ms` | 100000 / 60s | **对 mq-starter 消费的 stream 不生效**中间件的定时裁剪只认自己注册的 handler stream handler 时任务不启动mq-starter 不走那套 handler只经 mq-starter 收发的 topic **没有任何裁剪、无界增长**要封顶得靠直连中间件的服务碰巧订同一 topic或运维层面自行 XTRIM |
| `autoclaim.*` | | 同上 mq-starter 不生效也是按 handler streammq-starter 有自己的 reclaim配上表的 `mq.redis-stream.reclaim-min-idle` |
| `trim.maxlen` / `trim.interval-ms` | 100000 / 60s | stream 封顶裁剪**默认开启**driver **订阅过** stream 每周期执行一次 `XTRIM MAXLEN ~ maxlen``~` 近似裁剪实际长度可能略超 maxlen)。⚠ 裁剪只按条数砍最老的、**不看消费进度**——堆积超过 maxlen 时未消费的老消息也会被删容量按可容忍的最大停机时长 × 生产速率估算`maxlen` 0/负数关闭纯发送不订阅的 topic 不裁裁剪节奏归消费方 |
| `autoclaim.*` | | mq-starter **不生效**中间件的 autoclaim 只认自己注册的 handler stream handler 任务不启动mq-starter 不走那套mq-starter 有自己的 reclaim配上表的 `mq.redis-stream.reclaim-min-idle` |
RocketMQ 这边直接复用 rocketmq-spring 原生的 `rocketmq.*` 配置`name-server``producer.group` )。