• 人民网驻阿尔及利亚记者报道集 2018-02-19
  • 党务问答:党组与党委有何区别? 2018-02-19
  • MINI车联网服务3月起升级至4G网络 增加新功能 2018-02-18
  • 以色列警方:已有足够的证据可以用于起诉以总理 2018-02-18
  • 冬奥会短节目第四 金博洋:伤病令我更强大 2018-02-18
  • 天津市北辰区委书记冯卫华:强化政治担当 把主体责任落实落细 2018-02-17
  • 正月初一客流继续回落 全国铁路预计发送旅客389万人次 2018-02-17
  • 送别余光中:诗人虽远行,乡愁永流传 2018-02-17
  • 集团原董事长违纪被查 人员伤亡事故频发 湖北宜化:去年亏损额超过公司市值 2018-02-17
  • 图片故事:“六个人”的火车站 2018-02-16
  • 【马来西亚房产】雅诗阁之星十年包租可续租! ——凤凰网房产马来西亚 2018-02-16
  • 大量顺差在中国,多数利润归美国 2018-02-16
  • 河北今年将削减煤炭消费500万吨 2018-02-16
  • 开创生态文明新时代 绘出美丽中国新图景 2018-02-15
  • 以色列警方:已有足够的证据可以用于起诉以总理 2018-02-15
  • Kevensuu's Blog

    PHP 防并发 insert 多条记录

    方式1:通过 redis get|set 来实现

    if($this->user_baby_model->get_lock($params['uid'], $params['bbtype']))
    {
        $this->my_send_log->add(100012, array('add_baby_concurrent', date('Ymd-H:i:s'), $params), 1);
        return $this->error('Err.Unknown_error', 'the same request has exist');
    }
    else
    {
        $this->user_baby_model->set_lock($params['uid'], $params['bbtype']);
    }
    
    public function set_lock($uid, $bbtype)
    {
        $key = $this->set_lock_key($uid, $bbtype);
        return $this->my_redis->save_string('redis_bcache', $key, 1, 10);
    }
    
    public function get_lock($uid, $bbtype)
    {
        $key = $this->set_lock_key($uid, $bbtype);
        return $this->my_redis->get_string('redis_bcache', $key);
    }
    
    public function set_lock_key($uid, $bbtype)
    {
        return md5($uid.$bbtype);
    }
    

    上面代码意思是:

    1、先判断是否已经加锁
    2、未加锁,则先进行加锁操作,然后继续后面流程
    3、已加锁,直接返回错误
    

    这种方式看是没什么问题,但是忽略了一点:如果 判断是否加锁 这个操作未完成之前,另外一个请求又进来了,这种情况下就取不到 的作用了。

    方式2:通过 redis setnx 来实现

    $ret = $redis->setnx($key, $value);
    if(!$ret)
    {
        return false;
    }
    
    // success do something
    
    $redis->del($key);  // 删除锁
    

    上面代码意思是:通过 setnx 去缓存中设置值,如果设置失败,则终止程序执行;设置锁成功的请求,在请求结束前要删除锁。

    但是这种方法依然存在问题,就是如果删除锁失败,后面所有请求都会失败。