用Redis实现高并发抢购问题(原理及代码全)

版权声明:转发原创文章请复制文章链接地址 https://blog.csdn.net/weixin_42579642/article/details/84563055

业务场景:

我们做商品抢购功能,要面临的第一个问题就是数据不能异常,而保证数据不异常我们的解决办法有很多比如说数据库的锁机制,或者先改后查的方式都能解决,但是第二个问题来了如果我们用上述技术解决,数据是不会异常了,但是我们的服务器压力就会很大了,从而使服务器宕机,那么我们如何使服务器压力减小还能保证数据不异常呢,我们可以使用队列的思想,下面我们介绍的是使用redis队列解决高并发的问题!

redis队列解决抢购高并发的原理:

在程序跟数据库之前呢我们可以利用redis队列做一个缓冲机制,让所有用户的请求进行排队,禀行先进先出的原则(redis中的lpush和rpop),lpush程序是把用户的请求压入redis队列,然后用rpop做一个守护进程来取队列中的数据,按规定的抢购名额写好,把所有抢购成功的用户写入redis并且生成订单,在lpush程序中查看中奖的用户并且给用户及时提醒抢购结果!

html页面代码:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
<input type="button" id="luo" class="qianggou" value="抢购1">
<input type="button" id="zhang" class="qianggou" value="抢购2">
<input type="button" id="li" class="qianggou" value="抢购3">
<input type="button" id="wang" class="qianggou" value="抢购4">
<input type="button" id="xu" class="qianggou" value="抢购5">
<input type="button" id="ma" class="qianggou" value="抢购6">
</body>
</html>
<script>
    $('.qianggou').click(function(){
        var user = $(this).attr('id');
        $.get('./lpush.php',{
            user:user
        },function(data){
            alert(data)
        })
    })
</script>

lpush程序代码

<?php
$username = $_GET['user']; //页面测试用
//$username = rand(1000,9999);//做压力测试用
$redis = new redis();
$res = $redis -> connect('172.20.10.111',6379);
$redis -> lPush('bbb',$username);
//sleep(1);
$num = $redis -> sCard('user');
while(true){
    $res = $redis -> sIsMember('user',$username);
    if($res){
        echo '恭喜你中奖';
        break;
    }else{
        if($num == 5){
            if(!($redis -> sIsMember('user',$username))){  //如果队列里面没有用户且队列执行完毕则没抢中
                echo '再接再厉';
                break;
            }else{
                echo '恭喜你中奖';
                break;
            }
        }
    }
}

rpop程序代码:

<?php
$redis = new redis();
$redis -> connect('172.20.10.111',6379);
$num = 0;
while($num<5){
    $username = $redis -> rPop('bbb');
    if($username){
        $res = $redis -> sAdd('user',$username);
        if($res){                     //防止重复用户点击
            echo '创建订单'.$username;
            $num++;
        }
    }else{
        echo "本次无数据\n\r";
        sleep(2);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42579642/article/details/84563055