1
![img_742264da5503e67c0b21b64921eec70c.png](https://yqfile.alicdn.com/img_742264da5503e67c0b21b64921eec70c.png?x-oss-process=image/resize,w_1400/format,webp)
目录
2 主从复制高可用?
![img_dcbb957c8941905492e901a137b3775a.png](https://yqfile.alicdn.com/img_dcbb957c8941905492e901a137b3775a.png?x-oss-process=image/resize,w_1400/format,webp)
![img_a1fc6ca9fa028b53537930ba1d79c1fa.png](https://yqfile.alicdn.com/img_a1fc6ca9fa028b53537930ba1d79c1fa.png?x-oss-process=image/resize,w_1400/format,webp)
故障出现主节点挂掉
![img_bd08b548c11f99d8bbf02cc7686da60e.png](https://yqfile.alicdn.com/img_bd08b548c11f99d8bbf02cc7686da60e.png?x-oss-process=image/resize,w_1400/format,webp)
主从复制-mster宕掉故障处理
3 Redis Sentinel 架构
![img_bdf184e6de0cfa55bb5da150049033eb.png](https://yqfile.alicdn.com/img_bdf184e6de0cfa55bb5da150049033eb.png?x-oss-process=image/resize,w_1400/format,webp)
![img_e0b200c272a4acabc6788752f84f0e0c.png](https://yqfile.alicdn.com/img_e0b200c272a4acabc6788752f84f0e0c.png?x-oss-process=image/resize,w_1400/format,webp)
![img_9fde9e8f4c736b7dbc0d1d59159020d8.png](https://yqfile.alicdn.com/img_9fde9e8f4c736b7dbc0d1d59159020d8.png?x-oss-process=image/resize,w_1400/format,webp)
可监控多套
4 安装与配置
![img_694148219e4fb69b24754d8ab889e60b.png](https://yqfile.alicdn.com/img_694148219e4fb69b24754d8ab889e60b.png?x-oss-process=image/resize,w_1400/format,webp)
安装与配置
![img_c33df64e4b278a1a6713d2a3e866ef23.png](https://yqfile.alicdn.com/img_c33df64e4b278a1a6713d2a3e866ef23.png?x-oss-process=image/resize,w_1400/format,webp)
![img_2565f19586f554db1f8918e08af41f1f.png](https://yqfile.alicdn.com/img_2565f19586f554db1f8918e08af41f1f.png?x-oss-process=image/resize,w_1400/format,webp)
Redis 主节点
![img_f030e6f7899366e5d9748a0614df1aff.png](https://yqfile.alicdn.com/img_f030e6f7899366e5d9748a0614df1aff.png?x-oss-process=image/resize,w_1400/format,webp)
Redis 从节点
![img_f2d03ee89f5e2aba62ce9ae516de5327.png](https://yqfile.alicdn.com/img_f2d03ee89f5e2aba62ce9ae516de5327.png?x-oss-process=image/resize,w_1400/format,webp)
Sentinel 主要配置
5 安装与演示
![img_ce79f2574c103be96714034e7a6a1ec6.png](https://yqfile.alicdn.com/img_ce79f2574c103be96714034e7a6a1ec6.png?x-oss-process=image/resize,w_1400/format,webp)
![img_1591a8673bd2bce39fc038834167c648.png](https://yqfile.alicdn.com/img_1591a8673bd2bce39fc038834167c648.png?x-oss-process=image/resize,w_1400/format,webp)
主节点配置
![img_6945df7b66c866c0ee00b33802c62aa0.png](https://yqfile.alicdn.com/img_6945df7b66c866c0ee00b33802c62aa0.png?x-oss-process=image/resize,w_1400/format,webp)
快速生成从节点配置文件
![img_8297b8e624b9667ff1b4e8a1ac10c355.png](https://yqfile.alicdn.com/img_8297b8e624b9667ff1b4e8a1ac10c355.png?x-oss-process=image/resize,w_1400/format,webp)
重定向
![img_34c9230872797ce7ca10be46bede3156.png](https://yqfile.alicdn.com/img_34c9230872797ce7ca10be46bede3156.png?x-oss-process=image/resize,w_1400/format,webp)
打印检查配置文件
![img_7ded2bb8d063348f46cf0d1da345a640.png](https://yqfile.alicdn.com/img_7ded2bb8d063348f46cf0d1da345a640.png?x-oss-process=image/resize,w_1400/format,webp)
启动
6 客户端
![img_ede75704ba8fe40f36dd8b9560588a3f.png](https://yqfile.alicdn.com/img_ede75704ba8fe40f36dd8b9560588a3f.png?x-oss-process=image/resize,w_1400/format,webp)
客户端
![img_f3d54a69b76dd8d4dd806f5e58202ef3.png](https://yqfile.alicdn.com/img_f3d54a69b76dd8d4dd806f5e58202ef3.png?x-oss-process=image/resize,w_1400/format,webp)
直连?
![img_cf287f79c0991ec83d546a87a434f6e9.png](https://yqfile.alicdn.com/img_cf287f79c0991ec83d546a87a434f6e9.png?x-oss-process=image/resize,w_1400/format,webp)
客户端实现基本原理-1
![img_94aa602a5ec8929180a7e5c8a89fbd49.png](https://yqfile.alicdn.com/img_94aa602a5ec8929180a7e5c8a89fbd49.png?x-oss-process=image/resize,w_1400/format,webp)
客户端实现基本原理-2
![img_3c4d6cc87345b0ae58bff8e717a4c9a0.png](https://yqfile.alicdn.com/img_3c4d6cc87345b0ae58bff8e717a4c9a0.png?x-oss-process=image/resize,w_1400/format,webp)
客户端实现基本原理-3 验证
![img_5ea744f7ec6b56060241a309a916e28c.png](https://yqfile.alicdn.com/img_5ea744f7ec6b56060241a309a916e28c.png?x-oss-process=image/resize,w_1400/format,webp)
客户端实现基本原理-4 通知(发布订阅))
![img_bdd90002120a4b99dc892b5dd44fca14.png](https://yqfile.alicdn.com/img_bdd90002120a4b99dc892b5dd44fca14.png?x-oss-process=image/resize,w_1400/format,webp)
![img_672c298837e9b8859a94eafbb0cfd7ed.png](https://yqfile.alicdn.com/img_672c298837e9b8859a94eafbb0cfd7ed.png?x-oss-process=image/resize,w_1400/format,webp)
客户端接入流程
![img_4fabc34675efa18dd881ad8719a679ae.png](https://yqfile.alicdn.com/img_4fabc34675efa18dd881ad8719a679ae.png?x-oss-process=image/resize,w_1400/format,webp)
Jedis
11 三个定时任务
![img_60f207d3869019f248ba042aab43680b.png](https://yqfile.alicdn.com/img_60f207d3869019f248ba042aab43680b.png?x-oss-process=image/resize,w_1400/format,webp)
三个定时任务
![img_0ef29445096e6b1d9a4266c8b8e651f6.png](https://yqfile.alicdn.com/img_0ef29445096e6b1d9a4266c8b8e651f6.png?x-oss-process=image/resize,w_1400/format,webp)
每 10s info
![img_738c312813b75327f7119c3701a16c81.png](https://yqfile.alicdn.com/img_738c312813b75327f7119c3701a16c81.png?x-oss-process=image/resize,w_1400/format,webp)
第2个监控任务,每 2s 发布订阅
![img_b45be99c4f5a88ccdd41ba9cd947eec2.png](https://yqfile.alicdn.com/img_b45be99c4f5a88ccdd41ba9cd947eec2.png?x-oss-process=image/resize,w_1400/format,webp)
第3个监控任务,每 1s PING
12 主观下线和客观下线
![img_35731bd2779d5ece19c52b9da880ed2a.png](https://yqfile.alicdn.com/img_35731bd2779d5ece19c52b9da880ed2a.png?x-oss-process=image/resize,w_1400/format,webp)
主观下线和客观下线
13 领导者选举
![img_2eec950258b9d0fa273faf1097d2b114.png](https://yqfile.alicdn.com/img_2eec950258b9d0fa273faf1097d2b114.png?x-oss-process=image/resize,w_1400/format,webp)
领导者选举
![img_db4ea40558a8ea8bd57c9feafeefb551.png](https://yqfile.alicdn.com/img_db4ea40558a8ea8bd57c9feafeefb551.png?x-oss-process=image/resize,w_1400/format,webp)
选举实例
14 故障转移
![img_1619ba802e5764c29eea14257f42d926.png](https://yqfile.alicdn.com/img_1619ba802e5764c29eea14257f42d926.png?x-oss-process=image/resize,w_1400/format,webp)
领导者节点完成
![img_301f05e6951cbd11c4c86b2e78739c11.png](https://yqfile.alicdn.com/img_301f05e6951cbd11c4c86b2e78739c11.png?x-oss-process=image/resize,w_1400/format,webp)
选择合适的slave节点
15 常见开发运维问题-目录
![img_4a0cdf1eddfba57b614f9405d9fe65c7.png](https://yqfile.alicdn.com/img_4a0cdf1eddfba57b614f9405d9fe65c7.png?x-oss-process=image/resize,w_1400/format,webp)
16 节点运维
![img_dbe52be66d165d69694773696238f84f.png](https://yqfile.alicdn.com/img_dbe52be66d165d69694773696238f84f.png?x-oss-process=image/resize,w_1400/format,webp)
![img_a736dda638752247d04960660007812a.png](https://yqfile.alicdn.com/img_a736dda638752247d04960660007812a.png?x-oss-process=image/resize,w_1400/format,webp)
主节点
![img_2318618d0f03fee74428549e39335e05.png](https://yqfile.alicdn.com/img_2318618d0f03fee74428549e39335e05.png?x-oss-process=image/resize,w_1400/format,webp)
节点下线
![img_c39bd76a2bd531b0cf83d3d7e6091a97.png](https://yqfile.alicdn.com/img_c39bd76a2bd531b0cf83d3d7e6091a97.png?x-oss-process=image/resize,w_1400/format,webp)
节点上线
17 高可用的读写分离
看一下JedisSentinelPool
的实现
![img_2139ae53ccd12b5c5b51b96914ede49b.png](https://yqfile.alicdn.com/img_2139ae53ccd12b5c5b51b96914ede49b.png?x-oss-process=image/resize,w_1400/format,webp)
![img_68971df81d79e0035ae7388a28a159dd.png](https://yqfile.alicdn.com/img_68971df81d79e0035ae7388a28a159dd.png?x-oss-process=image/resize,w_1400/format,webp)
![img_cd7d86f47ee381f2e815c0427a0f13c5.png](https://yqfile.alicdn.com/img_cd7d86f47ee381f2e815c0427a0f13c5.png?x-oss-process=image/resize,w_1400/format,webp)
![img_ef522f0e3e5f4578969a1c0fe257a84f.png](https://yqfile.alicdn.com/img_ef522f0e3e5f4578969a1c0fe257a84f.png?x-oss-process=image/resize,w_1400/format,webp)
private HostAndPort initSentinels(Set<String> sentinels, final String masterName) {
HostAndPort master = null;
boolean sentinelAvailable = false;
log.info("Trying to find master from available Sentinels...");
// 遍历所有 Sentinel 节点
for (String sentinel : sentinels) {
final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(":")));
log.fine("Connecting to Sentinel " + hap);
Jedis jedis = null;
try {
// 找到一个可运行的,并用jedis连接上去
jedis = new Jedis(hap.getHost(), hap.getPort());
// 通过 mastername 区分 sentinel 节点,得到其地址
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) {
// resolves #1036, it should handle JedisException there's another chance
// of raising JedisDataException
log.warning("Cannot get master address from sentinel running @ " + hap + ". Reason: " + e
+ ". Trying next one.");
} finally {
if (jedis != null) {
jedis.close();
}
}
}
//无可用节点,抛异常
if (master == null) {
if (sentinelAvailable) {
// can connect to sentinel, but master name seems to not
// monitored
throw new JedisException("Can connect to sentinel, but " + masterName
+ " seems to be not monitored...");
} else {
throw new JedisConnectionException("All sentinels down, cannot determine where is "
+ masterName + " master is running...");
}
}
log.info("Redis master running at " + master + ", starting Sentinel listeners...");
//当拿到master节点后,所要做的就是订阅那个消息,客户端只需订阅该频道即可
for (String sentinel : sentinels) {
final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel.split(":")));
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();
}
以下为监听线程类
protected class MasterListener extends Thread {
protected String masterName;
protected String host;
protected int port;
protected long subscribeRetryWaitTimeMillis = 5000;
protected volatile Jedis j;
protected AtomicBoolean running = new AtomicBoolean(false);
protected MasterListener() {
}
public MasterListener(String masterName, String host, int port) {
super(String.format("MasterListener-%s-[%s:%d]", masterName, host, port));
this.masterName = masterName;
this.host = host;
this.port = port;
}
public MasterListener(String masterName, String host, int port,
long subscribeRetryWaitTimeMillis) {
this(masterName, host, port);
this.subscribeRetryWaitTimeMillis = subscribeRetryWaitTimeMillis;
}
@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: " + message);
}
}
}, "+switch-master");
} catch (JedisConnectionException e) {
if (running.get()) {
log.log(Level.SEVERE, "Lost connection to Sentinel at " + host + ":" + port
+ ". Sleeping 5000ms and retrying.", e);
try {
Thread.sleep(subscribeRetryWaitTimeMillis);
} catch (InterruptedException e1) {
log.log(Level.SEVERE, "Sleep interrupted: ", e1);
}
} else {
log.fine("Unsubscribing from Sentinel at " + host + ":" + port);
}
} finally {
j.close();
}
}
}
public void shutdown() {
try {
log.fine("Shutting down listener on " + host + ":" + port);
running.set(false);
// This isn't good, the Jedis object is not thread safe
if (j != null) {
j.disconnect();
}
} catch (Exception e) {
log.log(Level.SEVERE, "Caught exception while shutting down: ", e);
}
}
}
![img_399af9258990e13b25a40b207116e291.png](https://yqfile.alicdn.com/img_399af9258990e13b25a40b207116e291.png?x-oss-process=image/resize,w_1400/format,webp)
感知到主从切换时,接收消息并重新初始化连接池
![img_a90f4a247bb5fe61a9fc355160ef3aa6.png](https://yqfile.alicdn.com/img_a90f4a247bb5fe61a9fc355160ef3aa6.png?x-oss-process=image/resize,w_1400/format,webp)
![img_f054fa5438fe8178cc05548c89df0162.png](https://yqfile.alicdn.com/img_f054fa5438fe8178cc05548c89df0162.png?x-oss-process=image/resize,w_1400/format,webp)
从节点的作用
由于Redis Sentinel只会对主节点进行故障转移,对从节点采取主观的下线,所以需要自定义一个客户端来监控对应的事件
![img_28b34d21e1b75dd8d615578644e882ef.png](https://yqfile.alicdn.com/img_28b34d21e1b75dd8d615578644e882ef.png?x-oss-process=image/resize,w_1400/format,webp)
三个消息
![img_b735c55edada8f7255d4a4c855091a84.png](https://yqfile.alicdn.com/img_b735c55edada8f7255d4a4c855091a84.png?x-oss-process=image/resize,w_1400/format,webp)
高可用读写分离
18 总结
![img_6ec3d52ffd585ba06a3e5260f11edbcf.png](https://yqfile.alicdn.com/img_6ec3d52ffd585ba06a3e5260f11edbcf.png?x-oss-process=image/resize,w_1400/format,webp)
![img_9e1e7f686cfbfd2d0bb513c7cd4d2569.png](https://yqfile.alicdn.com/img_9e1e7f686cfbfd2d0bb513c7cd4d2569.png?x-oss-process=image/resize,w_1400/format,webp)
![img_f92acdf0db9d59465b2753946b2899b0.png](https://yqfile.alicdn.com/img_f92acdf0db9d59465b2753946b2899b0.png?x-oss-process=image/resize,w_1400/format,webp)