Jedis 有4 种工作模式:单节点、分片(Sharded)、哨兵(Sentinel)、集群(Cluster)。上一篇我们通过实际应用的例子进行了源码剖析,本文将通过实际的例子对Redis的Sentinel
进行源码剖析。
分片(Sharded)、集群(Cluster)请参考:
1、环境:
对于Redis Sentinel的搭建请参考一篇学会Redis Sentinel的集群搭建
1、操作系统:Centos7.7
2、服务器配置如下:(本文采用了在单台机子上部署多个实例来模拟多机部署)
主机 | ip | 角色和端口 |
---|---|---|
master | 132.232.125.196 | 6380 |
slave1 | 132.232.125.196 | 6381 |
slave2 | 132.232.125.196 | 6382 |
Sentinel | 132.232.125.196 | 16380 |
Sentinel | 132.232.125.196 | 16381 |
Sentinel | 132.232.125.196 | 16382 |
2、启动redis和Sentinel服务
[root@m logs]# ps -ef|grep redis
root 13037 1 0 18:07 ? 00:00:00 /usr/local/soft/redis-5.0.8/src/redis-server *:6380
root 13042 1 0 18:07 ? 00:00:00 /usr/local/soft/redis-5.0.8/src/redis-server *:6381
root 13049 1 0 18:07 ? 00:00:00 /usr/local/soft/redis-5.0.8/src/redis-server *:6382
root 13942 1 0 18:07 ? 00:00:00 /usr/local/soft/redis-5.0.8/src/redis-sentinel *:16380 [`sentinel`]
root 13947 1 0 18:07 ? 00:00:00 /usr/local/soft/redis-5.0.8/src/redis-sentinel *:16381 [`sentinel`]
root 13952 1 0 18:07 ? 00:00:00 /usr/local/soft/redis-5.0.8/src/redis-sentinel *:16382 [`sentinel`]
root 14019 937 0 18:07 ? 00:00:00 [redis-server] <defunct>
root 14021 21486 0 18:07 pts/1 00:00:00 grep --color=auto redis
3、测试代码
package nci.henry;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @Author: henry
* @Date: 2020/4/18 15:43
* @Description: 测试Sentinel
*/
public class JedisSentinelTest {
private JedisSentinelPool pool;
@Before
public void initJedis(){
// master的名字是sentinel.conf配置文件里面的名称
String masterName = "mymaster";
Set<String> sentinels = new HashSet<String>();
sentinels.add("132.232.115.96:16380");
sentinels.add("132.232.115.96:16381");
sentinels.add("132.232.115.96:16382");
pool = new JedisSentinelPool(masterName, sentinels);
}
@Test
public void testGet(){
try {
pool.getResource().set("henry", "time:" + new Date());
System.out.println(pool.getResource().get("henry"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行 testGet()方法,结果如下:
time:Sat Apr 18 18:32:27 CST 2020
疑问
:
Jedis 连接Sentinel 的时候,我们配置的是全部哨兵的地址。Sentinel 是如何返回可用的master 地址的呢?下面我们通过分析源码,看一下Sentinel 具体实现方式。
4、源码分析
4.1 原理
1)、客户端连接到哨兵集群后,通过发送Protocol.SENTINEL_GET_MASTER_ADDR_BY_NAME
命令;
2)、从哨兵机器中询问master
节点的信息,拿到master
节点的ip
和端口号
以后,再到客户端发起连接。
3)、建立连接以后,需要在客户端建立监听机制,当master
重新选举之后,客户端需要重新连接到新的master
节点。
4.2 JedisSentinelPool构造方法
pool = new JedisSentinelPool(masterName, sentinels);
先来看下JedisSentinelPool
的构造方法:
public JedisSentinelPool(String masterName, Set<String> sentinels,
final GenericObjectPoolConfig poolConfig, final int connectionTimeout, final int soTimeout,
final String password, final int database, final String clientName,
final int sentinelConnectionTimeout, final int sentinelSoTimeout,