Official Url:https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#readme
Redis introduces cluster support as of version 3.0.0, and to communicate with a cluster using Phpredis one needs to use th E Rediscluster class. For the majority of operations the Rediscluster class can act as a drop-in replacement for the Redis class without needing To modify how it ' s called. This feature is added as the result of a generous sponsorship by Tradesy
Creating and connecting to a cluster
To maintain consistency with the Redisarray class, one can create and connect to a cluster either by passing it one or mor E ' seed ' nodes, or by defining these in Redis.ini as a ' named ' Cluster.
Declaring a cluster with an array of seeds
// Create a cluster setting two nodes as seeds
$obj_cluster = new RedisCluster(NULL, Array(‘host:7000‘, ‘host:7001‘, ‘host:7003‘));
// Connect and specify timeout and read_timeout
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5);
// Connect with read/write timeout as well as specify that phpredis should use
// persistent connections to each node.
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5, true);
Loading a cluster configuration by name
In order to load a named array, one must first define the seed nodes in Redis.ini. The following lines would define the cluster ' mycluster ', and is loaded automatically by Phpredis.
# In redis.ini
redis.clusters.seeds = "mycluster[]=localhost:7000&test[]=localhost:7001"
redis.clusters.timeout = "mycluster=5"
redis.clusters.read_timeout = "mycluster=10"
Then, this cluster can is loaded by doing the following
$obj _cluster = new Rediscluster (' mycluster ');
Connection process
On construction, the Rediscluster class would iterate over the provided seed nodes until it can attain a connection to the Cluster and run cluster SLOTS to map every node in the cluster locally. Once the keyspace is mapped, Rediscluster would only connect to nodes when it needs to (e.g. you ' re getting a key that we B Elieve is on the that node.)
Timeouts
Because Redis cluster is intended-provide high availability, timeouts does not work in the same-on-a-do-in-normal SOC KET communication. It's fully possible to having a timeout or even exception on a given socket (say in the case of a master node has failed), and continue to serve the request if and when a slave can be promoted as the new master.
The Rediscluster handles user specified timeout values are that every time a command are sent to the cluster, we record The the time at the start of the request and then again every time we had to re-issue the command to a different node (EI Ther because Redis cluster responded with Moved/ask or because we failed to communicate with a given node). Once we detect have been in the command loop for longer than our specified timeout, an error is raised.
Keyspace Map
As previously described, Rediscluster makes an initial mapping of every master (and any slaves) on construction, which it uses to determine which nodes to direct a given command. However, one of the core functionalities of Redis cluster is, the keyspace can change while the cluster is running.
Because of this, the Rediscluster class would update it ' s keyspace mapping whenever it receives a MOVED error when requesti ng data. In the case that we receive ASK redirection, it follows the Redis specification and requests the key from the ASK node, PR Efixed with an asking command.
Automatic slave failover/distribution
By default, Rediscluster would only ever send commands to master nodes, but can is configured differently for ReadOnly comm ANDs if requested.
// The default option, only send commands to master nodes
$obj_cluster->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_NONE);
// In the event we can‘t reach a master, and it has slaves, failover for read commands
$obj_cluster->setOption(RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_ERROR);
// Always distribute readonly commands between masters and slaves, at random
$obj_cluster->setOption(
RedisCluster::OPT_SLAVE_FAILOVER, RedisCluster::FAILOVER_DISTRIBUTE
);
Main Command Loop
With the exception of commands, was directed to a specific node, each command executed via Rediscluster is processed T Hrough a command loop, where we make the request, handle any MOVED or ASK redirection, and repeat if necessary. This continues until one of the following conditions is met:
- We fail to communicate with any node that we were aware of, in which case a isRedisClusterExecptionraised.
- We have been bounced around longer than the timeout which is set on construction.
- Redis Cluster returns us aCLUSTERDOWNerror, in which case a isRedisClusterExceptionraised.
- We receive a valid response, in which case the data was returned to the caller.
Transactions
The Rediscluster class fully supports MULTI ... EXEC transactions, including commands such as MGET and MSET which operate on multiple keys. There is considerations that must is taken into account here however.
When you callRedisCluster->multi(), the cluster was put into a MULTI state, but the MULTI command was not delivered to any nodes until a ke Y is requested on that node. In addition, calls to EXEC would always return an array (even in the event that a transaction to a given node failed), as T He commands can be going to any number of nodes depending on what is called.
Consider the following example:
// Cluster is put into MULTI state locally
$obj_cluster->multi();
// The cluster will issue MULTI on this node first (and only once)
$obj_cluster->get("mykey");
$obj_cluster->set("mykey", "new_value");
// If ‘myotherkey‘ maps to a different node, MULTI will be issued there
// before requesting the key
$obj_cluster->get("myotherkey");
// This will always return an array, even in the event of a failed transaction
// on one of the nodes, in which case that element will be FALSE
print_r($obj_cluster->exec());
Pipelining
The Rediscluster class does not pipelining as there is no-to-detect whether the keys still live where our map Indicates that they does and would therefore be inherently unsafe. It would be possible to implement this support as an option if there is demand for such a feature.
Multiple key commands
Redis cluster does allow commands this operate on multiple keys, but only if all of the those keys hashes to the same slot. Note that it isn't enough that the keys are all on the same node, but must actually hash to the exact same hash slot.
For any of these multiple key commands (with the exception of MGET and MSET), the Rediscluster class would verify each key Maps to the same hash slot and raise a "Crossslot" warning, returning false if they don ' t.
MGET and MSET
Rediscluster have specialized processing for MGET and MSET which allows the send any number of keys (hashing to Whicheve R slots) without has to consider where they live. The "This works," is, the Rediscluster class would split the command as it iterates through keys, delivering a subset of commands per each key ' s slot.
// This will be delivered in two commands. First for all of the {hash1} keys,
// and then to grab ‘otherkey‘
$obj_cluster->mget(Array("{hash1}key1","{hash1}key2","{hash1}key3","otherkey"));
This operation can also is do in MULTI mode transparently.
Directed node Commands
There is a variety of commands which has to is directed at a specific node. In the case of these commands, the caller can either pass a key (which would be hashed and used to direct our command), or An array with Host:port.
// This will be directed at the slot/node which would store "mykey"
$obj_cluster->echo("mykey","Hello World!");
// Here we‘re iterating all of our known masters, and delivering the command there
foreach ($obj_cluster->_masters() as $arr_master) {
$obj_cluster->echo($arr_master, "Hello: " . implode(‘:‘, $arr_master));
}
In the case of all commands which need to being directed at a node, the calling convention are identical to the Redis call, ex Cept that they require a additional (first) argument in order to deliver the command. Following is a list of each of these commands:
- SAVE
- BGSAVE
- Flushdb
- Flushall
- Dbsize
- Bgrewriteaof
- Lastsave
- INFO
- CLIENT
- CLUSTER
- CONFIG
- PUBSUB
- Slowlog
- Randomkey
- Ping
Session Handler
You can use the cluster functionality of Phpredis to store PHP session information in a Redis cluster as can with a No n cluster-enabled Redis instance.
To does this, you must configure your and INI variables to give Phpredis enough information tosession.save_handlersession.save_pathcommunicate with The cluster.
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
Set this variable to the "Rediscluster" to inform Phpredis, which is a cluster instance.
Session.save_path
The save path for cluster based session storage takes the form of a PHP GET request, and requires so you specify at L East on seed node. Other options can specify is as follows:
- timeout (double): The amount of time Phpredis would wait when connecting or writing to the cluster.
- read_timeout (Double): The amount of time Phpredis would wait for a result from the cluster.
- persistent: tells Phpredis whether persistent connections should be used.
- Distribute: Phpredis would randomly distribute session reads between masters and any attached slaves (load Balanci NG).
- failover (String): How Phpredis should distribute session reads between Master and slave nodes.
- None : Phpredis Communicate with master nodes
- error: Phpredis would communicate with master nodes unless one failes, in which case an attempt would be made to re Ad session information from a slave.
Phpredis Redis cluster Redis Cluster