网上有很多介绍秒杀系统架构文章,写得不错,包括前后端的实现,这里只从后台服务系统架构阐述。
打开页面时查询商品数量和点击抢购按钮提交校验时都是从本地web进程内缓存读取,这里没有使用redis,是考虑到redis号称单机qps最大10w/s,用户端可能会使用些作弊器产生的qps大于10w/s,所以通过web进程内缓存实现,web进程可以通过nginx做平行扩容。单个web应用可支持的qps为2w多,一台机器部署2个tomcat支持4w qps,根据预估的请求量评估需要多少台web应用服务器。
Web进程缓存的商品数量的实时更新通过redis消息订阅机制实现。
当抢购成功更新数据库后,web应用推送消息到redis队列,所以监听redis消息队列的web应用收到消息更新缓存。
第五步更新数据库时,使用乐观锁的设计,在商品数量表里加多个版本号version字段,按以下步骤走:
5.1 如果本地缓存商品数量大于0,根据商品id和版本号根据商品数量
update t_products set count=count-1,version=version+1 where id=#{id} andversion=#{old_version};
5.2 update语句影响的记录数量大于0,返回更新成功结果
5.3 upate语句影响的记录等于0,读取数据库的商品数量更新本地缓存商品数量,再按5.1流程走。
为了避免5.1到5.3会死循环的情况,要对5.1至5.3的循环次数做限制,限制为3次,超过3次未更新成功按更新失败处理。