秒杀系统交易模块优化(一)

Scroll Down

应用场景:秒杀系统-秒杀模块
表设计:库存和商品信息是两张表
目的:在系统依旧稳定运行的情况下,提高一定量的TPS。

未优化前:先做正则校验,用户信息是否存在,商品信息是否存在,活动信息是否存在,校验过后,进行正式交易。先对Mysql的库存表去进行减库存,如果库存删减成功则订单入库.

存在问题
1.交易验证完全依赖于数据库(商品信息的校验,活动信息的校验)
2.库存的行锁问题(大量并发进来,会有行锁的抢占)

Jemeter压测环境:4核8G内存
压测结果:TPS250~300,响应时间500ms

实施优化
检验流程:将用户信息,商品信息与活动信息存入Redis做一个缓存,不走Mysql。

检验优化效果
压测结果:TPS1000~1200,响应时间600ms

继续实施优化
优化过程:当我们在减少库存的时候,用到了
update item_stock set stock = stock - #

where item_id = #
and stock >= #
这条语句,我们知道,在Mysql中update会用到where里面的索引列,会有一个行锁,要是这个列没有用到索引那么会升级到表锁,所以我们要注意,一定要用到索引。上面语句中,itemId我是有创建唯一索引的,所以这里是用到了行锁。

第一反应,我们想一想,能不能把减库存这个操作,也往Redis里面上引入,我先用Redis做一层缓存(当活动发布时,库存缓存),减库存的时候,都在Redis里面进行减,最后再将库存的值引入Mysql。这样虽然可以提高性能,但是又存在了一个问题,达不到Redis和Mysql一致性的问题,所以我们要想想如何来完成这个一致性的问题。

要想完成Redis和Mysql的信息同步,又不影响库存在Redis里面的减操作,这时候可以想到,通过异步来实现数据同步的问题,异步,一想到异步,咱们就可以想到消息队列来进行操作,当Redis减完后,发一条消息给消息队列,让消息队列再去消费这条消息,实现Mysql的数据同步。