PHP 在redis-sentinel模式下的使用總結

Light發表於2019-02-16

近期公司所用專案的快取想要由memcache遷移到redis,運維給配置的redis使用模式是sentinel(即哨兵模式的),這種模式之前沒用過,在此記錄一下。

簡單介紹下Redis-sentinel:
Redis-sentinel是Redis例項的監控管理、通知和例項失效備援服務,是Redis叢集的管理工具。在一般的分散式中心節點資料庫中,Redis-sentinel的作用是中心節點的工作,監控各個其他節點的工作情況並且進行故障恢復,來提高叢集的高可用性
(簡介來自http://www.searchdatabase.com…

我自己的理解就是,假如有a,b,c 3臺可用的redis伺服器,其中a為主伺服器,b,c為從伺服器。
在sentinel模式下如果a出現問題,可以自動將a伺服器拿掉或者降級為從伺服器,然後從b和c中根據一定策略選擇一臺升級為主伺服器,之後a恢復後作為從伺服器使用,避免了了由於某臺伺服器出現問題時影響整個redis服務。

redis-sentinel模式對redis服務無疑是一個很好的支援,但是在開發人員使用時會稍微麻煩一些。因為可能更常用的模式就是直接在程式中寫好一個配置檔案,redis主從庫都是確定的,程式讀取配置檔案進行redis操作。假如主庫出現問題,必須手動修改配置檔案才能繼續正常使用。而如果發現的比較晚可能會造成不必要的損失。

而在sentinel模式下需要程式動態獲取主從庫的ip,即使某臺redis服務出現問題,也不會影響到程式,這樣就避免了手動修改配置的問題。而關鍵問題其實就是動態獲取主從庫的ip,埠等資訊了。
在網上查相關資料,大部分都是講解如何配置sentinel服務,而php對應使用方法不太多。看了官方redis-sentinel文件後瞭解到獲取sentinel資訊是有對應API的,只不過是一些原生命令。

而php-redis庫是有支援原生命令的方法的,如下:

    /*
     * Send arbitrary things to the redis server.
     * @param   string      $command    Required command to send to the server.
     * @param   mixed       ...$arguments  Optional variable amount of arguments to send to the server.
     * @return  mixed
     * @example
     * <pre>
     * $redis->rawCommand(`SET`, `key`, `value`); // bool(true)
     * $redis->rawCommand(`GET", `key`); // string(5) "value"
     * </pre>
     */
    public function rawCommand( $command, $arguments ) {}

而在開發使用大致過程如下
1、根據運維給的sentinel配置資訊連線sentinel,獲得需要的資訊(注意:此處是sentinel服務的配置資訊,和redis的並不一致)。配置資訊(IP,PORT)會有多個,每個sentinel返回的redis主從配置資訊是一致的,所以進行操作時使用其中一臺服務返回的資訊即可。

//初始化redis物件
$redis = new Redis();
//連線sentinel服務 host為ip,port為埠
$redis->connect($host, $port);

//可能用到的部分命令,其他可以去官方文件檢視

//獲取主庫列表及其狀態資訊
$result = $redis->rawCommand(`SENTINEL`, `masters`);

//根據所配置的主庫redis名稱獲取對應的資訊
//master_name應該由運維告知(也可以由上一步的資訊中獲取)
$result = $redis->rawCommand(`SENTINEL`, `master`, $master_name);

//根據所配置的主庫redis名稱獲取其對應從庫列表及其資訊
$result = redis->rawCommand(`SENTINEL`, `slaves`, $master_name);

//獲取特定名稱的redis主庫地址
$result = $redis->rawCommand(`SENTINEL`, `get-master-addr-by-name`, $master_name)

//這個方法可以將以上sentinel返回的資訊解析為陣列
function parseArrayResult(array $data)
{
    $result = array();
    $count = count($data);
    for ($i = 0; $i < $count;) {
        $record = $data[$i];
        if (is_array($record)) {
            $result[] = parseArrayResult($record);
            $i++;
        } else {
            $result[$record] = $data[$i + 1];
            $i += 2;
        }
    }
    return $result;
}

2、通過以上操作已經可以獲取到redis主從庫的資訊,redis密碼是固定的,自己寫好就OK。之後就可以按照單例模式去使用redis了,注意操作時主從分離。

以上只是一個大體的使用過程,不同情況可能有所調整。

已上只是簡單說了下php程式如何去使用這種模式,具體工作原理和配置請移步
https://segmentfault.com/a/11…
https://segmentfault.com/a/11…

相關文章