共计 2227 个字符,预计需要花费 6 分钟才能阅读完成。
1. 真实案例:大促期间的验证码之痛
去年 618 大促期间,我们电商平台的短信验证码服务经历了严峻考验。峰值时段出现:

- 发送接口超时率高达 35%
- 部分用户重复收到 5 条以上相同验证码
- 凌晨库存更新时出现验证码服务雪崩
事后分析发现核心问题在于:
- 同步调用第三方 API 导致线程池耗尽
- 缺乏有效的请求限流机制
- 失败重试策略不合理引发连锁反应
2. 整体架构设计
2.1 基于 Kafka 的异步削峰
flowchart LR
A[客户端] -->| 同步调用 | B(API 网关)
B -->| 异步写入 | C[Kafka]
C --> D[消费者组]
D -->| 批量处理 | E[Claude API]
E --> F[(Redis)]
关键设计点:
- 网关层仅做基础参数校验,200ms 内快速响应
- Kafka 分区数与消费者实例数按 1:3 配置
- 消费者采用批量拉取模式(每批次 100-200 条)
2.2 防刷策略实现
Redis 原子计数器方案
-- KEYS[1]: 手机号 ARGV[1]: 时间窗口 (秒) ARGV[2]: 最大次数
local current = redis.call('INCR', KEYS[1])
if tonumber(current) == 1 then
redis.call('EXPIRE', KEYS[1], ARGV[1])
end
return tonumber(current) > tonumber(ARGV[2]) and 0 or 1
执行效果:
- 第一次请求:设置计数器并初始化 TTL
- 后续请求:原子性递增判断
- 返回 0 表示触达限流,1 表示允许通过
2.3 验证码存储设计
采用双 Redis 结构存储:
// 验证码本体存储(5 分钟过期)stringRedisTemplate.opsForValue().set(
"vc:" + phone,
code,
5, TimeUnit.MINUTES);
// 验证状态标记(10 分钟过期)stringRedisTemplate.opsForValue().set(
"vc_verified:" + phone,
"1",
10, TimeUnit.MINUTES);
3. 核心代码实现
3.1 Spring Boot 集成示例
@RestController
public class VcController {
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@PostMapping("/send")
public ResponseEntity<String> send(@Valid @RequestBody VcRequest request) {
// 防刷校验
if (!rateLimiter.check(request.getPhone())) {return ResponseEntity.status(429).build();}
// 构造事件消息
VcEvent event = new VcEvent(UUID.randomUUID().toString(),
request.getPhone(),
generateRandomCode());
// 异步发送 Kafka
kafkaTemplate.send("vc_topic",
request.getPhone(),
JsonUtils.toJson(event));
return ResponseEntity.accepted().build();
}
}
3.2 Claude 客户端配置
claude:
sms:
endpoint: https://api.claude.com/v3/sms
retry:
maxAttempts: 3
backoff: 1000ms
circuitBreaker:
failureRateThreshold: 30%
waitDuration: 30s
4. 生产环境验证
4.1 压测数据对比
| 指标 | 改造前 | 改造后 |
|---|---|---|
| 单节点 QPS | 217 | 1584 |
| 平均响应时间 | 1200ms | 85ms |
| 99 分位延迟 | 2500ms | 210ms |
4.2 监控指标建议
# 请求量统计
claude_sms_requests_total{status="success"}
claude_sms_requests_total{status="failure"}
# 处理耗时
claude_sms_duration_seconds_bucket{le="0.1"}
claude_sms_duration_seconds_bucket{le="0.5"}
# 熔断器状态
resilience4j_circuitbreaker_state{name="claudeSms"}
4.3 故障排查手册
场景 1:验证码发送延迟高
- 检查 Kafka 消费者 lag
- 确认 Claude API 健康状态
- 验证 Redis 连接池使用率
场景 2:重复收到验证码
- 检查防刷 Lua 脚本执行日志
- 验证 Kafka 消息是否重复消费
- 审计消费者组的 offset 提交
5. 开放性思考
5.1 有效期与安全性平衡
- 金融类场景:3 分钟有效期 + 6 位复杂码
- 社交类场景:10 分钟有效期 + 4 位简码
- 考虑引入动态有效期机制
5.2 多通道降级方案
graph TD
A[主通道 Claude] -->| 失败 | B[备用通道 AWS SNS]
B -->| 失败 | C[本地短信猫]
C -->| 失败 | D[邮件通知]
核心原则:
- 降级策略需要分级配置
- 每个通道独立熔断控制
- 最终兜底方案必须存在
总结
通过这套架构,我们实现了:
- 峰值流量削峰能力提升 8 倍
- 防刷漏过率降至 0.01% 以下
- 季度运维人力成本降低 60%
未来可优化方向包括:
- 基于用户行为的智能限流
- 多通道自动质量择优
- 端到端加密验证方案
正文完
