php flock 都是true_PHP秒杀系统设计

场景描述

假设现在要搞一个特价促销活动,商品为iPhone11手机,库存为2台,购买时间为晚上8点。预计有100名用户参与这次促销活动。现在用PHP做了一个链接,时间一到,谁先点击,谁就可以下单购买。

表设计

  • 商品库存表

CREATE TABLE `goods` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `subject` varchar(100) DEFAULT NULL,  `stock` int(3) DEFAULT '0',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8INSERT INTO `goods`(`id`, `subject`, `stock`) VALUES (1, 'iPhone11', 2);
  • 订单表

CREATE TABLE `good_orders` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `user_id` varchar(36) DEFAULT NULL,  `good_id` int(11) DEFAULT NULL,  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

PHP代码

PHP伪代码如下:

$sql = "SELECT * from goods where id = 1";$userid = uniqid();$row = $db->query($sql);if ($row['stock'] > 0) {    //插入订单表    $db->exec("insert into good_orders set user_id ='{$userid}',good_id='1'");    //减库存    $stock = $row['stock'] - 1;    $db->exec("update goods set stock ='{$stock}' where good_id='1'");    echo '购买成功';} else {    echo '库存不足';}

不在并发条件下,单个点击是没有问题的,good_orders表里只会出现2条订单记录,但一旦处于并发条件下,就会存在多条订单,这样就造成了超卖。

文件锁

$fp = fopen("lock.txt", "w+");if (flock($fp, LOCK_EX)) { // 进行排它型锁定    $sql = "SELECT * from goods where id = 1";    $userid = uniqid();    $row = $db->query($sql);    if ($row['stock'] > 0) {        //插入订单表        $db->exec("insert into good_orders set user_id ='{$userid}',good_id='1'");        //减库存        $stock = $row['stock'] - 1;        $db->exec("update goods set stock ='{$stock}' where good_id='1'");        echo '购买成功';    } else {        echo '库存不足';    }    flock($fp, LOCK_UN); // 释放锁定} else {    echo '前方拥挤';}fclose($fp);

redis

将库存放入redis

$redis = new \Redis;$redis->connect('127.0.0.1', 6379);$sql = "SELECT * from goods where id = 1";$userid = uniqid();$row = $db->query($sql);if ($row['stock'] > 0) {    for ($i = 0; $i < $row['stock']; $i++) {        $redis->lpush('goods_number', $i);    }}echo $redis->llen('goods_number');

从redis中扣库存

$stock = $this->redis->llen('goods_number');$count = $this->redis->rpop('goods_number');  //下单时做rpop 从goods_number中取出1if ($count===false) {    echo '库存不足';exit();}$userid = uniqid();//插入订单表$db->exec("insert into good_orders set user_id ='{$userid}',good_id='1'");//减库存$stock = $row['stock'] - 1;$db->exec("update goods set stock ='{$stock}' where good_id='1'");echo '购买成功';

PHP flock() 函数

定义和用法

flock() 函数锁定或释放文件。

若成功,则返回 true。若失败,则返回 false。

语法

flock(file,lock,block)
参数描述
file必需。规定要锁定或释放的已打开的文件。
lock必需。规定要使用哪种锁定类型。
block可选。若设置为 1 或 true,则当进行锁定时阻挡其他进程。

说明

flock() 操作的 file 必须是一个已经打开的文件指针。

lock 参数可以是以下值之一:

  • 要取得共享锁定(读取的程序),将 lock 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)。

  • 要取得独占锁定(写入的程序),将 lock 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)。

  • 要释放锁定(无论共享或独占),将 lock 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)。

  • 如果不希望 flock() 在锁定时堵塞,则给 lock 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)。

提示和注释

提示:可以通过 fclose() 来释放锁定操作,代码执行完毕时也会自动调用。

注释:由于 flock() 需要一个文件指针, 因此可能不得不用一个特殊的锁定文件来保护打算通过写模式打开的文件的访问(在 fopen() 函数中加入 "w" 或 "w+")。

0537b78b4a1c51bff7f688a7cf188170.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值