redis 秒杀成功 mysql_Redis实现简单秒杀

随着电商业务的发展,秒杀是个十分常见的场景,今天我们来利用redis实现一个简单的秒杀系统。

电商类系统中,秒杀是身份常见的。我们来探究一下秒杀问题。

简单提炼出,假定我们有一个商品id为1,秒杀数量是5。

一般场景我们可以使用mysql:

// 引入数据库操作类medoo

include 'db.php';

$db = new db([

'database_type' => 'mysql',

'database_name' => 'test',

'server' => '13sai',

'username' => '13sai',

'password' => '*',

'charset' => 'utf8'

]);

$stock_num= $db->get('goods', 'stock_num', ['id' => 1]);

// 检测库存是否充足

if ($stock_num> 0) {

sleep(1); //模拟真实环境

$db->update('goods', ["stock_num[-]" => 1], ['id' => 1]);

print_r('ok')

} else {

print_r('sorry')

}

我们尝试模拟高并发场景,使用ab压测工具,

多次运行后发现库存stock_num很可能已经变成负数了,出现了超卖问题。

引入redis实现秒杀:

//实例化redis

$redis = new Redis();

//连接

$redis->connect('127.0.0.1', 6379);

$key = 'sale';

$redis->setnx($key, 0); // 此项不预定义亦可,保证key唯一就行

$redis->watch($key); //监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

$sale_num = $redis->get($key);

if ($sale_num > 4) {

exit();

}

$redis->multi(); //标记事务

$redis->incr($key); //销量+1

sleep(1); //模拟真实环境

$ret = $redis->exec(); // 事务块内所有命令的返回值,按命令执行的先后顺序排列。

if ($ret) {

include 'db.php';

$db = new db([

'database_type' => 'mysql',

'database_name' => 'test',

'server' => '13sai',

'username' => '13sai',

'password' => '*',

'charset' => 'utf8'

]);

$db->update('goods', ["stock_num[-]" => 1], ['id' => 1]);

}

库存定为5,ab多次测试,发现库存并无出现负数情况,测试通过。

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值