我之前在阿里巴巴技术部门担任团队面试官,多次负责淘宝双十一的订单系统维护,工作 2 年多从未出过 bug,对于这个问题我还是比较有发言权的。
利益相关,拿几个订单系统的设计要点跟大家聊一聊。
当商家将产品库存设置为有限数量时,买家下单产品就会减少相应的库存,其实现机制是:
读取库存表,判断库存,然后扣减库存
1.查询库存余量
SELECT available_stock FROM `seckill_activity`
WHERE commodity_id = 189 AND id = 28;
2.扣减库存
UPDATE `seckill_activity` SET available_stock = available_stock- 1
WHERE commodity_id = 189 AND id = 28 AND available_stock > 0;
然而当大流量并发请求数据库时,就有可能导致系统崩溃,导致超卖。超卖即“超卖缺货”,当宝贝库存接近 0 时,如果多个买家同时付款购买此宝贝,就会出现“超卖缺货”现象。
这种情况一般会出现在大型秒杀活动上,每个秒杀的用户都去数据库查询库存校验库存,然后扣减库存,导致数据库崩溃。
应对措施是将库存信息加载到 Redis 中,将 MySQL 的访问压力转移到 Redis 上,直接通过 Redis 来判断并扣减库存。订单系统常用的数据库是 MySQL,但在秒杀环境下会将库存信息加载到 Redis 中,将 MySQL 的访问压力转移到 Redis 上,直接通过 Redis 来判断并扣减库存。
这是因为两者的性能不同:MySQL 数据库单点能支撑** 1000 QPS,但是 Redis 单点能支撑 10 万 QPS**,更适合秒杀环境。
重点来了,订单系统设计中最常考的一个知识点就是 Redis 的特点。
想了解关于Redis 的更多应用场景,可以移步我主讲的免费讲座《电商秒杀项目实战》,系统介绍了订单系统中用到的各种技术栈和知识点,提供项目源代码,带你用 2 周时间完成一个完整的秒杀系统项目。
戳我即可免费试听
1.缓存库存信息
由于大部分数据读取请求都被 Redis 挡住了,保护了 MySQL
2.检查 Redis 库存和扣减
Redis 库存是两步操作,通过 Lua 脚本将这两步操作,合并成一个整体,保证原子操作性
3.MySQL 复检
哪怕 Redis 侧方行,可以创建订单了,到 MySQL 的时候也需要再检查一次
Redis 的扩展还有 Lua 脚本,Lua 脚本功能是 Reids 在 2.6 版本中推出, 通过内嵌对 Lua 环境的支持,Redis 解决了长久以来不能高效地处理 CAS ( Compare And Swap )命令的缺点并且可以通过组合使用多个命令, 轻松实现以前很难实现或者不能高效实现的模式。
Lua 脚本是类似 Redis 事务,有一定的原子性,不会被其他命令插队,可以完成一些 Redis 事务性的操作。
此外,关于订单系统如何应对瞬时大流量高并发、如何保证系统稳定和高可用,我在《电商秒杀系统 - Spring 项目实战》里都有深度的分析,目前开放免费试听,对订单系统感兴趣的朋友戳我体验一下。