spring-boot-redis-starter源码分析
文章目录
RedisAutoConfiguration自动配置类,redis链接工厂以及哨兵等监听
- RedisAutoConfiguration里面主要做JedisConnectionFactory的装配工作:
根据配置的sentinel或者cluster进行不同的装配,加载配置等。
@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
public JedisConnectionFactory redisConnectionFactory()
throws UnknownHostException {
return applyProperties(createJedisConnectionFactory());
}
- JedisConnectionFactory实现了InitializingBean,在装载Bean之后调用afterPropertiesSet方法进行池JedisSentinelPool的创建
public void afterPropertiesSet() {
if (shardInfo == null) {
shardInfo = new JedisShardInfo(hostName, port);
if (StringUtils.hasLength(password)) {
shardInfo.setPassword(password);
}
if (timeout > 0) {
setTimeoutOn(shardInfo, timeout);
}
}
if (usePool && clusterConfig == null) {
this.pool = createPool();
}
if (clusterConfig != null) {
this.cluster = createCluster();
}
}
这里主要是pool的创建,pool中主要存储的是Jedis对象,主要执行Jedis的管理工作,为后续连接的租借、归还进行一定的处理.
- JedisSentinelPool中首先initSentinels会根据sentinel的配置获取到主master节点的信息,遍历每个sentinel节点执行
sentinel get-master-addr-by-name mymaster
命令获取master(其中一个返回master即可)
for (String sentinel : sentinels) {
final HostAndPort hap = HostAndPort.parseString(sentinel);
log.fine("Connecting to Sentinel " + hap);
Jedis jedis = null;
try {
jedis = new Jedis(hap.getHost(), hap.getPort());
List<String> masterAddr = jedis.sentinelGetMasterAddrByName(masterName);
// connected to sentinel...
sentinelAvailable = true;
if (masterAddr == null || masterAddr.size() != 2) {
log.warning("Can not get master addr, master name: " + masterName + ". Sentinel: " + hap
+ ".");
continue;
}
master = toHostAndPort(masterAddr);
log.fine("Found Redis master at " + master);
break;
} catch (JedisException e) {
log.warning("Cannot get master address from sentinel running @ " + hap + ". Reason: " + e
+ ". Trying next one.");
} finally {
if (jedis != null) {
jedis.close();
}
}
}
- 开启一个Daemon后台线程订阅+switch-master的消息,当master切换后收到sentinel发送的切换通知重新初始化连接pool。
for (String sentinel : sentinels) {
final HostAndPort hap = HostAndPort.parseString(sentinel);
MasterListener masterListener = new MasterListener(masterName, hap.getHost(), hap.getPort());
// whether MasterListener threads are alive or not, process can be stopped
masterListener.setDaemon(true);
masterListeners.add(masterListener);
masterListener.start();
}
- MasterListener的作用就是对每个哨兵进行订阅消息,当收到通知后改变currentHostMaster,进行切换
MasterListener
@Override
public void run() {
running.set(true);
while (running.get()) {
j = new Jedis(host, port);
try {
// double check that it is not being shutdown
if (!running.get()) {
break;
}
j.subscribe(new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
log.fine("Sentinel " + host + ":" + port + " published: " + message + ".");
String[] switchMasterMsg = message.split(" ");
if (switchMasterMsg.length > 3) {
if (masterName.equals(switchMasterMsg[0])) {
initPool(toHostAndPort(Arrays.asList(switchMasterMsg[3], switchMasterMsg[4])));
} else {
log.fine("Ignoring message on +switch-master for master name "
+ switchMasterMsg[0] + ", our master name is " + masterName);
}
} else {
log.severe("Invalid message received on Sentinel " + host + ":" + port
+ " on channel +switch-master: "