mysql 高并发扣除库存,高并发库存控制

高并发库存控制

如今,在电商行业,秒杀活动已经是家常便饭,面对这种高并发压力之下,又有什么办法来缓解这种压力呢?

秒杀就像过年回家的时候买火车票,需要遵守以下几个原则:

1.公平性,机会均等,遵守FIFO原则。

2.快速处理能力,增加售票窗口,增加售票渠道。

3.稳定性,适当的入口数量,保证售票厅内人满为患。

那么,在现实开发当中,怎么去实现呢?以下图为例:

![](/uploads/article/2017/06/28/20170628214054_5172.gif)

1.有n个购票者守候在售票大厅外面,交通方便的肯定会挤在靠近入口的位置,通过入口的机会就越大.

好比秒杀时疯狂的购物者都在等待秒杀开始,大家都在刷新网页,带宽给力的肯定进去的胜算比较大.

2.我们设置了30个入口,因为我们没有更大的地方,因为现在地皮也比较贵,

那么,对应到秒杀,这个入口就是我们服务器同时处理并发处理能力大小,如果我们通过控制这30个入口的吞吐量,

那我们就可以有效的控制住服务器接受外来的压力,把强大的力量堵在第一个关口,保证服务器接受到的压力能够快速处理.

3.这30个入口我们看做一个管道(tube),假定每一个购票者给大概5分钟可以完成购票,那么超过5分钟后或者已经买到票,就会让出位置让后面的人进入售票大厅,当然这是理想化想法,但至少我们把压力控制在我们可以处理的能力之内,要不然服务器宕机,欲哭无泪。

这是第一步,缓解了压力,让压力陆续进来,到这一步我们也可以松口气了,说了这么多该怎么实现呢?

创建管道:

/**

* 创建管道 默认30个入口

* @param string $tubeName

* @param int $max

* @return bool

*/

static public function createTube($tubeName, $max = 30) {

if (!$beanstalk = Common::getBeanstalkHandle()) return false;

$beanstalk->use_tube($tubeName);

$i = 0;

while ($i < $max) {

$beanstalk->put(1);

$i++;

}

return true;

}

实现管道锁

/**

* 采用管道方式进行加锁,以限制同时进行某个流程的并发数

* @param string $name 管道名称

* @param int $delay 出管理延迟时间默认为5秒

* @return bool

*/

public function tubeLock($name, $delay = 5) {

$beanstalk = Common::getBeanstalkHandle();

$beanstalk->watch($name);

$return = false;

$job = $beanstalk->reserve_with_timeout();

if ($job['id'] > 0) $return = $beanstalk->release($job['id'], 1024, $delay);

$beanstalk->ignore($name);

return $return;

}

提前创建好管道,在并发流程中:

$tubeName = 'tube_' . $goods['id'];

if (Common::getLockHandle()->tubeLock($tubeName) == false) return false; //如果管理已经加锁,直接返回

到此为止,如我们所愿,我们已经控制了并发,我们已经把我们能力范围内可以控制的人放进来了,其它人只能继续等待...

剩下就是库存问题了,库存控制原则:

1.库存数不能<0,否则问题大了,商品超卖了,用户下了单,但没货发给卖家,那你就等着投诉吧。

请看下面一个sql(数据库是InnoDB):

/**

*

* 更新库存

* @param int $num

* @param int $id

*/

public function updateQuantity($num, $goodsid) {

$sqlPart = $num < 0 ? ' AND quantity >= ' . abs($num) : '';

$sql = 'UPDATE %s SET quantity = quantity + ?, sale_num = sale_num - ? WHERE id = ?' . $sqlPart;

return $this->_update($sql, array(intval($num), intval($num), intval($goodsid));

}

重点看sqlPart部分,这里巧妙和利用mysql的行级锁,把库存不可能为0的控制权交给了mysql来处理,此乃点晴之笔。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值