phpredis Redis集羣 Redis Cluster

官方url: https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#readmephp

 2017年10月29日20:44:25node

Redis引入3.0.0版本的羣集支持,而且使用phpredis與羣集進行通訊時,須要使用RedisCluster類。 對於大多數操做,RedisCluster類能夠做爲Redis類的替換,而不須要修改它的調用方式。 因爲Tradesy的慷慨贊助,這個功能被添加了git

建立並鏈接到集羣

爲了保持與RedisArray類的一致性,能夠經過傳遞一個或多個「種子」節點,或者將redis.ini中的這些節點定義爲「命名」集羣來建立和鏈接到集羣github

聲明具備種子數組的羣集

// 建立一個集羣,將兩個節點設置爲種子
$obj_cluster = new RedisCluster(NULL, Array('host:7000', 'host:7001', 'host:7003'));

// 鏈接並指定timeout和read_timeout
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5);

// 鏈接讀/寫超時,並指定phpredis應該使用
// 鏈接到每一個節點
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5, true);

按名稱加載羣集配置

爲了加載一個命名的數組,必須首先在redis.ini中定義種子節點。 如下行將定義集羣「mycluster」,並由phpredis自動加載redis

# In redis.ini
redis.clusters.seeds = "mycluster[]=localhost:7000&test[]=localhost:7001"
redis.clusters.timeout = "mycluster=5"
redis.clusters.read_timeout = "mycluster=10"

而後,能夠經過執行如下操做來加載此羣集數組

$obj_cluster = new RedisCluster('mycluster');

鏈接過程

在構建時,RedisCluster類將遍歷提供的種子節點,直到它能夠得到與羣集的鏈接,並運行CLUSTER SLOTS以映射本地羣集中的每一個節點。 一旦鍵空間被映射,RedisCluster只會在須要時鏈接到節點(例如,您得到了咱們相信該節點上的密鑰)。安全

超時

因爲Redis集羣旨在提供高可用性,所以超時在正常套接字通訊中的工做方式不同。 徹底可能在給定的套接字上發生超時甚至異常(例如,在主節點發生故障的狀況下),而且若是能夠將從屬機制升級爲新主機,則繼續提供請求。服務器

RedisCluster處理用戶指定的超時值的方式是,每當命令發送到集羣時,咱們會記錄在請求開始時的時間,而後再次每次從新發出命令到另外一個節點 由於Redis集羣用MOVED / ASK響應,或者由於咱們未能與給定節點進行通訊)。 一旦咱們檢測到在命令循環中超過咱們指定的超時時間,就會出現錯誤。markdown

Keyspace map

如前所述,RedisCluster對構建中的每一個主(和任何從站)進行初始映射,它用於肯定哪些節點用於指定給定的命令。 可是,Redis集羣的核心功能之一就是,這個密鑰空間能夠在集羣運行時發生變化。session

所以,RedisCluster類將在請求數據時收到MOVED錯誤時更新它的密鑰空間映射。 在咱們收到ASK重定向的狀況下,它遵循Redis規範,並從ASK節點請求密鑰,前綴爲ASKING命令。

Automatic slave failover / distribution 自動從站故障切換/分發

默認狀況下,RedisCluster只會向主節點發送命令,可是若是請求,能夠爲readonly命令配置不一樣的命令。

//默認選項,只發送命令到主節點
$obj_cluster->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_NONE);

// 若是咱們沒法訪問主服務器,而且對於讀取命令,它們具備從站,故障轉移
$obj_cluster->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_ERROR);

// 始終在主機和從機之間隨機分配只讀命令
$obj_cluster->setOption(
    RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_DISTRIBUTE
);

Main command loop 主命令循環

除了指向特定節點的命令以外,經過RedisCluster執行的每一個命令都將經過命令循環進行處理,在該循環中,咱們進行請求,處理任何MOVED或ASK重定向,並在必要時重複執行。 這將持續到知足如下條件之一:

  1. 咱們沒法與咱們所知道的任何節點通訊,在這種狀況下會引起RedisClusterExecption。
  2. 咱們已經反彈了比施工期限的時間更長的時間。(翻譯有問題)
  3. Redis cluster返回一個CLUSTERDOWN錯誤,在這種狀況下會引起一個RedisClusterException異常。
  4. 咱們收到一個有效的響應,在這種狀況下,數據將返回給來調用者。

Transactions

RedisCluster類徹底支持MULTI ... EXEC事務,包括在多個鍵上操做的諸如MGET和MSET的命令。 可是,在這裏必須考慮到這些因素。

當您調用RedisCluster-> multi()時,集羣將進入MULTI狀態,可是在該節點上請求一個密鑰以前,MULTI命令不會傳遞給任何節點。 此外,對EXEC的調用將始終返回一個數組(即便在給定節點的事務發生故障的狀況下),由於根據所調用的命令能夠轉到任意數量的節點

請考慮如下示例:

// 集羣在本地進入MULTI狀態
$obj_cluster->multi();

// 集羣將首先在該節點上發佈MULTI(而且只有一次)
$obj_cluster->get("mykey");
$obj_cluster->set("mykey", "new_value");

// 若是'myotherkey'映射到不一樣的節點,MULTI將在那裏發出
// before requesting the key
$obj_cluster->get("myotherkey");

// 即便在事件失敗的狀況下,它也將始終返回一個數組
// 在其中一個節點上,在這種狀況下,該元素將爲FALSE
print_r($obj_cluster->exec());

Pipelining

RedisCluster類不支持流水線,由於沒法檢測密鑰是否仍然存在於咱們的地圖表示它們所作的事情上,所以原本不安全。 若是須要這樣的功能,能夠實施這種支持做爲選擇。

Multiple key commands

Redis集羣容許在多個鍵上操做的命令,但只有當全部這些鍵都散列到同一個插槽時。 請注意,這些密鑰所有在同一個節點上是不夠的,但實際上必須哈希到徹底相同的哈希槽。

對於全部這些多個密鑰命令(除了MGET和MSET以外),RedisCluster類將驗證每一個密鑰映射到相同的哈希槽,並引起「CROSSSLOT」警告,若是沒有,則返回false。

MGET and MSET

RedisCluster具備針對MGET和MSET的專門處理功能,容許您發送任意數量的密鑰(散列到任意一個插槽),而無需考慮其居住地點。 這樣作的方式是,RedisCluster類會在命令遍歷密鑰時分割命令,併爲每一個密鑰的插槽提供一組命令

// 這將經過兩個命令傳遞。 首先對於全部的{hash1}鍵
// 而後抓取'otherkey'
$obj_cluster->mget(Array("{hash1}key1","{hash1}key2","{hash1}key3","otherkey"));

這個操做也能夠在MULTI模式下透明地完成

Directed node commands

有各類命令必須針對特定節點。 在這些命令的狀況下,調用者能夠傳遞一個鍵(它將被散列並用於指示咱們的命令),或者傳遞一個帶有host:port的數組

// 這將針對將存儲「mykey」的插槽/節點
$obj_cluster->echo("mykey","Hello World!");

// 在這裏,咱們重複了全部已知的主節點,並在那裏交付命令
foreach ($obj_cluster->_masters() as $arr_master) {
    $obj_cluster->echo($arr_master, "Hello: " . implode(':', $arr_master));
}

在須要指向節點的全部命令的狀況下,調用約定與Redis調用相同,只是它們須要額外的(第一個)參數才能傳遞命令。 如下是每一個命令的列表:

  1. SAVE
  2. BGSAVE
  3. FLUSHDB
  4. FLUSHALL
  5. DBSIZE
  6. BGREWRITEAOF
  7. LASTSAVE
  8. INFO
  9. CLIENT
  10. CLUSTER
  11. CONFIG
  12. PUBSUB
  13. SLOWLOG
  14. RANDOMKEY
  15. PING

Session Handler

您可使用phpredis的集羣功能將Redhat集羣中的PHP會話信息存儲在可啓用的不支持集羣功能的Redis實例中。

爲此,您必須配置session.save_handler和session.save_path INI變量,以使phpredis足夠的信息與羣集通訊。

session.save_handler = rediscluster session.save_path = "seed[]=host1:port1&seed[]=host2:port2&seed[]=hostN:portN&timeout=2&read_timeout=2&failover=error&persistent=1"

session.session_handler

將此變量設置爲「rediscluster」以通知phpredis這是一個集羣實例

session.save_path

基於羣集的會話存儲的保存路徑採用PHP GET請求的形式,並要求您至少在種子節點上指定。 您能夠指定的其餘選項以下:

  • timeout (double): phpredis在鏈接或寫入羣集時等待的時間量
  • read_timeout (double): phpredis的時間將等待集羣的結果
  • persistent: 告訴phpredis是否應該使用永久鏈接
  • distribute: phpredis將隨機分配主機和任何鏈接的從站之間的會話讀取(負載平衡)
  • failover (string): phpredis應如何分配主節點和從節點之間的會話讀取
    • none : phpredis只能與主節點進行通訊
    • error: phpredis將與主節點進行通訊,除非出現故障,在這種狀況下,將嘗試從從站讀取會話信息
相關文章
相關標籤/搜索