框架: springmvc + mybatis
业务: 在多用户并发购买商品的时候,发现用户总的购买量>某商品的剩余库存。
比如某商品库存为100个,但在多用户购买的情况下,sum(用户购买的的总量) > 100了。
目前实现方式: <tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" isolation="READ_COMMITTED"/>
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true">
<aop:pointcut id="txPointcut"
expression="execution(* com.my.abc..*.*(..))" />
<aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice" />
</aop:config>
Controller调用service层buy()方法, Controller加了 @Scope("prototype")。
业务逻辑都写在service层,service层首先判断了用户购买的数量是否大于剩余库存。如果小于等于,才可以购买。 要怎么样解决这个问题,请高手指点????

解决方案 »

  1.   

    数据库乐观锁在你sql修改库存的时候,加上一个限制条件:购买数<库存数  然后才能扣减成功
      

  2.   

    首先前端要做限量,比如一个IP 不能多次请求,一个账号不能多次请求
    接着将请求放入队列中,按顺序请求,同时队列设置超时时间,一段
    时间没处理,请自动移出队列,底层可以使用使用乐观锁
    或者在上层使用原子,除此之外redis也有相关的接口可以操作。
      

  3.   

    商品超卖罢了
    单台服务器直接加锁
    比如两个用户同时购买,两个线程几乎同时查询库存,结果当然是够的,所以这个校验被绕过去没起作用
    可以考虑库存表做乐观锁,如果没有更新库存成功那就重新获取库存校验数量(非分布式场景)
    如果库存和订单不在一个数据库,那就得设计好流程了,比如先减库存,再创建订单,或者采用tcc,最终一致性等分布式事务的解决方案
      

  4.   

    1.最省力的办法,购买逻辑加上同步
    2.更新的时候校验库存,一般并发量应该也没有什么问题update product set position = position - #{sum} where id = #{id} and position >= #{sum}3.乐观锁,加失败尝试update product set position = position - #{sum},version = version + 1 where id = #{id} and version = #{version}4.用队列Redis加锁超时等等等等
      

  5.   

    可以使用redis数据库做库存管理,因为redis是单线程的