现在做商城这么多,但大部分都是用的开源商城,但公司可能会一些抢购的活动,当然,不出问题你什么问题都发现不了,毕业流量还没有达到那么大,但一旦流量达到足够大的时候,并发就很有可能发生,这个时候你的商品抢购数量就有可能出问题,100件的商品,最后成功订单可能出现105个 ,下面我们来模拟一下这种情况。
公共连接数据库部分
第一种:正常代码的情况
先自己创建一个t_goods数据库,其中库存字段为stock,看代码
代码的功能很简单,就是每运行一次就去把库存减一,你如果在浏览器里面刷新,肯定没问题,因为这不是并发,你可以模拟一下并发的情况,我这里默认库存为100,模仿10个用户同时发10个请求的情况,看库存会减多少?
看结果,库存才减6,这就是并发出现库存不同步的问题
问题是怎么出现的呢?
A去查询库存(假如是100),正要减一(没来得及减),B也去查询库存(肯定为100),A去减一了,B也去减一(减的是自己查询到的100), 最后两个操作后,库存还为99,正常应该为98才行,这就是并发出现的问题,那怎么解决呢,下面我介绍四种加锁的解决方案,数据库锁、文件锁、Memcache锁、Redis锁
第一种加锁:数据库锁
这种锁不建议使用,因为它会锁库,其它人可能就动不了库了,流量比较大的情况,网站可能就会崩
第二种加锁:文件锁
注意:文件锁也分为排它锁(LOCK_EX)和共享(LOCK_SH)锁两种,这里只能用排它锁
第三种锁:Memcache锁
要用到Memcache锁,首先你的服务器要安装Memcache的支持
class MemcacheLock { public function __construct($options=null) { $this->memcache = new Memcache(); $this->memcache->connect("127.0.0.1", 11211); } public function getLock($key, $timeout=5) { $waitime = 20000; $totalWaitime = 0; $time = $timeout*1000000; while ($totalWaitime < $time && false == $this->memcache->add($key, 1, false ,$timeout)) { usleep($waitime); $totalWaitime += $waitime; } if ($totalWaitime >= $time) throw new Exception('can not get lock for waiting '.$timeout.'s.'); } public function releaseLock($key) { $this->memcache->delete($key); } }
第四种锁:Redis锁
class RedisLock { private $_redis=null; public function __construct($config=null){ $this->_redis = $this->_redis == null ? new redis() : $this->_redis; $this->_redis->connect($config); } public function getlock($key, $expire = 60) { if(!$key) { return false; } do { if($acquired = ($this->_redis->setnx("Lock:{$key}", time()))) { // 如果redis不存在,则成功 $this->_redis->expire($key, $expire); break; } usleep($expire); } while (true); return true; } //释放锁 public function releaseLock($key) { $this->_redis->del("Lock:{$key}"); $this->_redis->close(); } }
ok,这些只是给你的一些方案,可能还有一些其它的方案来处理并发数据同步的问题,在实际项目中自己合理去抉择,选择自己合适的方案。有问题留言....
本文共 个字数,平均阅读时长 ≈ 分钟,您已阅读:0时0分0秒。
649494848