>  기사  >  백엔드 개발  >  과매수 방지를 위한 쇼핑몰 반짝 세일

과매수 방지를 위한 쇼핑몰 반짝 세일

PHPz
PHPz원래의
2017-04-04 14:45:446671검색

PHP-MALL

1. 몰 러시 세일 , 과잉 판매된 재고를 플래시로 죽이는 것은 골치 아픈 일입니다.

1.mysql锁机制,悲观锁InnoDB行级锁方案,不建议使用,对数据库压力较大,如果出现死锁会导致一直不能更新,除非kill掉进程
2.mysql乐观锁 不使用第三方情况下可以使用此方案
3.redis incrby decrby原子性操作,防止超卖
4.为方便扩展,把库存类抽象出接口,方便以后扩展,也可以使用其它方式实现

1.1.mysql 잠금 메커니즘, 비관적 잠금, InnoDB 행 수준 잠금 방식, 쿼리 에서 를 사용해야 합니다. 🎜>색인

1.事务级别必须为 SERIALIZABLE 级别
2.查询条件验证库存是否够本次购买,例: id = 1 AND inventory >=1
3.PDO update更新后,不但要验证返回状态是否为!==false,并且同时验证影响行数是否大于0
4.数据库链接一定要使用同一链接,单例或DB链接传入,建议使用单例,由于测试网上找了个db类,没有实现单例,所以使用比较笨的方法,传递数据库链接
5.update件件增加验证购买数量条件 AND inventory >=1

1.2.mysql 낙관적 잠금

数据库表增加版本字段如version,每次修改时版本号+1
如果更新操作顺序执行,则数据的版本(version)依次递增,不会产生冲突。但是如果发生有不同的业务操作对同一版本的数据进行修改,那么,先提交的操作(图中B)会把数据version更新为2,当A在B之后提交更新时发现数据的version已经被修改了,那么A的更新操作会失败。
PDO update更新后,不但要验证返回状态是否为true,并且同时验证影响行数是否大于0

1.3.redis 원자 연산

incr/decr原子性操作,incr增加,decr减少
//此处不可以取出后放入php变量判断库存,否则会出现幻读,导致超卖
if ($redis_client->decrby($key, $parmas['num']) > -1) {
        //减库存
        $goods = new Goods();
        $parmas['version'] = 1;
        return $goods->subInventory($parmas);
} else {
    //购买多个时,如库存不足,需要把数量加回去,否则会出现库减库存,商品并没有卖出去
    $redis_client->incrby($key, $parmas['num']);
    return false;
}
使用redis测试时,每次修改完库存需要删除KEY:DEL goods_1

테스트

配置使用方式
//db 悲观锁(事务级别SERIALIZABLE) db2 mysql乐观锁 redis redis方式
define('INVENTORY_TYPE', 'db2');

并发小时可能不会有问题,如查并发较大会有超卖现像,为了可以重现超卖下面代码加入2秒迟时
services/inventory/db/Inventory.php 31行左右
$data = $goods->getInventory($params);
sleep(2); //停2秒,方便测试出问题
nginx配置站点mall.com
本机hosts绑定域名 10.211.55.100 mall.com(10.211.55.100为实际站点的ip)

测试方法使用ab测试,请求100,并发10
ab -n100 -c10 http://mall.com

3.

아아아아


위 내용은 과매수 방지를 위한 쇼핑몰 반짝 세일의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.