Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
b76cc583
Commit
b76cc583
authored
Jan 12, 2026
by
yangjianbo
Browse files
去掉失误提交的openspec提案
parent
955af6b3
Changes
4
Show whitespace changes
Inline
Side-by-side
openspec/changes/update-rate-limit-ttl-atomic/design.md
deleted
100644 → 0
View file @
955af6b3
## Context
限流中间件当前采用
`INCR`
后
`EXPIRE`
的两步操作,且未处理
`EXPIRE`
失败,导致计数 key 可能没有过期时间。该情况一旦发生,计数会持续累加,触发长期限流并造成 Redis key 膨胀。
## Goals / Non-Goals
-
Goals:
-
原子化 Redis 计数与过期设置
-
修复 TTL 缺失的历史 key
-
支持按接口配置 Redis 故障策略(fail-open/fail-close)
-
为需要强制保护的接口启用 fail-close
-
Non-Goals:
-
改变现有固定窗口限流算法
-
调整限流 key 格式或前缀
-
引入新的外部依赖
## Decisions
-
使用 Lua 脚本在 Redis 内部原子执行
`INCR`
、
`TTL`
与
`PEXPIRE`
-
过期时间统一采用毫秒精度窗口(
`window.Milliseconds()`
向下取整)以保持精度一致
-
当毫秒窗口小于 1 时,按 1ms 设置过期,避免 0 导致立即过期
-
当
`count == 1`
或
`TTL == -1`
时设置过期,避免刷新已有 TTL
-
新增
`RateLimitOptions`
并提供
`LimitWithOptions`
,由调用方显式配置故障策略
-
`Limit`
默认使用 fail-open 以保持兼容
-
当 fail-close 生效时,Redis 执行失败直接返回 429
## Alternatives considered
-
使用
`MULTI/EXEC`
事务封装
`INCR`
+
`EXPIRE`
:原子性可保证,但无法在同一事务内便捷修复
`TTL == -1`
,且仍需额外判断逻辑
-
使用
`SET`
+
`EX`
/
`NX`
组合:无法保留计数累加语义
## Risks / Trade-offs
-
Lua 脚本会带来轻微 CPU 开销,但可接受
-
TTL 修复会在首次访问时设定过期,可能缩短历史脏 key 的“无限期”状态,这是期望的修复效果
## Migration Plan
-
上线后脚本在请求路径上自动修复 TTL 缺失的 key
-
如需回滚,恢复原有两步命令即可
## Open Questions
-
无
openspec/changes/update-rate-limit-ttl-atomic/proposal.md
deleted
100644 → 0
View file @
955af6b3
# Change: 原子化 Redis 限流 TTL 设置
## Why
当前限流逻辑使用
`INCR`
后再
`EXPIRE`
,非原子且未处理
`EXPIRE`
失败,会导致 key 可能永久存在,引发长期限流或 Redis 内存增长。
## What Changes
-
使用 Lua 脚本原子化
`INCR`
+ 过期设置
-
当检测到 TTL 缺失时补设过期,修复历史脏数据
-
支持 Redis 故障策略配置(默认放行,特定接口可 fail-close)
-
新增
`limit-requests`
capability,用于描述限流行为与故障策略
## Impact
-
Affected specs: 新增
`specs/limit-requests/spec.md`
-
Affected code:
`backend/internal/middleware/rate_limiter.go`
openspec/changes/update-rate-limit-ttl-atomic/specs/limit-requests/spec.md
deleted
100644 → 0
View file @
955af6b3
## ADDED Requirements
### Requirement: 原子化限流计数与过期
限流中间件 SHALL 在单个原子操作中完成 Redis 计数增量与过期设置,并且仅在首次创建或 TTL 缺失时设置过期,避免刷新已有 TTL;过期时间以毫秒为单位向下取整,最小为 1ms。
#### Scenario: 首次请求创建计数器
-
**WHEN**
第一次请求命中该限流 key
-
**THEN**
计数增量为 1 且 key 过期时间设置为窗口值
#### Scenario: 窗口小于 1ms
-
**WHEN**
限流窗口小于 1ms
-
**THEN**
过期时间按 1ms 设置
#### Scenario: 窗口包含非整数毫秒
-
**WHEN**
限流窗口包含非整数毫秒
-
**THEN**
过期时间按毫秒向下取整
#### Scenario: 已有 TTL 的计数器继续计数
-
**WHEN**
计数器已存在且 TTL 正常
-
**THEN**
计数递增且 TTL 不被刷新
#### Scenario: 计数器缺失 TTL
-
**WHEN**
计数器存在但 TTL 为 -1
-
**THEN**
系统为该 key 补设窗口过期时间
### Requirement: Redis 故障策略可配置
限流中间件 SHALL 支持为每个限流 key 配置 Redis 故障策略,支持 fail-open 与 fail-close,默认 fail-open,配置由调用方在注册限流时提供。
#### Scenario: fail-open 策略
-
**WHEN**
配置为 fail-open 且 Redis 脚本执行返回错误或连接不可用
-
**THEN**
请求继续处理且不执行限流阻断
#### Scenario: fail-close 策略
-
**WHEN**
配置为 fail-close 且 Redis 脚本执行返回错误或连接不可用
-
**THEN**
请求被限流阻断并返回 429
### Requirement: 优惠码验证接口 fail-close
系统 SHALL 对
`/auth/validate-promo-code`
的限流在 Redis 故障时采用 fail-close。
#### Scenario: 验证优惠码时 Redis 不可用
-
**WHEN**
请求
`/auth/validate-promo-code`
且 Redis 不可用
-
**THEN**
请求返回 429
openspec/changes/update-rate-limit-ttl-atomic/tasks.md
deleted
100644 → 0
View file @
955af6b3
## 1. Implementation
-
[x] 1.1 在限流中间件中引入 Lua 脚本原子化计数与过期设置(使用 PEXPIRE 毫秒窗口)
-
[x] 1.2 脚本内检测
`TTL == -1`
时补设过期,修复历史脏 key
-
[x] 1.3 引入
`RateLimitOptions`
与
`LimitWithOptions`
,
`Limit`
保持默认 fail-open
-
[x] 1.4 为
`/auth/validate-promo-code`
配置 fail-close 策略
-
[x] 1.5 添加测试覆盖首次请求、已有 TTL、TTL 缺失、非整数毫秒窗口与故障策略(使用 Redis 集成测试/testcontainers 方案)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment