侧边栏壁纸
博主昵称
梦之中小俊

以前高中时,羡慕大学考试只要及格就行;现在大学了,怀念高中考试及不及格都行??

PHP

教你如果处理高并发数据不同步的问题

梦之中小俊
2023-03-01 / 0 评论 / 367 阅读 / 推送成功!

现在做商城这么多,但大部分都是用的开源商城,但公司可能会一些抢购的活动,当然,不出问题你什么问题都发现不了,毕业流量还没有达到那么大,但一旦流量达到足够大的时候,并发就很有可能发生,这个时候你的商品抢购数量就有可能出问题,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秒。
3

打赏

评论 (0)

OωO
  • ::(呵呵)
  • ::(哈哈)
  • ::(吐舌)
  • ::(太开心)
  • ::(笑眼)
  • ::(花心)
  • ::(小乖)
  • ::(乖)
  • ::(捂嘴笑)
  • ::(滑稽)
  • ::(你懂的)
  • ::(不高兴)
  • ::(怒)
  • ::(汗)
  • ::(黑线)
  • ::(泪)
  • ::(真棒)
  • ::(喷)
  • ::(惊哭)
  • ::(阴险)
  • ::(鄙视)
  • ::(酷)
  • ::(啊)
  • ::(狂汗)
  • ::(what)
  • ::(疑问)
  • ::(酸爽)
  • ::(呀咩爹)
  • ::(委屈)
  • ::(惊讶)
  • ::(睡觉)
  • ::(笑尿)
  • ::(挖鼻)
  • ::(吐)
  • ::(犀利)
  • ::(小红脸)
  • ::(懒得理)
  • ::(勉强)
  • ::(爱心)
  • ::(心碎)
  • ::(玫瑰)
  • ::(礼物)
  • ::(彩虹)
  • ::(太阳)
  • ::(星星月亮)
  • ::(钱币)
  • ::(茶杯)
  • ::(蛋糕)
  • ::(大拇指)
  • ::(胜利)
  • ::(haha)
  • ::(OK)
  • ::(沙发)
  • ::(手纸)
  • ::(香蕉)
  • ::(便便)
  • ::(药丸)
  • ::(红领巾)
  • ::(蜡烛)
  • ::(音乐)
  • ::(灯泡)
  • ::(开心)
  • ::(钱)
  • ::(咦)
  • ::(呼)
  • ::(冷)
  • ::(生气)
  • ::(弱)
  • ::(狗头)
泡泡
阿鲁
颜文字
取消
  1. 头像
    6767 Lv.1
    iPhone · Safari
    沙发

    画图

    回复
  2. 头像
    6767 Lv.1
    Windows 10 · Google Chrome
    板凳

    表情

    回复
  3. 头像
    透露 Lv.2
    Android · QQ Browser
    第30楼

    649494848

    回复