秒杀系统的设计思路。
1、下单过程:
校验库存
更新库存
创建订单
支付(本文暂先不考虑)
2、表的概要设计
库存表:id、名称、库存数、已售数,版本号(防止超卖)。
订单表:id、订单名称、库存表id,订单创建时间。
3、考虑到的问题。
首先,超卖问题,也就是说原来计划最大卖30个,结果卖了1000多个。
解决方法:采用乐观锁(CAS,比较并交换的意思,只有比较相等才能交换,否则不交换)。
更新库存的数据库语句可以这么设计,
update 库存表 set 版本号= 版本号+1,已售数 = 已售数+1
where 版本号 = 版本号 and id = 传过来的id
注:version_old_query是通过id查询出来的。
其次,数据库宕机和系统报错(查询数据库因为版本号不对,更新库存失败导致的报错)的问题,
数据库宕机往往是连接数不够导致的宕机,毕竟并发数比较大。
解决方法:限流+缓存。本身redis有限流,快速失败返回的策略,也就是限制访问数,每次访问
数只能是固定的,如果访问不到,则直接返回,这个限流类似java的信号量这个类。通过和
springmvc集成即可,而采用先查缓存,缓存里如果没有则去查数据库,这样,通过redis限流
把大部分流量拦截在上游,使之不能到达数据库,缓存提高查询效率等。很好的解决了数据层的
访问问题了,但redis最好采用集群的模式,毕竟秒杀的访问量还是很大的,我认为redis的限流
措施往往起到的保护系统的作用,限流最好用nginx、springcloud或者dubbo横向扩展来实现。
最后,如果进来到下单的并发量还是很大,可以将同步下单改成异步下单的形式。
解决方法:采用kafka发送库存的实体,然后马上返回,kafka和springboot集成的消费端,
采用线程池消费任务,对库存进行缓存和落地更新及创建订单,然后回调通知。
—— 未完待续 ——