Redis plus plus是一个c++版本的Redis客户端,更详细的介绍见:https://blog.csdn.net/qq_34999565/article/details/119918553
cluster模式的命令发送接口如下,和普通命令发送接口的区别主要有几点
1,当命令返回一个io错误IoError的时候,有可能是主节点已经下线,这时候从节点会被晋升为主节点。往一个旧的的主节点发送命令就会返回一个IoError错误,这种情况下需要更新槽位映射关系;
2,如果一个节点已被移除,再往这个节点发送命令也会返回一个错误-ClosedError,这时也需要重新更新槽位映射;
3,对重定向MovedError错误的处理,发生这个错误意味着槽位映射出错了,所以也要更新槽位映射;
4,aski错误,这种情况发生于槽位迁移过程中,这种情况不需要更新槽位映射,ask错误会把目标节点信息带过来,只需从目标节点中获取一条新的连接,再往该链接发送一个asking命令,然后在重发命令
ReplyUPtr RedisCluster::_command(Cmd cmd, const StringView &key, Args &&...args) {
for (auto idx = 0; idx < 2; ++idx) {
try {
auto pool = _pool.fetch(key);
assert(pool);
SafeConnection safe_connection(*pool);
return _command(cmd, safe_connection.connection(), std::forward<Args>(args)...);
} catch (const IoError &err) {
// When master is down, one of its replicas will be promoted to be the new master.
// If we try to send command to the old master, we'll get an *IoError*.
// In this case, we need to update the slots mapping.
_pool.update();
} catch (const ClosedError &err) {
// Node might be removed.
// 1. Get up-to-date slot mapping to check if the node still exists.
_pool.update();
// TODO:
// 2. If it's NOT exist, update slot mapping, and retry.
// 3. If it's still exist, that means the node is down, NOT removed, throw exception.
} catch (const MovedError &err) {
// Slot mapping has been changed, update it and try again.
_pool.update();
} catch (const AskError &err) {
auto pool = _pool.fetch(err.node());
assert(pool);
SafeConnection safe_connection(*pool);
auto &connection = safe_connection.connection();
// 1. send ASKING command.
_asking(connection);
// 2. resend last command.
try {
return _command(cmd, connection, std::forward<Args>(args)...);
} catch (const MovedError &err) {
throw Error("Slot migrating... ASKING node hasn't been set to IMPORTING state");
}
} // For other exceptions, just throw it.
}
// Possible failures:
// 1. Source node has already run 'CLUSTER SETSLOT xxx NODE xxx',
// while the destination node has NOT run it.
// In this case, client will be redirected by both nodes with MovedError.
// 2. Other failures...
throw Error("Failed to send command with key: " + std::string(key.data(), key.size()));
}