客户端路由
首选简单说下redis-cli客户端
通过cluster keyslot [key]
可以计算出key对用的槽。
通过./redis-cli -c -p [port]
可以以集群模式访问,它会自动的帮助我们捕获moved异常,自动跳转到新的节点并执行命令。
moved重定向
redis-cli 原始方式连接
[root@iz2zechwdfwvcm1rr3upjvz redis]# ./redis-cli -p 8000
127.0.0.1:8000> set zhangsan 100
# 返回moved异常,需要转到8002节点执行
(error) MOVED 12767 127.0.0.1:8002
# 退出
127.0.0.1:8000> exit
#手动连接8002节点执行set命令
[root@iz2zechwdfwvcm1rr3upjvz redis]# ./redis-cli -p 8002
127.0.0.1:8002> set zhangsan 100
OK
redis-cli 集群模式连接
[root@iz2zechwdfwvcm1rr3upjvz redis]# ./redis-cli -c -p 8000
#发送set命令
127.0.0.1:8000> set zhangsan 100
# 跳转到8002节点,并执行set命令
-> Redirected to slot [12767] located at 127.0.0.1:8002
OK
127.0.0.1:8002>
ask重定向
ask重定向会发生在集群的伸缩过程中,会导致slot发生迁移,似的客户端原本能够访问到的槽,在迁移过程中所处位置发生变化,导致客户端无法正常访问,此时需要ask重定向帮助客户端找到slot的正确的位置。
ask和moved
- 两者都属于客户端重定向
- moved异常代表槽已经确定不再当前节点,确定已经迁移
- ask异常代表当前正处在slot迁移中,每时每刻槽的位置处于不确定
在集群伸缩时就对客户端造成了极大的困扰,这对我们客户端的实现就有了一个很高的要求,redis本来就是高性能的nosql,这时访问的不确定性对性能造成了很大的影响,那么此时我们就需要一个智能客户端。
智能客户端
既然使用了 redis那么我们肯定是想要追求性能,那么代理我们就放弃使用。
我们可以简单梳理下实现一个智能客户端的实现的伪代码!
- 从集群中选择一个可运行节点,使用cluster slots初始化槽和节点映射。
- 将cluster slots的结果映射到本地,为每个节点创建JedisPool。
- 准备执行命令,当连接出错,我们可以访问随机节点
- 在正常情况下我们缓存下来的映射关系是可以保证我们直接通过直连就可以完成命令的执行。
- 当我们接收到redis返回的moved异常,那就证明redis的槽已经发生了迁移,那么我们根据返回信息,再次连接另一个redis节点,完成命令执行,同时本地slots和节点映射关系需要重新初始化。
- 当我们接收到redis返回的ask异常,证明redis可能正在进行slots迁移,再次访问新的节点完成命令的执行
- 不管是moved异常还是ask异常,当命令发送次数超过一定限制仍未成功,需要抛出异常信息,转由人工排查。
JedisCluster就是一个实现很完美的智能客户端。
- 单例:内置了所有节点的连接池。
- 无需手动借还连接池。
- 设置好commons-pool。