Login
网站首页 > 文章中心 > 其它

使用Redis实现抢购的一种思路_list队列实现)

作者:小编 更新时间:2023-09-04 10:26:29 浏览量:199人看过

抢购是如今很常见的一个应用场景,主要需要解决的问题有两个:

①. 高并发对数据库产生的压力

对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用Redis.重点在于第二个问题,我们看看下面一种常规的实现代码:

require('predis/src/Autoloader.php');

$redis = new Predis\Client(array(
'scheme' => 'tcp',
'host'   => '12⑦0.0.1',
'port'   => '6379'
));

//redis 登录 
$redis->auth('123456');

//库存
$num = 10;

//用户id
$user_id = $_SESSION['user_id'];

//检查库存 
$len = $redis->llen('order:1');
if($len >= $num){
exit('已经抢光了');
}

//把抢到的用户存入到列表中  
$result = $redis->lpush('order:1',$user_id);
if($result){
echo '抢到了';
}

?>

使用Redis实现抢购的一种思路_list队列实现)-图1

如果代码正常运行,列表order:1中最多只能存储10个用户的id,因为库存只有10个.

然而,在使用Apache AB工具模拟很多用户并发请求时,最后发现order:1中总是超过10个用户,也就是出现了"超卖".

问题就出在这一段代码:

//检查库存 
$len = $redis->llen('order:1');
if($len >= $num){
exit('已经抢光了');
}

在高并发下,很多不是问题的,都成了问题.要解决"超卖"问题,核心在于保证检查库存时的操作是依次执行的,形象的说就是把"多线程"转成"单线程".即使有很多用户同时到达,也是一个个检查并给与抢购资格,一旦库存抢尽,后面的用户就无法继续了.

我们需要使用Redis的原子操作来实现这个"单线程".首先我们把库存存在goods:1这个列表中,假设有10件库存,就往列表中push10个数,这个数没有实际意义,仅仅代表一件库存.抢购开始后,每到来一个用户,就从goods:1中pop一个数,表示用户抢购成功.当列表为空时,表示已经被抢光了.因为列表的pop操作是原子的,即使有很多用户同时到达,也是依次执行的.抢购的示例代码如下:

//抢购 
require('predis/src/Autoloader.php');

$redis = new Predis\Client(array(
'scheme' => 'tcp',
'host'   => '12⑦0.0.1',
'port'   => '6379'
));

$redis->auth('123456');

//用户ID
$user_id = $_SESSION['user_id'];

$check = $redis->lpop('goods:1');
if(!$check){
exit('抢光了');
}

$result = $redis->lpush('order:1',$user_id);
if($result){
echo '抢购成功';
}

?>

用户抢购成功后,我们将用户ID存入了order:1列表中.此时此刻呢我们可以引导这些用户去完成订单的其他步骤,这里才涉及到与数据库的交互.最终只有很少的人走到这一步,也就解决的数据库的压力问题.

以上就是土嘎嘎小编为大家整理的使用Redis实现抢购的一种思路_list队列实现)相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章