zoukankan      html  css  js  c++  java
  • 使用Mysql和Redis设计抢购逻辑

    抢购场景中,要保证两点:

    1.库存不会超减/少卖

    2.在1基础上的执行速度

    我测试了两种方案,

    方案一.Mysql开启事务,获取库存时使用独占锁阻塞其他读请求.

    我把库存表简单设计如下

    CREATE TABLE `la_store` (
      `id` int(11) NOT NULL,
      `val` int(255) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    假设库存有100000件(val=100000)

    php逻辑代码

    <?php
    $stime=microtime(true);
    $count=100000;//测试次数
    while($count>0){
    $count-=1;
    $con = mysql_connect("localhost","user","pwd");
    if (!$con)
      {
      die('Could not connect: ' . mysql_error());
      }
    mysql_select_db("database_name", $con);
    mysql_query('begin');
    $record=mysql_query("select * from la_store where id = 1 for update");//获取独占锁
    $record=mysql_fetch_array($record);
    if($record['val']>0){//判断是否还有库存
    //有库存的逻辑
    $res=mysql_query("UPDATE la_test SET val = val-1 WHERE id=1 ");//更新库存
    }else{
    //没库存的逻辑
    }
    mysql_query("commit"); mysql_close($con); } $etime=microtime(true);//获取程序执行结束的时间 $total=$etime-$stime; echo $total;

    方案二.使用Redis开启事务

    假设库存有100000件(set store 100000)

    <?php
    $stime=microtime(true);//开始时间
    $count=100000;//测试次数
    while($count>0){
    $count-=1;
    $redis = new Redis();
       $redis->connect('127.0.0.1', 6379);
    $res=$redis->multi()->decr('store')->get('store')->exec();
    if($res[1]>0){
            //有库存逻辑
    }else{
            //没有库存逻辑
    }
    }
    $etime=microtime(true);//获取程序执行结束的时间
    print_r($res);
    $total=$etime-$stime;
    echo $total;

    测试结果:

    分别执行,经过100000次循环后,Redis用时22秒,Mysql用时50秒;

    使用Redis更快,但Redis的事务不能回滚,如果业务逻辑出错时允许不回滚,并且回滚的概率很小,建议使用Redis.如果逻辑出错时必须回滚,还是用Mysql更稳妥.

  • 相关阅读:
    单点登录
    公共的service接口
    springMvc入门--初识springMvc
    mybatis进阶--mapper输入映射和输出映射
    mybatis入门--mapper代理方式开发
    AJAX学习笔记——跨域
    AJAX学习笔记——jQuery中的AJAX
    AJAX学习笔记——JSON
    XAMPP启动Apache服务时启动失败
    Ajax的简单例子——PHP
  • 原文地址:https://www.cnblogs.com/ch459742906/p/8400412.html
Copyright © 2011-2022 走看看