软考案例题和大厂高级架构师面试,经常会遇到同一个业务:秒杀。
奇妙的是,同一套技术方案,用同一种说法去答,效果可能完全不同。
软考案例题希望你在有限时间里命中知识点,写出措施、原因、权衡和指标;架构面试则会顺着你的方案继续追问:流量怎么估?Redis挂了怎么办?消息重复了怎么办?库存到底以谁为准?
所以真正值得练的,不是一段万能答案,而是同一套架构的两种表达。
下面用一个练习用假设场景完整走一遍。数字用于演示分析方法,不代表真实项目或考试题。
先把场景说清楚
某电商平台进行限时(秒杀)活动:
- 系统需要防止超卖、重复下单,并向用户返回明确状态。
如果拿到题目就直接写Redis和消息队列……那就少一步:先把矛盾说出来。
这个场景的核心矛盾是:稀缺库存只有5000份,入口请求却在极短时间集中到达;数据库不能同步处理全部竞争请求,但库存结果又必须可追踪、可补偿。
一套可讲清楚的秒杀架构
1. 静态资源前置,减少无关回源
商品图片、活动说明和倒计时等静态内容由CDN承载。活动按钮在前端按服务器时间展示,但是否允许下单必须由服务端判断,不能把业务安全寄托在一段JavaScript上。
它解决的是页面访问洪峰,不直接解决库存竞争。
2. 网关做身份、资格和流量治理
网关校验登录态、活动时间、用户资格和请求签名,再按用户、设备、IP或活动维度限流。对超出容量的请求快速返回“排队中”或“本轮已结束”,避免无效流量进入核心链路。
限流阈值不能拍脑袋。应根据网关、Redis、消息队列和消费者的压测结果确定,并预留故障余量。
3. Redis保存活动库存,Lua完成原子预扣
活动开始前将可售库存预热到Redis。Lua脚本在一次原子执行中完成:
这一步把热点竞争挡在内存层,并防止多个命令之间被并发请求插入。
需要注意:Redis预扣成功表示“获得下单资格”,不是数据库订单一定已经创建成功。
4. 消息队列削峰,消费者异步创建订单
预扣成功后,服务生成包含活动ID、用户ID、商品ID和预扣凭证的下单消息。消费者按数据库可以承受的速度创建订单。
消息发送环节要能回答两个问题:
可采用本地事件记录或可靠消息机制跟踪发送状态,由后台任务重试;客户端查询下单结果时,根据预扣凭证返回“处理中、成功、失败”。
5. 幂等键和数据库唯一约束,防止重复订单
以“活动ID+用户ID”作为业务幂等键。消费端处理消息前检查状态,数据库对该组合建立唯一约束。
即使消息至少一次投递、消费者重启或接口重试,也只能形成一笔有效订单。
幂等不等于“看见重复就静默丢掉”。重复请求还应该返回上一笔处理结果,让客户端知道自己是成功、处理中还是失败。
6. 超时关单、库存回补与对账
订单创建后15分钟未支付,系统关闭订单并产生库存回补事件。回补要带业务唯一标识,避免重复增加库存。
后台定时对账至少检查:
若差值超过阈值,触发告警并进入人工或自动修复流程。
7. 监控不只看CPU
核心指标包括:
这些指标让“高并发方案有效”从一句口号变成可验证结论。
软考案例题怎么答
软考答案要让阅卷人迅速找到得分点。可以写成下面这样:
活动开始前将库存预热到Redis,使用Lua脚本原子完成用户校验、库存判断和预扣,避免并发读改写导致超卖;网关按用户和活动限流,过滤重复及无效请求,保护核心链路。
预扣成功后通过消息队列异步创建订单,以削峰保护数据库;使用活动ID和用户ID作为幂等键,并建立数据库唯一约束,防止接口重试或消息重复投递形成多笔订单。
对消息发送失败、订单创建失败和支付超时设置重试、关单、库存回补及定时对账机制,并监控消息积压、订单创建延迟和库存差值。
这段答案命中了:
如果题目只问“Redis如何优化”,就收窄到库存预热、Lua原子操作、热点保护、幂等与故障处理,不要把整套系统全部倒进答题框。
架构面试怎么讲:90秒版本
面试不是背完整论文。先用90秒给出主线,再等面试官选方向深入。
这个场景的核心矛盾是5000份库存面对每秒约8000次入口请求,而数据库写能力低于峰值。
我会先用CDN承载静态流量,网关做身份、资格和限流;核心库存预热到Redis,通过Lua原子脚本完成一人一单校验和预扣。
预扣成功后发送下单消息,由消费者削峰写入数据库,活动ID和用户ID同时作为业务幂等键,数据库建立唯一约束。
对于预扣成功但消息失败、订单落库失败和支付超时,分别通过可靠事件重试、状态查询、关单回补和定时对账处理。
监控上重点看Redis脚本耗时、消息积压、订单创建延迟和缓存库存与有效订单的差值。
方案取舍是接受短时间的异步一致,换取峰值下的可用性,但用户端必须能查询处理中状态,库存差异也必须可补偿。
这90秒里有场景、有数字、有链路、有异常、有指标,也主动交代了取舍。面试官接下来无论问Redis、MQ还是一致性都有入口,怎能不爱你?
面试追问一:怎么保证不超卖?
建议分三层回答:
- Redis Lua原子预扣,保证热点库存不会在并发读改写中扣成不可控状态;
- 一人一单使用业务幂等键,数据库唯一约束拦截重复订单;
- 数据库创建订单时仍校验活动与订单状态,对缓存、消息和数据库做定时对账。
不要回答“用了分布式锁,所以一定不会超卖”。锁会过期,服务会暂停,网络会抖动,运维同学听到这种满格承诺也会轻轻叹气。
面试追问二:Redis挂了怎么办?
先区分故障类型。
- 主从切换期间短暂不可用:入口快速失败或返回排队状态,避免直接降级到数据库扣库存。
- 库存数据丢失或发生回退:暂停活动核心链路,根据数据库订单、事件日志和预扣记录重建状态,再决定是否恢复。
- 单个热点Key压力过大:评估分片库存,但分片会增加汇总、回补和公平性复杂度,不能为了“分片”两个字把库存拆成一地零件。
核心原则是:Redis故障时不要让所有流量穿透到数据库。
面试追问三:消息重复或积压怎么办?
消息重复依靠业务幂等键、处理状态和数据库唯一约束。消费成功后记录结果,重复消息返回已有结果。
消息积压时要看原因:消费者不足、数据库变慢、单条处理变重或外部依赖超时。可在数据库容量允许范围内扩消费者,并临时关闭非核心处理;若数据库已经是瓶颈,盲目扩消费者只会把队列里的堵车搬到数据库门口。
面试追问四:库存到底以Redis还是数据库为准?
活动进行中的快速可售判断由Redis承担;订单和支付的持久业务事实由数据库保存。两者之间通过消息、状态机、补偿和对账让状态逐步收敛。
如果业务要求所有时刻都强一致,就不能只靠上述异步方案,需要重新评估吞吐、锁粒度和用户体验。架构不是给技术颁奖,而是在约束里做选择。
两种表达,分别检查什么
今天就做一次双写练习
找一个自己熟悉的场景,例如支付、优惠券、消息推送或文件上传,写两遍:
写完检查:业务规模是否清楚,措施有没有对应风险,异常路径能否闭环,指标是否能验证,取舍是否真实。
想把这类场景继续练下去
如果你准备以真题、案例专项和论文材料为主线自学,可以到胡师傅软考淘宝资料店(https://hushifu-architecture.taobao.com)查看电子资料。专项资料适合已有基础、希望集中补案例或论文表达的人;完整资料更适合需要从知识框架开始的人。
如果你希望通过看视频听讲课的路线逐步学完,再把知识迁移到软考答题和架构场景,可看系统架构设计师27章节在线精讲课程(https://m.tenclass.cn/channel2/1898631)。课程视频持续更新,建议每个章节至少配一次独立作答或口述复盘。
店铺资料更偏“查、练、复盘”,在线课程更偏“听懂、串联、跟进度”。按自己的学习习惯选一条主线即可。
本文由胡师傅软考原创整理。文中业务规模为教学假设,技术方案用于学习讨论,应结合真实系统约束评估。未经许可,请勿复制、改编或用于商业传播。