抢购高并发问题

  • 基于MySQL解决方案
    • 悲观锁方案
      悲观锁的方案采用的是排他读,也就是同时只能有一个进程读取到num的值。
      事务在提交或回滚之后,锁会释放,其他的进程才能读取(SELECT … FOR UPDATE)

    • 乐观锁方案
      乐观锁的方案在读取数据是并没有加排他锁,而是通过一个每次更新都会自增的version字段来解决,多个进程读取到相同num,然后都能更新成功的问题。
      在每个进程读取num的同时,也读取version的值,并且在更新num的同时也更新version,并在更新时加上对version的等值判断。
      假设有10个进程都读取到了num的值为1,version值为9,则这10个进程执行的更新语句都是UPDATE goods SET num=num-1,version=version+1 WHERE version=9,然而当其中一个进程执行成功之后,数据库中version的值就会变为10,剩余的9个进程都不会执行成功,这样保证了商品不会超发,num的值不会小于0,但这也导致了一个问题,那就是发出抢购请求较早的用户可能抢不到,反而被后来的请求抢到了。

  • 基于redis解决方案
    • 基于watch的乐观锁方案
      watch用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
      这种方案跟mysql中的乐观锁方案类似,具体表现也是一样的。

    • 基于list的队列方案
      基于队列的方案利用了redis出队操作的原子性,抢购开始之前首先将商品编号放入响应的队列中,在抢购时依次从队列中弹出操作,这样可以保证每个商品只能被一个进程获取并操作,不存在超发的情况。
      该方案的优点是理解和实现起来都比较简单,缺点是当商品数量较多是,需要将大量的数据存入到队列中,并且不同的商品需要存入到不同的消息队列中

猜你喜欢

转载自www.cnblogs.com/phonecom/p/10345782.html