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将与主节点进行通讯,除非出现故障,在这种状况下,将尝试从从站读取会话信息
相关文章
相关标签/搜索