redis集群使用

请查看安装章节的redis集群相关配置使用

集群兼容方法

在正常情况下,有些方法是不能直接被集群客户端调用成功的,比如mSet方法,它涉及了多个键名的操作,而多个键名是会分配给其他节点的
目前redis集群客户端,实现了部分多键名操作方法的兼容,实现原理如下:
对多键名操作方法,进行拆分成单键名,然后通过键名去获取槽节点,再通过槽节点分配的client去执行,每次只会执行一个键名

已经实现了兼容的方法:

方法名称参数说明备注
mSet$data设置多个键值对
mGet$keys获取多个键名的值
mSetNx$data设置多个键值对该方法将不能准确的判断”当所有key不存在时,设置多个key值”

集群禁用方法

由于集群的特性,不同的key分配到了不同的槽位,当你调用sUnion,sUnIonStore等涉及多个key操作的命令时,将会返回false,同时错误信息会在$redis->getErrorMsg()中显示:

  1. $redis = new \EasySwoole\Redis\RedisCluster(new \EasySwoole\Redis\Config\RedisClusterConfig([
  2. ['172.16.253.156', 9001],
  3. ['172.16.253.156', 9002],
  4. ['172.16.253.156', 9003],
  5. ['172.16.253.156', 9004],
  6. ], [
  7. 'auth' => '',
  8. 'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_PHP
  9. ]));
  10. $data = $redis->sUnIonStore('a','v','c');
  11. var_dump($data,$redis->getErrorMsg());

将输出:

  1. bool(false)
  2. string(53) "CROSSSLOT Keys in request don't hash to the same slot"

集群客户端调度逻辑

客户端默认调度

集群客户端在调用redis方法的时候,自动默认一个客户端进行发送接收命令:

  1. function sendCommand(array $com, ?ClusterClient $client = null): bool
  2. {
  3. $client = $client ?? $this->getDefaultClient();
  4. $this->setDefaultClient($client);
  5. return $this->sendCommandByClient($com, $client);
  6. }
  7. function recv($timeout = null, ?ClusterClient $client = null): ?Response
  8. {
  9. $client = $client ?? $this->getDefaultClient();
  10. $this->setDefaultClient($client);
  11. return $this->recvByClient($client, $timeout);
  12. }

当get,或者set的key值槽位不一致时,会自动切换客户端进行发送接收命令:

  1. //节点转移客户端处理
  2. if ($result->getErrorType() == 'MOVED') {
  3. $nodeId = $this->getMoveNodeId($result);
  4. $client = $this->getClient($nodeId);
  5. $this->clientConnect($client);
  6. //只处理一次moved,如果出错则不再处理
  7. $client->sendCommand($command);
  8. $result = $client->recv($timeout ?? $this->config->getTimeout());
  9. }

切换完成之后,下一次命令,依旧是默认客户端.

获取集群的客户端

集群操作方法列表:

方法名称参数说明备注
getNodeClientList获取集群客户端列表
getNodeList获取集群节点信息数组
clientAuthClusterClient $client, $password集群客户端auth验证
setDefaultClientClusterClient $defaultClient设置一个默认的客户端
getDefaultClient获取一个默认的客户端(初始化会自动默认一个)
tryConnectServerList尝试重新获取客户端列表当调用命令返回false,可尝试重新获取
getClient$nodeKey = null根据nodeKey获取一个客户端
getMoveNodeIdResponse $response根据recv返回的Move消息获取一个nodeKey
getSlotNodeId$slotId根据槽id获取 nodeKey

这些方法用于用户自定义发送命令给redis服务端,或者是自己定义默认客户端进行发送

集群兼容管道方法

由于管道的特性,开启管道后,之后执行的命令将会保存不会直接发送,直到最后执行execPipe才会一次性发送
在集群中,只能选择一个客户端,进行一次性发送命令:

方法名称参数说明备注
execPipe?ClusterClient $client = null一次性执行管道中保存的方法可通过获取客户端列表,自定义选择一个客户端进行发送
discardPipe取消管道
startPipe管道开始记录