我是靠谱客的博主 美好保温杯,最近开发中收集的这篇文章主要介绍redis实战-高并发抢购案例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

先普及一下,什么叫超卖,订单商品数据量大于商品库存数量,就叫做超卖;

那么问题来了,为什么会超卖呢?

在商城抢购中,假如库存为100个,这时有100 000个并发请求过来了,最后库存只剩1个时,假如还有1000个并发请求,如果这1000个请求都成功了,那最后库存是不是变成了-999,这就是超卖。(以上仅为理论上理解超卖)

先介绍一个很有用的工具,并发测试工具ab.exe,在Apache的bin目录下打开cmd窗口,输入命令ab -n10000 -c1000 http://localhost/code/mysql.php,表示测试10000个请求,并发量为1000,测试访问地址为http://localhost/code/mysql.php

 

先建一个商品表,store为库存,以下为一些用到SQL语句

// 建表
create table product(
	id int(8) not null auto_increment comment '产品id',
	name varchar(25) not null default '' comment '产品名',
	price decimal(10,3) not null default 0 comment '价格',
	store int(8) not null default 0 comment '库存',
	primary key(id)
)engine=innodb default charset=utf8;

// 添加数据
insert into product value(1, '小米手环', 198, 10);

// 查看表数据
select * from product;

// 设置库存
update product set store=10 where id=1;

 

接下来,用代码解释下高并发抢购的超卖,直接在MySQL上测试,以下就是mysql.php文件

<?php
    header("content-type:text/html; charset=utf-8");
    
    // 连接数据库
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root') or die("数据库连接失败");
    $pdo->exec("set names utf8");

    $sql = "select * from product where id=1";
    $res = $pdo->query($sql);
    $data = $res->fetch(PDO::FETCH_ASSOC);
    // print_r($data);

    if($data['store']>0){

        // 开启事务
        $pdo->beginTransaction();
        $sql = "update product set store=store-1 where id=1";
        $res = $pdo->query($sql);
        print_r($res);
        if($res){
            echo "抢到啦!";
        }else{
            echo "抢购失败...";
            $pdo->rollBack();
        }
        $pdo->commit();

    }else{
        echo '商品已被抢购一空,感谢参与!';
    }
?>

给它10000个请求,并发为1000

来看下商品表中的库存store

 

再来看下用redis实现的,用到了redis的事务、乐观锁,以下为redis.php

<?PHP
    header("content-type:text/html; charset=utf-8");
    
    // 连接数据库
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root') or die("数据库连接失败");
    $pdo->exec("set names utf8");

    $redis = new Redis();
    $redis->connect("localhost");

    $redis->watch('salec'); // 虚拟销量
    $salec = $redis->get('salec');

    $store = 10; // 设置虚拟库存与数据库的一致

    if($salec >= $store){
        exit("商品已被抢购一空,感谢参与!");
    }

    // 开启事务
    $redis->multi();
    $redis->incr('salec'); // 增加销量 
    $res = $redis->exec(); // 执行事务 如果发现自己拿到的key被修改了,事务则被打断

    if($res){
        // 以下代码只是为了测试,实际中是交给 MQ 去处理

        // 连接数据库
        $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root') or die("数据库连接失败");
        $pdo->exec("set names utf8");
        $sql = "update product set store=store-1 where id=1";
        if($pdo->query($sql)){
            echo "抢到啦!";
        }

    }else{
        echo "抢购失败...";
    }
?>

也给它10000个请求,并发为1000

看下商品表中的库存store

redis完美解决了高并发抢购的超卖现象。

 

最后

以上就是美好保温杯为你收集整理的redis实战-高并发抢购案例的全部内容,希望文章能够帮你解决redis实战-高并发抢购案例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部