PHP yii2 扩展底层实现排它锁,与接口缓存锁

前言

yii2扩展底层实现链式查询中可以使用排它锁,yii2实现用于防止接口并发的缓存锁。


排它锁

提示:排它锁有两种实现方式

1.实现方式:原生查询


	$sql = 'select * from 表名 where store_id = 1 and id = 1 for update';
	return \Yii::$app->db->createCommand($sql)->queryOne();

2.实现方式:扩展底层代码实现模型查询中使用排它锁

	//最终实现效果,可在结尾使用->forUpdate()
	$form = User::find()->where('store_id 1 and id = 1')->forUpdate()->one();
	//实现步骤
	1.在\vendor\yiisoft\yii2\db\Query.php中增加以下代码
		/** @var bool true-追加悲观锁*/
	    public $isForUpdate = false;
	    
		/**
	     * 追加悲观锁
	     * @see forUpdate()
	     * @return $this the query object itself
	     */
	    public function forUpdate(){
	    	$this->isForUpdate = true;
	    	return $this;
	    }

	
	2.在\vendor\yiisoft\yii2\db\Query.php中修改create()方法,修改为
		public static function create($from)
	    {
	        return new self([
	            'where' => $from->where,
	            'limit' => $from->limit,
	            'offset' => $from->offset,
	            'orderBy' => $from->orderBy,
	            'indexBy' => $from->indexBy,
	            'select' => $from->select,
	            'selectOption' => $from->selectOption,
	            'distinct' => $from->distinct,
	            'from' => $from->from,
	            'groupBy' => $from->groupBy,
	            'join' => $from->join,
	            'having' => $from->having,
	            'union' => $from->union,
	            'params' => $from->params,
	        	'isForUpdate'=>$from->isForUpdate //增加forupdate进去
	        ]);
	    }
	

	3.在\vendor\yiisoft\yii2\db\QueryBuilder.php中增加forUpdate()方法
		/**
	     * 格式化所有查询语句后才追加它
	     * @return string 查询语句末尾追加排它锁语句
	     */
	    public function forUpdate($isForUpdate)
	    {
	        if ($isForUpdate) {
	            return ' for update';
	        }
	        return '';
	    }
    
    4.在\vendor\yiisoft\yii2\db\QueryBuilder.php中修改build()方法,在其最后的return [$sql, $params];上面增加sql链接
    	$sql .= $this->forUpdate($query->isForUpdate);//确保是在最后面
    	return [$sql, $params];//这段不要复制上去了
    
	5.在\vendor\yiisoft\yii2\db\QueryInterface.php中增加forUpdate()方法
		public function forUpdate();
	
    6.在\vendor\yiisoft\yii2\db\QueryTrait.php中增加forUpdate()方法
		public function forUpdate()
	    {
	        return $this;
	    }
    
    7.接下来本可使用AR->forUpdate()方法了

缓存锁

提示:缓存锁适用于请求接口时的并发限制,距离:用户短时间内多次访问接口,访问只会成功一次,剩余将被拦截
	//最终实现效果
	public function actionIndex()
	{
		//第一次输出:访问成功
		//第二次输出:已拦截请求
		//第N次输出:....
		if (Cachelocks('index-' . getCurrentUserId(), 1, 2)) { // 设置2秒缓存锁
            return '已拦截请求';
        }
       	return '访问成功';
	}
		

	//实现代码
	/**
     * 缓存锁
     * 存在缓存则返回缓存,不存在则设缓存并返回null
     * @param string $Cachekey 缓存名称
     * @param string $Cachevalue 缓存内容
     * @param int $Cachetime 缓存时间 默认3s
     * @return mixed
     */
    function Cachelock($Cachekey, $Cachevalue, $Cachetime = 3)
    {
    	//存在缓存则返回缓存
        if (($value = \Yii::$app->cache->get($Cachekey)) !== false) {
            return $value;
        }
        if ($Cachevalue) {
        	//不存在缓存,则设置缓存,并返回null
            if (!\Yii::$app->cache->set($Cachekey, $Cachevalue, $Cachetime)) {
                Yii::warning('Failed to set cache value for key ' . json_encode($Cachekey), __METHOD__);
            }
        }
        return null;
    }


纯手打,喜欢请点个赞吧

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值