一、系统架构分层设计:解耦与扩展性
1.1 分层架构选型
采用经典的三层架构(接入层-服务层-数据层),结合业务特性增加优惠券模板服务、用户领券服务、核销服务三个独立微服务。接入层使用Nginx+Lua实现动态路由,服务层通过gRPC进行内部通信,数据层采用分库分表+缓存双写策略。
# Nginx动态路由配置示例upstream coupon_services {server 10.0.0.1:8080 weight=5;server 10.0.0.2:8080 weight=3;server 10.0.0.3:8080 backup;}server {location /api/coupon {set $backend "";if ($arg_action = "claim") {set $backend coupon_claim;}proxy_pass http://$backend;}}
1.2 服务拆分原则
- 模板服务:处理优惠券规则配置(满减、折扣、有效期等)
- 领券服务:实现限流控制、库存扣减、用户黑名单校验
- 核销服务:对接订单系统,验证优惠券有效性
- 监控服务:实时采集QPS、错误率、延迟等指标
二、数据库优化:支撑百万级并发读写
2.1 分库分表策略
采用用户ID取模分库+优惠券ID范围分表的混合方案:
-- 创建分库分表示例CREATE DATABASE coupon_db_0;CREATE DATABASE coupon_db_1;CREATE TABLE coupon_db_0.coupon_0 (id BIGINT PRIMARY KEY,user_id BIGINT,template_id BIGINT,status TINYINT,expire_time DATETIME) PARTITION BY RANGE (id) (PARTITION p0 VALUES LESS THAN (1000000),PARTITION p1 VALUES LESS THAN (2000000));
2.2 读写分离实现
通过MyCat中间件实现自动路由,写请求发往主库,读请求按权重分配至从库。配置中设置writeHost和readHost节点,并启用连接池复用。
2.3 事务处理方案
对库存扣减等关键操作采用分布式锁+本地事务组合:
// Redis分布式锁实现public boolean tryAcquireLock(String key, long expire) {String result = redisTemplate.opsForValue().setIfAbsent(key, "1", expire, TimeUnit.SECONDS);return Boolean.TRUE.equals(result);}// 库存扣减事务示例@Transactionalpublic boolean deductStock(Long couponId) {if (!tryAcquireLock("lock:" + couponId, 5)) {throw new RuntimeException("获取锁失败");}try {Coupon coupon = couponMapper.selectById(couponId);if (coupon.getStock() <= 0) {return false;}couponMapper.updateStock(couponId, coupon.getStock() - 1);return true;} finally {redisTemplate.delete("lock:" + couponId);}}
三、缓存体系构建:毫秒级响应
3.1 多级缓存架构
- 本地缓存:Guava Cache存储热点数据(如用户已领优惠券列表)
- 分布式缓存:Redis集群存储模板规则、全局库存
- CDN缓存:静态资源(优惠券图片、规则说明)
// Guava本地缓存配置LoadingCache<String, CouponTemplate> templateCache = CacheBuilder.newBuilder().maximumSize(10000).expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader<String, CouponTemplate>() {@Overridepublic CouponTemplate load(String templateId) {return redisTemplate.opsForValue().get("template:" + templateId);}});
3.2 缓存穿透解决方案
- 空值缓存:对不存在的优惠券ID缓存NULL值
- 布隆过滤器:预加载所有有效优惠券ID
- 互斥锁:缓存未命中时只允许一个请求查询数据库
3.3 缓存雪崩预防
- 随机过期时间:在基础过期时间上增加±5分钟随机值
- 多级缓存:本地缓存与Redis缓存设置不同过期时间
- 限流降级:缓存失效时触发流量控制
四、流量控制与降级策略
4.1 动态限流算法
采用令牌桶算法实现平滑限流:
// Guava RateLimiter实现private final RateLimiter rateLimiter = RateLimiter.create(1000.0); // 每秒1000个请求public boolean tryAcquire() {return rateLimiter.tryAcquire();}// 分布式限流(Redis+Lua实现)String luaScript ="local key = KEYS[1]\n" +"local limit = tonumber(ARGV[1])\n" +"local current = tonumber(redis.call('GET', key) or '0')\n" +"if current + 1 > limit then\n" +" return 0\n" +"else\n" +" redis.call('INCRBY', key, '1')\n" +" redis.call('EXPIRE', key, '1')\n" +" return 1\n" +"end";
4.2 服务降级方案
- 熔断机制:Hystrix实现服务调用超时自动降级
- 静态页面:系统过载时返回预生成的HTML
- 队列削峰:将领券请求写入Kafka,异步处理
五、压测与优化实战
5.1 全链路压测方案
使用JMeter模拟10万QPS请求:
<!-- JMeter线程组配置 --><ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup"><stringProp name="ThreadGroup.num_threads">1000</stringProp><stringProp name="ThreadGroup.ramp_time">60</stringProp><stringProp name="ThreadGroup.duration">300</stringProp></ThreadGroup><!-- HTTP请求采样器 --><HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy"><elementProp name="HTTPsampler.Arguments" elementType="Arguments"><collectionProp name="Arguments.arguments"><elementProp name="couponId" elementType="HTTPArgument"><stringProp name="Argument.value">${__Random(1,1000000)}</stringProp></elementProp></collectionProp></elementProp></HTTPSamplerProxy>
5.2 性能瓶颈定位
- 慢查询分析:通过pt-query-digest定位耗时SQL
- 链路追踪:SkyWalking实现全链路调用跟踪
- 火焰图分析:使用async-profiler定位CPU热点
5.3 优化效果验证
经过三轮优化后关键指标对比:
| 优化项 | 优化前QPS | 优化后QPS | 延迟降低 |
|————————|—————-|—————-|—————|
| 数据库分库 | 3,200 | 8,500 | 62% |
| Redis集群 | 5,800 | 12,000 | 51% |
| 连接池复用 | 7,200 | 15,000 | 52% |
| 静态化改造 | 9,500 | 22,000 | 57% |
六、运维监控体系
6.1 监控指标设计
- 业务指标:领券成功率、核销率、优惠金额
- 系统指标:QPS、响应时间、错误率
- 基础设施:CPU使用率、内存占用、网络IO
6.2 告警策略配置
- 阈值告警:QPS持续5分钟超过90%峰值时触发
- 趋势告警:响应时间10分钟内上升30%时告警
- 关联告警:数据库连接数超限+慢查询数激增
6.3 自动化运维
- 弹性伸缩:根据QPS自动调整容器副本数
- 金丝雀发布:新版本先接收1%流量验证
- 混沌工程:定期模拟网络分区、服务宕机等故障
七、实战经验总结
- 渐进式优化:先解决数据库瓶颈,再优化缓存,最后处理网络层
- 全链路压测:必须模拟真实用户行为,包括参数分布、请求间隔
- 容灾设计:关键服务需具备跨机房部署能力
- 数据一致性:最终一致性方案需设计补偿机制
- 成本平衡:在QPS、延迟、硬件成本间找到最佳平衡点
通过上述方案,某电商平台的优惠券系统成功支撑了双11期间12.7万QPS的峰值流量,领券接口平均响应时间控制在48ms以内,系统可用性达到99.99%。实际开发中需根据业务特性调整技术选型,建议先实现基础功能,再逐步优化高并发场景。