Jedis 如何支持 Sentinel
## 前言
Jedis 作为 Java 世界 Redis 的老牌客户端,很好的支持了 Sentinel,例如 Sentinel 的故障转移功能。
代码
Jedis 提供了一个 Sentinel 构造方法:
1 | public JedisSentinelPool(String masterName, Set<String> sentinels, |
该构造方法做了 2件事情,初始化 Sentinel 和 Pool。我们先看看 initSentinel。
1 | private HostAndPort initSentinels(Set<String> sentinels, final String masterName) { |
方法很长,简单说说逻辑:
- 遍历 Sentinel 字符串
- 根据字符串生成 HostAndPort 对象,然后创建一个 Jedis 对象。
- 使用 Jedis 对象发送
get-master-addr-by-name masterName
命令,得到 master 信息。 - 得到 master 信息后,再次遍历哨兵集合,为每个哨兵创建一个线程,监听哨兵的发布订阅消息,消息主题是
+switch-master
. 当主节点发生变化时,将通过 pub/sub 通知该线程,该线程将更新 Redis 连接池。
看看这个线程的主要内容:
1 |
|
该方法已经写了很多注释,稍微说下逻辑:根据哨兵的 host 和 port 创建一个 jedis 对象,然后,这个 jedis 对象订阅了 pub/sub 消息,,消息的主题是 “+switch-master” ,如果收到消息了,就执行 onMessage 方法,该方法会根据新的 master 信息重新初始化 Redis 连接池。
那么如何初始化连接池的呢?
1 | private void initPool(HostAndPort master) { |
事实上,在 Sentinel 构造器里面,也会调用这个方法,第一次调用的时候, factory 肯定是 null,第二次调用的时候,会设置 factory 的 hostAndPort 为新的 master 地址,然后清空原来的连接池。那么新的 getResource 方法就会从这个新的地址获取到新的连接了。
具体关于 JedisSentinelPool 的 getResource 方法就不细说了,大家可以自己看看,还是很简单的,
总结
可以看到 Sentinel 的通知客户端机制,是需要客户端进行配合的,客户端需要通过 Sentinel 的 pub/sub 机制订阅哨兵节点的 +switch-master
主题,当 master 改变的时候,会通过 pub 通知客户端,客户端此时就可以优雅的更新连接池。
Jedis 如何支持 Sentinel
http://thinkinjava.cn/2018/08/04/2018/2018-08-06-Jedis 如何支持 Sentinel/