回想自己本科毕业三年了,三年来,一直做的是电商项目,可是前两年都太忙了,一直进行简单的CRUD,反反复复,现在把项目中用到的一些设计思想和技术记录下来,今天要说的是---电商项目中减库存模块中的并发问题
减库存并发问题一般都是在秒杀活动,爆款商品中出现,那么如何解决呢?
机器访问问题解决:一些商贩会利用一些工具来进行下单套利交易,所以为了防止工具也就是机器请求,我们可以采用图像验证码,缺点是会导致用户体验下降.
数据一致性问题:大型电商网站都是采用分库技术来提高数据库的并发能力,并且通过分布式缓存技术来减少数据库的压力,但是也会造成跨数据库或分布式缓存与数据库之间难以进行事务操作,由于下单和减库存不在一个事务中,可能会出现超卖或者少卖的现象,为了避免数据不一致的情况发生,并且保证前端页面能够在高并发情况下正常浏览,我们采取的是实际库存和浏览库存分离的方式,由于验证码的添加,真正到达后端下单模块的流量不如前端的大,所以可以将真实的库存保存在数据库中,而前端浏览的库存保存在缓存中,这样的话,下单和减库存就在同一个事务中进行,数据库库存更新完毕后,再将数据更新到缓存中
行锁和表锁:众所周知,由于oracle扩展成本高,所以互联网企业一般选择mysql数据库,mysql存储殷勤myiasm采用的表锁,如果一个用户对表操作时候,就会锁定整张表,innodb采用的行锁,只有对同一行写入操作时,锁机制才会生效,所以采用innodb存储引擎,适合高并发写入的场景,那么如果采用innodb的话,一个线程获得行锁后,其他线程就将等待,随着并发数的增加,会导致数据库拒绝服务,这时我们可以将一行库存分成多行,,下单库存操作将路由到哪一条记录,可以采用多种策略,如根据用户id取模,总的库存通过sum函数进行汇总,在同步到缓存,查询库存:select sum(库存) form 库存表 ,减库存:update 商品表 set 库存 = 库存-1 where id = 1000x and sum(库存)>0 ; 但是这样存在一个问题:当总库存大于0时,但是前段下单要求刚好被路由到库存为0的记录,导致减库存失败
redis缓存:Redis是一个key-value存储系统,是单线程的,不存在数据安全问题,数据都是缓存在内存中,在客户未下单之前,所有的商品保存到redis中,redis的吞吐量可以达到10万/m/次,所以可以很好的解决高并发问题,当下单成功之后,减少库存,然后把数据同步保存到数据库中,这样可以减少与数据库的交互
电商网站减库存模块设计到的思想就有这些,如有不足,请补充