1. 程式人生 > 程式設計 >Redis-PHP實戰篇——常用的使用場景

Redis-PHP實戰篇——常用的使用場景

redis-php實戰

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();
複製程式碼

String 簡單字串快取實戰

$key  = 'str:name';
 
// 字串快取實戰
$redis->set($key
,'WXiangQian'); $name = $redis->get($key); echo $name; // WXiangQian $redis->expire($strCacheKey,30); # 設定30秒後過期 複製程式碼

HSET 簡單雜湊快取實戰

$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,-1,true); echo "---- {$strKey}由大到小的排序 ---- <br /><br />"; print_r($dataOne); $dataTwo = $redis->ZRANGE($strKey,true); echo "<br /><br />---- {$strKey}由小到大的排序 ---- <br /><br />"; print_r($dataTwo); 複製程式碼

list分頁實戰

$strKey = 'list:data';
$page = $request->input('page',1);
$pageSize = $request->input('limit',50);
$limit_s = ($page-1) * $pageSize;
$limit_e = ($limit_s + $pageSize) - 1;
$data = $tools->redis->lRange($strKey,$limit_s,$limit_e);
print_r($data);
複製程式碼

簡單字串悲觀鎖實戰

解釋:悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀。

每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖。

場景:如果專案中使用了快取且對快取設定了超時時間。

當併發量比較大的時候,如果沒有鎖機制,那麼快取過期的瞬間,

大量併發請求會穿透快取直接查詢資料庫,造成雪崩效應。

/**
 * 獲取鎖
 * @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),顧名思義,就是很樂觀。

每次去拿資料的時候都認為別人不會修改,所以不會上鎖。

watch命令會監視給定的key,當exec時候如果監視的key從呼叫watch後發生過變化,則整個事務會失敗。

也可以呼叫watch多次監視多個key。這樣就可以對指定的key加樂觀鎖了。

注意watch的key是對整個連線有效的,事務也一樣。

如果連線斷開,監視和事務都會被自動清除。

當然了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,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適,之所以用悲觀鎖就是因為兩個使用者更新同一條資料的概率高,也就是衝突比較嚴重的情況下,所以才用悲觀鎖.

悲觀鎖比較適合強一致性的場景,但效率比較低,特別是讀的併發低。樂觀鎖則適用於讀多寫少,併發衝突少的場景

redis篇集合

Redis基礎篇——Redis安裝

Redis基礎篇——介紹以及瞭解

Redis基礎篇——基本用法

Redis進階篇——PHP連線redis

Redis-PHP實戰篇——常用的使用場景