{{ it.name }}
{{ it.text }}
作者:王悦
redis sentinel 提供了一个服务发现机制,连接 sentinel 执行“SENTINEL get-master-addr-by-name”,会返回当前 master 实例地址,故障切换后,返回结果也会更新为新的master实例地址: 有很多“聪明”的 redis client 库都实现了基于该服务发现机制的自动连接,只要将 sentinel 的地址列表传入,clinet 会通过 sentinel 获取当前最新的 master 地址,然后使用获取的地址连接。比如 jedis: jedis 作为一个优秀的 redis 客户端,其使用的订阅 sentinel 的方式是时刻在内存中维护最新的 master 地址。而一些其他的 client 则是在每次获取连接时,先询问 sentinel 最新 master 地址,然后再执行 redis 连接,这样每次操作都需要发送两次请求,并不是非常高效。另一种方式是使用 VIP : 我们维护一个 VIP ,使其始终绑定在 master 节点上,这样 client 连接时就可以无脑地连接 VIP 地址。VIP 的维护可以通过 sentinel 的 client-reconfig-script 脚本实现,每次 sentinel 监控的主从实例发生故障切换后,sentinel 都会调用该脚本并传入最新的 master 地址,我们可以在脚本内实现 VIP 的绑定和解绑操作。 绑定 VIP 不依赖于 client 的“聪明”,通过自定义脚本实现,比较灵活可控,但是 VIP 对于一些外网访问场景无法支持。当然由于脚本是自定义的,比如有 DNS 系统,则可以将绑定 VIP 换成绑定 DNS ,去提供外网的访问能力. 方法三与方法二类似,都是通过 VIP 提供服务入口,方法三使用 keepalived 的 VRRP 来实现 VIP 绑定,不依赖于 sentinel 的 reconfig 脚本。 一些公有云的 redis 服务都提供了一个 Proxy 地址用于 client 的访问,该地址后面实际就对应了一个中间件代理。实现一个中间件除了需要开发成本,还需要在运行时维护中间件本身的高可用,当然花了成本就会带来收益。中间件除了实现基础的连接转发以外,还能提供更多的高阶功能,比如阿里云的 redis Proxy 提供了: 重定向指的是 client 会随机挑选一个 redis 实例进行请求操作,redis 实例收到请求后会计算 key 对应的 slot ,如果在本地则直接处理,否则会返回一个 MOVED 给 client ,指明正确的实例地址,让 client 进行重定向。比如 redis-cli 工具就是使用的重定向方式: redis-cli 在收到 MOVED 响应后会自动重定向到指定的地址,这样做的一个问题是可能一次操作会需要两次请求,比较影响性能。 “聪明”的 client (比如 JedisCluster)会在启动时通过访问集群中任意节点,获取 slots 信息,在本地缓存一份所有 slots 所对应的节点列表。这样当 slots 没有发生迁移时,能够保证操作请求被直接发送到正确的节点上。而当集群中发生了 slots 迁移之后,某些请求会返回错误,此时 client 会重新更新缓存中的 slots 列表,然后再次请求。由于 slots 迁移并不是一个高频操作,这样的做法对总体性能影响不大。 万能的中间件,和主从架构类似,这里就不详细讨论了,如果 client 不够”聪明“,可以把锅丢给中间件。当然实现中间件的成本和收益成正比,需要根据实际情况选择。主从架构方法一: 使用 redis sentinel 的服务发现
sentinels.add(new HostAndPort("192.168.0.31",26379).toString());
sentinels.add(new HostAndPort("192.168.0.32",26379).toString());
sentinels.add(new HostAndPort("192.168.0.33",26379).toString());
pool = new JedisSentinelPool(masterName, sentinels, config, TIMEOUT,password);
...
// 获取连接:
Jedis jedis = pool.getResource();
try {
jedis.set("hello", "jedis");
} finally {
jedis.close();
}主从架构方法二:绑定 VIP
主从架构方法三: 使用 keepalived VRRP
主从架构方法四:中间件代理
集群架构方法一:请求重定向
集群架构方法二:本地缓存 slots 列表
集群架构方法三:中间件代理