利用redis实现简单的乐观锁与悲观锁

作者:Shine 发布于:2017-11-02 20:49:40 浏览:1154次 分类:PHP

利用redis实现简单的乐观锁与悲观锁

<?php
namespace backend\models;

class RedisModel
{

	public function _initialize(){
		$this->redisHandle = $this->redisHandle();
	}

	public function redisHandle(){
		$redis = new \Redis();
		$redis->connect('127.0.0.1',6379);
		$redis->auth("123456");
		return $redis;
	}

	/**
	 * @desc 获取锁
	 * @param $key
	 * @param int $expire
	 * @return bool
	 */
	public function lock($key, $expire = 5){
		$redisHandle = $this->redisHandle();
		$hasLock     = $redisHandle->setnx($key, time() + $expire);
		if (!$hasLock) {
			$lockTime = $redisHandle->get($key);
			if (time() > $lockTime) {
				$this->unlock($key);
				$hasLock = $redisHandle->setnx($key, time() + $expire);
			}
		}
		return $hasLock ? true : false;
	}

	/**
	 * @desc 释放锁
	 * @param string $key
	 * @return int
	 */
	public function unlock($key = ''){
		$redisHandle = $this->redisHandle();
		return $redisHandle->del($key);
	}
}

简单字符串悲观锁实战

解释:悲观锁(Pessimistic Lock), 顾名思义,就是很悲观。

每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。

场景:如果项目中使用了缓存且对缓存设置了超时时间。

当并发量比较大的时候,如果没有锁机制,那么缓存过期的瞬间,

大量并发请求会穿透缓存直接查询数据库,造成雪崩效应。

/**
 * @desc 悲观锁demo
 */
public function pessimisticLock(){
	$key     = 'pessimistic_lock_test';
	$hasLock = $this->lock($key, 10);

	if ($hasLock) {
		echo 'get lock success<br>';
		echo 'write your code<br>';
		echo 'balabala~';
		echo 'done~';
		$this->unlock($key);
	} else {
		echo 'request too frequently';
	}
}

简单事务的乐观锁实战

解释:乐观锁(Optimistic Lock), 顾名思义,就是很乐观。

每次去拿数据的时候都认为别人不会修改,所以不会上锁。

watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败。

也可以调用watch多次监视多个key。这样就可以对指定的key加乐观锁了。

注意watch的key是对整个连接有效的,事务也一样。

如果连接断开,监视和事务都会被自动清除。

当然了exec,discard,unwatch命令都会清除连接中的所有监视。

/**
* @desc 乐观锁demo
*/
public function optimisticLock(){
	$redisHandle = $this->redisHandle();

	$key = 'optimistic_lock_test';

	$redisHandle->set($key, 10);

	$age = $redisHandle->get($key);

	echo "current age:{$age}<br/>";

	$redisHandle->watch($key);

	##开启事务
	$redisHandle->multi();

	##在这个时候新开了一个新会话执行
	$redisHandle->set($key, 30);

	$age = $redisHandle->get($key);

	echo "current age:{$age}<br/>";

	$redisHandle->set($key, 20);

	$redisHandle->exec();

	$age = $redisHandle->get($key);

	echo "current age:{$age}<br/>";

	##当exec时候如果监视的key从调用watch后发生过变化,则整个事务会失败
}

以下是两篇转自CSDN的文章

http://blog.csdn.net/mindfloating/article/details/8121479

http://blog.csdn.net/qq_16414307/article/details/50481484


标签: redis 锁机制
声明:文章内容由作者原创或整理,转载请标明出处!
暂留位置!--请勿随意修改