一、哨兵模式的蛋生
我们都知道单节点、单实例的东西一旦挂点就没救啦,所以凡事一定要多节点,一个节点挂掉,另一个节点还可以对外提供服务,这叫高可用。
一般来说,要保持高可用,启用多个实例,然后在客户端配置多个实例地址就可以了。
比如:
redis.host=127.0.0.1:6379;127.0.0.1:6380;127.0.0.1:6381
如果连接其中一个redis失败了,就尝试去连接另外一个redis。
然鹅,事实上这是不行的。
两个原因:
- redis不支持主从自动切换;
- redis仅支持 主-从,不支持 主-主,只能数据从master同步到slave;
既然Redis无法自动切换主从,所以只好让别人来做了,那就是sentinel。
所以,sentinel需要做什么事情呢?
- 监控各个redis实例是否存活;
- master断掉以后,自动选举出新的master;
- 通知其他redis:master变了;
服务器端采用多个sentinel节点来监控各个redis节点,并做主从自动切换。但是这和客户端没什么关系,所以如果客户端不对此做什么改变的话,那sentinel就形同虚设了。
现在,客户端肯定是不知道谁是master的,所以客户端肯定是不能直接连接到某个redis节点的。但是sentinel知道呀~ 所以,客户端应该连接到sentinel,由sentinel动态地告诉客户端应该连接到哪个Redis节点。
二、客户端接入Redis Sentinel
没错,客户端怎么接入sentinel呢?
我这里拿Jedis举例子。
通常,Jedis有两种接入sentinel的模式,按照业务层操作redis的直接对象,可以分为
- Jedis
- RedisTemplate
配置文件
redis.sentinel.master=mymaster
redis.sentinel.pwd=123456
redis.sentinel.nodes=10.10.101.123:26379;10.10.101.124:26380;10.10.101.125:26381
Jedis
即使用原生的Jedis来操作redis。
@Configuration
public class RedisTemplate {
@Value("${redis.sentinel.master}")
String masterName;
@Value("${redis.sentinel.pwd}")
String sentinelPwd;
@Value("${redis.sentinel.nodes}")
String sentinelNodes;
@Value("${redis.pool.maxIdle}")
int maxIdle;
@Value("${redis.pool.maxTotal}")
int maxTotal;
@Value("${redis.pool.maxWaitMillis}")
long maxWaitMillis;
@Value("${redis.pool.testOnBorrow}")
boolean testOnBorrow;
@Value("${redis.pool.minEvictableIdleTimeMillis}")
long minEvictableIdleTimeMillis;
@Bean(name = "jedisConnectionFactory")
public JedisConnectionFactory getFactory(){
JedisConnectionFactory factory = new JedisConnectionFactory(getSentinelConfig(), getPool());
factory.setPassword(sentinelPwd);
return factory;
}
@Bean(name = "jedisPoolConfig")
public JedisPoolConfig getPool(){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(maxIdle);
config.setMaxTotal(maxTotal);
config.setMaxWaitMillis(maxWaitMillis);
config.setTestOnBorrow(testOnBorrow);
config.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
return config;
}
@Bean(name = "jedisSentinelPool")
public JedisSentinelPool getJedisSentinelPool(){
Set<String> sets = Sets.newHashSet(getSentinelNodes());
JedisSentinelPool sentinelPool = new JedisSentinelPool(masterName, sets, getPool(), sentinelPwd);
return sentinelPool;
}
public List<String> getSentinelNodes(){
List<RedisNode> nodesList = Lists.newArrayList();
String[] nodes = sentinelNodes.split(";");
return Arrays.asList(nodes);
}
}
使用的时候只需这样
@Autowired
JedisSentinelPool pool;
public void test(){
String key = "key";
String value = "value";
Jedis jedis = pool.getgetResource();
jedis.set(key, value);
}
RedisTemplate
@Configuration
public class RedisTemplate {
...(忽略一部分,和上面是一样的)
@Bean(name = "stringRedisTemplate")
public StringRedisTemplate getRedisTemplate(){
StringRedisTemplate template = new StringRedisTemplate();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setDefaultSerializer(stringRedisSerializer);
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.setConnectionFactory(getFactory());
template.afterPropertiesSet();
return template;
}
}
使用的时候
@Autowired
StringRedisTemplate stringRedisTemplate;
public void test(){
String key = "key";
String value = "value";
stringRedisTemplate.template.opsForValue().set(key, value);
}
Jedis和RedisTemplate有何区别
Jedis操作完成后,需要手动调用close()释放连接;RedisTemplate不需要用户手动释放连接;
我们到 RedisConnectionUtils
查看一下execute方法会发现,每次RedisTemplate执行一个操作以后都会releaseConnection
。
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
...
try {
...
// TODO: any other connection processing?
return postProcessResult(result, connToUse, existingConnection);
} finally {
RedisConnectionUtils.releaseConnection(conn, factory);
}
}
继续查看一下releaseConnection()
public static void releaseConnection(RedisConnection conn, RedisConnectionFactory factory) {
...
if (connHolder != null && connHolder.isTransactionSyncronisationActive()) {
if (log.isDebugEnabled()) {
log.debug("Redis Connection will be closed when transaction finished.");
}
return;
}
// release transactional/read-only and non-transactional/non-bound connections.
// transactional connections for read-only transactions get no synchronizer registered
if (isConnectionTransactional(conn, factory)
&& TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
unbindConnection(factory);
} else if (!isConnectionTransactional(conn, factory)) {
if (log.isDebugEnabled()) {
log.debug("Closing Redis Connection");
}
conn.close();
}
}
可以看到,如果不是处于一个transactional事务,操作完成后,connection直接就close()了。
Jedis采用原生Jedis接口操作数据,redisTemplate则为不同客户端提供了统一的操作模板;
使用redisTemplate以后,如果切换为别的redis客户端,修改的成本比较低。
有人经过测试反映说redis是原生接口,效率比redisTemplate高一些。
三、How Redis Sentinel Work?
我们需要通过一些简单的场景来观察这个过程。在接下来的时间里,我们尝试去模拟可能发生的5种场景。
0. 环境
先来看下试验的环境:
145、146、147 三台服务器,都安装和运行了Redis和Sentinel。其中,146的redis为master,145/147的redis为slave。
如下图所示:
1. sentinel正常,关闭master
停止master服务
redis-cli -h 127.0.0.1 -p 6379 shutdown
先看一下最终的结果,最终的状态是这样子的
我们发现:
- 原146的redis(master)变成slave;
- 145变成了master;
- 147 slaveof 145;
然后我们观察根据三台Sentinel的日志,看一下sentinel是如何进行failover的(为了方便,我们把sentinel简写为S,Redis简写为R):
(ps:三台Sentinel的日志放在 附录1 噢)
-
146的S 首先发现发现146的R下线了(
+sdown
:subject down,主观下线)+sdown master mymaster 10.10.101.146 6379
-
达到指定人数(quorum),认同故障已发生,146的S将146的R标记为已下线(
+odown
:object down,客观下线)
+odown master mymaster 10.10.101.146 6379 #quorum 2/2
-
146的S尝试进行故障转移
+try-failover master mymaster 10.10.101.146 6379
-
146的S发起投票,选举新的S Leader
+vote-for-leader 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
-
145/147回应选举。
+vote-for-leader 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
-
146统计选举结果:146赢得选举,成为Leader
+elected-leader master mymaster 10.10.101.146 6379
-
146的S将145R选为新Master,并发送相关指令
7349:X 10 Dec 17:23:47.431 # +failover-state-select-slave master mymaster 10.10.101.146 6379 (尝试寻找一个slave来提升为master) 7349:X 10 Dec 17:23:47.561 # +selected-slave slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379 (将一个slave提升为master) 7349:X 10 Dec 17:23:47.561 * +failover-state-send-slaveof-noone slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379 (向145发送slaveofOnOne指令) 7349:X 10 Dec 17:23:47.627 * +failover-state-wait-promotion slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379 (等待145的回应) 7349:X 10 Dec 17:23:48.228 # +promoted-slave slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379 (成功将145提升为master) 7349:X 10 Dec 17:23:48.228 # +failover-state-reconf-slaves master mymaster 10.10.101.146 6379 (修改配置)
-
145、146 的S 收到Leader(146 S)的通知,将master切换为145R
21880:X 10 Dec 17:23:48.285 # +config-update-from sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.146 6379
21880:X 10 Dec 17:23:48.286 # +switch-master mymaster 10.10.101.146 6379 10.10.101.145 6379
-
145、146、147的S侦测到slave(147R、146R,注意,146R此时仍然被当做一个slave)
7349:X 10 Dec 17:23:49.338 * +slave slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.145 6379 7349:X 10 Dec 17:23:49.340 * +slave slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
-
将146R客观下线(我们发现,对于slave并没有执行客观下线
+odown
,也就是说:客观下线只适用于主服务器, 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商 。
7349:X 10 Dec 17:24:19.364 # +sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
用泳道图来描述,大概是这样子的
2. 重启down掉的master
原146R挂掉的时候,已经将145R提升了master,将146R退为slave,并标记为+down
。
重启146R
redis-server ./redis.conf
145S
2622:X 12 Dec 18:09:17.303 # -sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
2622:X 12 Dec 18:09:27.268 * +convert-to-slave slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
147S
21880:X 12 Dec 18:09:17.287 # -sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
可以发现,一个slave的复活,只有一个-sdown
。
3. 关闭一个slave
我们现在shutdown掉146的 R
redis-cli -h 127.0.0.1 -p 6379 shutdown
145、147S
2622:X 12 Dec 18:24:27.177 # +sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
可以发现,slave down掉的时候S们并不需要协商,无须odown。
4. master正常,关闭一个Sentinel
执行以下指令
redis-cli -h 127.0.0.1 -p 26380 -a 123 shutdown
147 S 日志
21880:X 12 Dec 12:08:59.394 # +sdown sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.145 6379
145 S 日志
2622:X 12 Dec 12:08:59.458 # +sdown sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.145 6379
5. 重启down掉的sentinel
重新启动146的sentinel
redis-sentinel ./sentinel-26380.conf
145S
2622:X 12 Dec 18:12:43.730 * -dup-sentinel master mymaster 10.10.101.145 6379 #duplicate of 10.10.101.146:26380 or 99efa85df21767e8ee4a15a1894d01094bfd2ddb
2622:X 12 Dec 18:12:43.730 * +sentinel sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.145 6379
147 S
21880:X 12 Dec 18:12:43.731 * -dup-sentinel master mymaster 10.10.101.145 6379 #duplicate of 10.10.101.146:26380 or 99efa85df21767e8ee4a15a1894d01094bfd2ddb
21880:X 12 Dec 18:12:43.731 * +sentinel sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.145 6379
已挂掉的S重启,会提示-dup-sentinel,因为配置文件并不会把挂掉的配置移除,只是标记为+down
。
6. 结论
- Redis下线分为主观下线(sdown)、客观下线(odown);
- 当sentinel单位时间内监听不到slave的消息时,就会主观下线;监听不到master的消息时,先主观下线,然后由各个Sentinel协商,达到指定数量的Sentinel认定master下线,即可标记master客观下线;
- 客观下线只适用于主服务器, 对于slave, Sentinel 在将它们判断为下线前不需要进行协商 。
- redis master下线需要经过主观下线、协商、客观下线、选举Sentinel Leader、Leader发起投票、Leader指挥failover等过程;
- master挂掉的时候,选举出新的master后,会把旧的master降级为slave,并标记主观下线(+sdwon);
- 某个master/slave挂掉的时候,sentinel并不会将他们的信息移除,只是会标记为主观下线(+sdown),若该Redis实例重新上线的时候,将直接(-sdown)。
7. 小小的猜测
为什么slave down的时候,不需要客观下线呢?
我们知道,sentinel的数据是不分片的,只是冗余了几个slave。一般情况下,我们也不会在sentinel模式下对Redis做读写分离。每次需要操作Redis,从Sentinel中获取的实例都是Redis master节点。只要保证master是可用的,就一定不会有问题,所以也就不需要耗费时间去验证slave协商slave是否真的挂掉了。
附录1
145日志
[apps@mvxl8195 redis-3.0.0]$ tail -f 26379.log
2622:X 21 Oct 07:12:21.028 # +sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:12:21.225 # -sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:43:28.463 # +sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:43:29.742 # -sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:48:44.978 # +sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:48:48.272 # -sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:53:04.249 # +sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 07:53:04.332 # -sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 08:33:29.834 # +sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
2622:X 21 Oct 08:33:36.789 # -sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
2622:X 10 Dec 17:23:47.228 # +sdown master mymaster 10.10.101.146 6379
2622:X 10 Dec 17:23:47.394 # +new-epoch 2
2622:X 10 Dec 17:23:47.395 # +vote-for-leader 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
2622:X 10 Dec 17:23:48.286 # +config-update-from sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.146 6379
2622:X 10 Dec 17:23:48.286 # +switch-master mymaster 10.10.101.146 6379 10.10.101.145 6379
2622:X 10 Dec 17:23:48.287 * +slave slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.145 6379
2622:X 10 Dec 17:23:48.288 * +slave slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
2622:X 10 Dec 17:24:18.362 # +sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
147日志
21880:X 21 Oct 05:15:22.731 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:15:35.515 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:33:42.970 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:34:14.079 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:35:40.013 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:36:11.227 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:38:16.866 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:38:18.895 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:54:08.848 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:55:07.052 # -sdown master mymaster 10.10.101.146 6
[apps@mvxl8197 redis-3.0.0]$ tail -f 26381.log
21880:X 21 Oct 05:15:22.731 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:15:35.515 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:33:42.970 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:34:14.079 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:35:40.013 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:36:11.227 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:38:16.866 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:38:18.895 # -sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:54:08.848 # +sdown master mymaster 10.10.101.146 6
21880:X 21 Oct 05:55:07.052 # -sdown master mymaster 10.10.101.146 6
^C
[apps@mvxl8197 redis-3.0.0]$ tail -f 26381.log
21880:X 21 Oct 05:15:22.731 # +sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:15:35.515 # -sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:33:42.970 # +sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:34:14.079 # -sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:35:40.013 # +sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:36:11.227 # -sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:38:16.866 # +sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:38:18.895 # -sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:54:08.848 # +sdown master mymaster 10.10.101.146 6379
21880:X 21 Oct 05:55:07.052 # -sdown master mymaster 10.10.101.146 6379
21880:X 10 Dec 17:23:47.381 # +new-epoch 2
21880:X 10 Dec 17:23:47.397 # +vote-for-leader 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
21880:X 10 Dec 17:23:48.285 # +config-update-from sentinel 10.10.101.146:26380 10.10.101.146 26380 @ mymaster 10.10.101.146 6379
21880:X 10 Dec 17:23:48.286 # +switch-master mymaster 10.10.101.146 6379 10.10.101.145 6379
21880:X 10 Dec 17:23:48.286 * +slave slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.145 6379
21880:X 10 Dec 17:23:48.287 * +slave slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
21880:X 10 Dec 17:24:18.319 # +sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
146日志
7349:X 21 Oct 07:22:42.935 # +sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:22:43.037 # -sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:26:09.603 # +sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:26:09.979 # -sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:37:29.928 # +sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:37:31.268 # -sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:52:11.764 # +sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 07:52:27.137 # -sdown sentinel 10.10.101.147:26381 10.10.101.147 26381 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 08:51:55.420 # +sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 21 Oct 08:51:56.738 # -sdown slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.243 # +sdown master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.363 # +odown master mymaster 10.10.101.146 6379 #quorum 2/2
7349:X 10 Dec 17:23:47.363 # +new-epoch 2
7349:X 10 Dec 17:23:47.363 # +try-failover master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.368 # +vote-for-leader 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
7349:X 10 Dec 17:23:47.393 # 10.10.101.145:26379 voted for 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
7349:X 10 Dec 17:23:47.397 # 10.10.101.147:26381 voted for 22c7af0b9b4bdfbb79337ec9d46a90f925a2f308 2
7349:X 10 Dec 17:23:47.431 # +elected-leader master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.431 # +failover-state-select-slave master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.561 # +selected-slave slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.561 * +failover-state-send-slaveof-noone slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:47.627 * +failover-state-wait-promotion slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:48.228 # +promoted-slave slave 10.10.101.145:6379 10.10.101.145 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:48.228 # +failover-state-reconf-slaves master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:48.284 * +slave-reconf-sent slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:48.536 # -odown master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:49.239 * +slave-reconf-inprog slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:49.239 * +slave-reconf-done slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:49.338 # +failover-end master mymaster 10.10.101.146 6379
7349:X 10 Dec 17:23:49.338 # +switch-master mymaster 10.10.101.146 6379 10.10.101.145 6379
7349:X 10 Dec 17:23:49.338 * +slave slave 10.10.101.147:6379 10.10.101.147 6379 @ mymaster 10.10.101.145 6379
7349:X 10 Dec 17:23:49.340 * +slave slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
7349:X 10 Dec 17:24:19.364 # +sdown slave 10.10.101.146:6379 10.10.101.146 6379 @ mymaster 10.10.101.145 6379
Redis常用指令
redis-cli登录
redis-cli -h 主机 -p 端口号 -a 密码
启动redis-server
redis-server path(配置文件路径)
停止redis-server
redis-cli -h 主机 -p 端口号 -a 密码 shutdown
redis-cli下的指令
info #查看redis相关信息
dbsize #查看当前库中总数据条数
client list #查看已连接的客户端信息