利用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