本文主要来介绍redis集群的重定向问题。
一、重定向产生的原因
对于Redis的集群来说,因为集群节点不能代理(proxy)命令请求, 所以客户端应该在节点返回 -MOVED
或者 -ASK
转向(redirection)错误时, 自行将命令请求转发至其他节点。
使用时候的常用优化方法: 客户端可以将键和节点之间的映射信息保存起来, 可以有效地减少可能出现的转向次数, 籍此提升命令执行的效率。
当节点需要让一个客户端长期地(permanently)将针对某个槽的命令请求发送至另一个节点时, 节点向客户端返回 MOVED
转向。这个情况一般是,客户端请求了不存在与当前节点上的操作的时候,我们通常可以通过在客户端维护一个节点和键值的映射关系来解决。
另一方面, 当节点需要让客户端仅仅在下一个命令请求中转向至另一个节点时, 节点向客户端返回 ASK
转向。这里重定向一般是redis集群不同节点间正在迁移数据的时候,才会使用这个ASK转向,例如redis集群的扩容或者缩容的时候。
二、MOVED转向
一个 Redis 客户端可以向集群中的任意节点(包括从节点)发送命令请求。如果所查找的槽不是由该节点处理的话, 节点将查看自身内部所保存的哈希槽到节点 ID 的映射记录, 并向客户端回复一个 MOVED
错误。
(来自: https://www.huaweicloud.com/articles/38e2316d01880fdbdd63d62aa26b31b4.html)
执行过程:
1.Redis的单个节点通过socket通讯,
会共享Redis Cluster中槽和集群中对应节点的关系。
2.客户端向Redis Cluster的任意节点发送命令,
接收命令的节点会根据CRC16规则进行hash运算与16383取余,
计算自己的槽和对应节点 。
3.如果保存数据的槽被分配给当前节点,则去槽中执行命令,
并把命令执行结果返回给客户端。
4.如果保存数据的槽不在当前节点的管理范围内,
则向客户端返回moved重定向异常 。
5.客户端接收到节点返回的结果,如果是moved异常,
则从moved异常中获取目标节点的信息。
6.客户端向目标节点发送命令,获取命令执行结果。
三、ASK转向
当节点需要让客户端仅仅在下一个命令请求中转向至另一个节点时, 节点向客户端返回 ASK
转向,往往发生在数据从节点A迁移到节点B的时候。
(来自: https://www.huaweicloud.com/articles/38e2316d01880fdbdd63d62aa26b31b4.html)
执行过程:
1.当客户端向集群中某个节点发送命令,
节点向客户端返回moved异常,告诉客户端数据对应目标槽的节点信息。
2.客户端再向目标节点发送命令,
目标节点中的槽已经迁移出别的节点上了,此时目标节点会返回ask重定向给客户端。
3.客户端向新的target节点发送Asking命令,
然后再次向新节点发送请求请求命令。
4.新节点target执行命令,把命令执行结果返回给客户端。
例子:
在我们上一节列举的槽 8
的例子中, 因为槽 8
所包含的各个键分散在节点 A 和节点 B 中, 所以当客户端在节点 A 中没找到某个键时, 它应该转向到节点 B 中去寻找, 但是这种转向应该仅仅影响一次命令查询, 而不是让客户端每次都直接去查找节点 B : 在节点 A 所持有的属于槽 8
的键没有全部被迁移到节点 B 之前, 客户端应该先访问节点 A , 然后再访问节点 B 。
参考文档:
http://redisdoc.com/topic/cluster-spec.html
https://www.huaweicloud.com/articles/38e2316d01880fdbdd63d62aa26b31b4.html