Redis 實現分佈鎖

kakasaber發表於2020-10-16
<?php
/**
 * 實現Redis分佈鎖
 */

$key        = 'test';       //要更新資訊的快取KEY
$lockKey    = 'lock:'.$key; //設定鎖KEY
$lockExpire = 10;           //設定鎖的有效期為10秒

//獲取快取資訊
$result = $redis->get($key);
//判斷快取中是否有資料
if(empty($result))
{
    $status = TRUE;
    while ($status)
    {
        //設定鎖值為當前時間戳 + 有效期
        $lockValue = time() + $lockExpire;
        /**
         * 建立鎖
         * 試圖以$lockKey為key建立一個快取,value值為當前時間戳
         * 由於setnx()函式只有在不存在當前key的快取時才會建立成功
         * 所以,用此函式就可以判斷當前執行的操作是否已經有其他程式在執行了
         * @var [type]
         */
        $lock = $redis->setnx($lockKey, $lockValue);
        /**
         * 滿足兩個條件中的一個即可進行操作
         * 1、上面一步建立鎖成功;
         * 2、   1)判斷鎖的值(時間戳)是否小於當前時間    $redis->get()
         *      2)同時給鎖設定新值成功    $redis->getset()
         */
        if(!empty($lock) || ($redis->get($lockKey) < time() && $redis->getSet($lockKey, $lockValue) < time() ))
        {
            //給鎖設定生存時間
            $redis->expire($lockKey, $lockExpire);
            //******************************
            //此處執行插入、更新快取操作...
            //******************************

            //以上程式走完刪除鎖
            //檢測鎖是否過期,過期鎖沒必要刪除
            if($redis->ttl($lockKey))
                $redis->del($lockKey);
            $status = FALSE;
        }else{
            /**
             * 如果存在有效鎖這裡做相應處理
             *      等待當前操作完成再執行此次請求
             *      直接返回
             */
            sleep(2);//等待2秒後再嘗試執行操作
        }
    }
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章