public function getRedis()
{
$redis = new \Redis();
$redis->connect(env("REDIS_MASTER",'127.0.0.1'),6379);
$redis->auth(env('REDIS_AUTH','123456'));
return $redis;
}
$redis = $this->getRedis();
複製代碼
$key = 'str:name';
// 字符串緩存實戰
$redis->set($key, 'WXiangQian');
$name = $redis->get($key);
echo $name; // WXiangQian
$redis->expire($strCacheKey, 30); # 設置30秒後過時
複製代碼
$key = 'hset:name'
$uid = 1;
$redis->hSet($key, $uid, 'WXiangQian');
$data = $redis->hGet($key, 1);
print_r($data); //輸出數據
複製代碼
$strKey = 'zset:ranking_list';
//存儲數據
$redis->zadd($strKey, '50', json_encode(['name' => 'Tom']));
$redis->zadd($strKey, '70', json_encode(['name' => 'John']));
$redis->zadd($strKey, '90', json_encode(['name' => 'Jerry']));
$redis->zadd($strKey, '30', json_encode(['name' => 'Job']));
$redis->zadd($strKey, '100', json_encode(['name' => 'LiMing']));
$dataOne = $redis->ZREVRANGE($strKey, 0, -1, true);
echo "---- {$strKey}由大到小的排序 ---- <br /><br />";
print_r($dataOne);
$dataTwo = $redis->ZRANGE($strKey, 0, -1, true);
echo "<br /><br />---- {$strKey}由小到大的排序 ---- <br /><br />";
print_r($dataTwo);
複製代碼
解釋:悲觀鎖(Pessimistic Lock), 顧名思義,就是很悲觀。php
每次去拿數據的時候都認爲別人會修改,因此每次在拿數據的時候都會上鎖。redis
場景:若是項目中使用了緩存且對緩存設置了超時時間。數據庫
當併發量比較大的時候,若是沒有鎖機制,那麼緩存過時的瞬間,json
大量併發請求會穿透緩存直接查詢數據庫,形成雪崩效應。緩存
/**
* 獲取鎖
* @param String $key 鎖標識
* @param Int $expire 鎖過時時間
* @return Boolean
*/
public function lock($key = '', $expire = 5) {
$is_lock = $this->_redis->setnx($key, time()+$expire);
//不能獲取鎖
if(!$is_lock){
//判斷鎖是否過時
$lock_time = $this->_redis->get($key);
//鎖已過時,刪除鎖,從新獲取
if (time() > $lock_time) {
unlock($key);
$is_lock = $this->_redis->setnx($key, time() + $expire);
}
}
return $is_lock? true : false;
}
/**
* 釋放鎖
* @param String $key 鎖標識
* @return Boolean
*/
public function unlock($key = ''){
return $this->_redis->del($key);
}
// 定義鎖標識
$key = 'str:lock';
// 獲取鎖
$is_lock = lock($key, 10);
if ($is_lock) {
echo 'get lock success<br>';
echo 'do sth..<br>';
sleep(5);
echo 'success<br>';
unlock($key);
} else { //獲取鎖失敗
echo 'request too frequently<br>';
}
複製代碼
解釋:樂觀鎖(Optimistic Lock), 顧名思義,就是很樂觀。bash
每次去拿數據的時候都認爲別人不會修改,因此不會上鎖。併發
watch命令會監視給定的key,當exec時候若是監視的key從調用watch後發生過變化,則整個事務會失敗。post
也能夠調用watch屢次監視多個key。這樣就能夠對指定的key加樂觀鎖了。性能
注意watch的key是對整個鏈接有效的,事務也同樣。ui
若是鏈接斷開,監視和事務都會被自動清除。
固然了exec,discard,unwatch命令都會清除鏈接中的全部監視。
$strKey = 'str:age';
$redis->set($strKey,10);
$age = $redis->get($strKey);
echo "---- Current Age:{$age} ---- <br/><br/>"; // 10
$redis->watch($strKey);
// 開啓事務
$redis->multi();
//-------------------------------
/**
* 在這個時候新開了一個新會話執行
*
* redis-cli 執行 $redis->set($strKey,30); //新會話 模擬其餘終端
* 這時候$age=30; //30
*/
//-------------------------------
$redis->set($strKey,20);
$redis->exec();
$age = $redis->get($strKey);
echo "---- Current Age:{$age} ---- <br/><br/>"; //30
//當exec時候若是監視的key從調用watch後發生過變化,則整個事務會失敗
複製代碼
悲觀鎖:比較適合寫入操做比較頻繁的場景,若是出現大量的讀取操做,每次讀取的時候都會進行加鎖,這樣會增長大量的鎖的開銷,下降了系統的吞吐量。
樂觀鎖:比較適合讀取操做比較頻繁的場景,若是出現大量的寫入操做,數據發生衝突的可能性就會增大,爲了保證數據的一致性,應用層須要不斷的從新獲取數據,這樣會增長大量的查詢操做,下降了系統的吞吐量。
總結:兩種所各有優缺點,讀取頻繁使用樂觀鎖,寫入頻繁使用悲觀鎖。
像樂觀鎖適用於寫比較少的狀況下,即衝突真的不多發生的時候,這樣能夠省去了鎖的開銷,加大了系統的整個吞吐量。但若是常常產生衝突,上層應用會不斷的進行retry,這樣反卻是下降了性能,因此這種狀況下用悲觀鎖就比較合適,之因此用悲觀鎖就是由於兩個用戶更新同一條數據的機率高,也就是衝突比較嚴重的狀況下,因此才用悲觀鎖.
悲觀鎖比較適合強一致性的場景,但效率比較低,特別是讀的併發低。樂觀鎖則適用於讀多寫少,併發衝突少的場景