redis集群使用

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

集群兼容方法

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

已经实现了兼容的方法:

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

集群禁用方法

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

$redis = new \EasySwoole\Redis\RedisCluster(new \EasySwoole\Redis\Config\RedisClusterConfig([
    ['172.16.253.156', 9001],
    ['172.16.253.156', 9002],
    ['172.16.253.156', 9003],
    ['172.16.253.156', 9004],
], [
    'auth'      => '',
    'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_PHP
]));

$data = $redis->sUnIonStore('a','v','c');
var_dump($data,$redis->getErrorMsg());

将输出:

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

集群客户端调度逻辑

客户端默认调度

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

function sendCommand(array $com, ?ClusterClient $client = null): bool
{
    $client = $client ?? $this->getDefaultClient();
    $this->setDefaultClient($client);
    return $this->sendCommandByClient($com, $client);
}

function recv($timeout = null, ?ClusterClient $client = null): ?Response
{
    $client = $client ?? $this->getDefaultClient();
    $this->setDefaultClient($client);
    return $this->recvByClient($client, $timeout);
}

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

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

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

获取集群的客户端

集群操作方法列表:

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

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

集群兼容管道方法

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

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