Redis 哨兵(sentinel)模式:实现对主从复制架构自动切换主从服务器。普通的主从复制机制,主机宕机后就无法使用了,启动了哨兵模式,系统可以自动在从机中选出一台充当主机的角色。
下载redis,我使用的是redis-2.8.3.tar.gz,解压后redis-2.8.3, make编译后,就可以使用了。把src目录下的redis-server复制到 redis.conf同级目录。需要绑定redis ip,否则外部机子可能无法访问。修改redis.conf 添加bind 192.168.254.129Ip是我的虚拟机的ip。再把redis-2.8.3,复制2份得到redis-6380,redis-6381.现在有三台redis服务了。
选择redis-2.8.3充当复制结构的主机,启动./redis-server redis.conf 。
主机启动后,切换到redi-6380端口下,修改配置redis.conf,修改端口
port 6381, 添加 slaveof 192.168.254.1296379 ,这个配置指定主机。修改完后启动第一个从机 ./redis-serverredis.conf 可以看到启动日志:[13199] 19 Mar 06:59:07.535 * Connecting to MASTER192.168.254.129:6379
[13199] 19 Mar 06:59:07.535 * MASTER<-> SLAVE sync started
[13199] 19 Mar 06:59:07.535 * Non blockingconnect for SYNC fired the event.
[13199] 19 Mar 06:59:07.535 * Masterreplied to PING, replication can continue...
[13199] 19 Mar 06:59:07.535 * Partialresynchronization not possible (no cached master)
[13199] 19 Mar 06:59:07.535 * Full resyncfrom master: 0065f20abd7effc9eb7879813af1f2afaba443cb:1
[13199] 19 Mar 06:59:07.635 * MASTER<-> SLAVE sync: receiving 40 bytes from master
[13199] 19 Mar 06:59:07.635 * MASTER<-> SLAVE sync: Flushing old data
[13199] 19 Mar 06:59:07.635 * MASTER<-> SLAVE sync: Loading DB in memory
[13199] 19 Mar 06:59:07.635 * MASTER<-> SLAVE sync: Finished with success
说明作为6379的从机启动的,启动成功。
6380端口上的从机启动后,对redis-6381做类似配置修改端口port 6381,添加主机slaveof 192.168.254.1296379 ,启动。
这样就完成了复制结构的启动:主机redis-2.8.3 从机redis-6380 redis-6381,一主2从。
主机可以写入和读取,从机只读,可以测试。
连接主机:./redis-cli -p 6379 -h 192.168.254.129
执行:info replication
输出:
[root@localhost redis-6381]# ./redis-cli -p6379 -h 192.168.254.129
192.168.254.129:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.254.129,port=6380,state=online,offset=295,lag=0
slave1:ip=192.168.254.129,port=6381,state=online,offset=295,lag=0
master_repl_offset:295
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:294
说明复制结构搭建成功。
在复制模式基础上做如下配置
redis-2.8.3(主机) 修改sentinel.conf,这个使用默认端口26379,添加配置sentinel monitor mymaster 192.168.254.129 6379 2 指定主机,后面数字2表示有2台机子检测到主机故障就自动切换主从(1不可以)。启动哨兵./redis-server sentinel.conf –sentinel
redis-6380(从机) 修改sentinel.conf,修改端口 port36379,添加配置sentinel monitor mymaster 192.168.254.129 6379 2.启动哨兵 ./redis-server sentinel.conf –sentinel
redis-6381(从机) 修改sentinel.conf,修改端口 port 46379,添加配置sentinelmonitor mymaster 192.168.254.129 6379 2.启动哨兵 ./redis-server sentinel.conf –sentinel
至此哨兵模式主从复制机制启动完毕。
使用java测试:
哨兵模式和单机模式接口配置不同,sentinel模式Pool
packagecn.tootoo.kzh.utile.redis;
importjava.util.HashSet;
importjava.util.Set;
importredis.clients.jedis.Jedis;
importredis.clients.jedis.JedisPoolConfig;
importredis.clients.jedis.JedisSentinelPool;
importredis.clients.util.Pool;
publicclass T1 {
publicstaticvoid main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.valueOf(350));
config.setMaxIdle(Integer.valueOf(100));
config.setMinIdle(Integer.valueOf(100));
config.setMaxWaitMillis(-1);
config.setMinEvictableIdleTimeMillis(60000);
config.setTimeBetweenEvictionRunsMillis(30000);
config.setBlockWhenExhausted(true);
config.setJmxEnabled(false);
config.setTestOnBorrow(true);
Set
ips.add("192.168.254.129:26379"); //哨兵配置ip和端口(不是redis服务的端口,是哨兵的端口)
ips.add("192.168.254.129:36379");
ips.add("192.168.254.129:46379");
Pool
Object res=null;
Jedis jedis=null;
String key="a1";
try {
jedis = jedisPool.getResource();
byte[] b = jedis.get(key.getBytes());
if (b != null && b.length != -1) {
res= ObjectsTranscoder.getInstance().deserialize(b);
System.out.println(res);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null){
jedis.close();
jedisPool.destroy();
}
}
}
}
输出日志:
三月 19, 2018 2:48:22 下午 redis.clients.jedis.JedisSentinelPool initSentinels
INFO:Trying to find master from available Sentinels...
三月 19, 2018 2:48:22 下午 redis.clients.jedis.JedisSentinelPool initSentinels
INFO:Redis master running at 192.168.254.129:6379, starting Sentinel listeners...
三月 19, 2018 2:48:22 下午 redis.clients.jedis.JedisSentinelPool initPool
INFO:Created JedisPool to master at 192.168.254.129:6379
123
可以看到在192.168.254.129:6379主机上进行的查询。
[root@localhost ~]# ps -ef|grep redis
root 15478 13498 0 07:39 pts/0 00:00:00 ./redis-server 192.168.254.129:6379
root 15533 15514 0 07:40 pts/1 00:00:00 ./redis-server192.168.254.129:6380
root 15584 15566 0 07:41 pts/2 00:00:00 ./redis-server192.168.254.129:6381
root 15634 15617 0 07:43 pts/3 00:00:00 ./redis-server *:26379
root 15687 15669 0 07:46 pts/4 00:00:00 ./redis-server *:36379
root 15736 15720 0 07:47 pts/5 00:00:00 ./redis-server *:46379
root 15785 15769 0 07:49 pts/6 00:00:00 grep redis
现在启动了三个redis进行和三个哨兵进程,主从结构的主机pid是15478 ,关掉主机
我们看到6380和6381上的哨兵输出日志:
[17660] 19 Mar 08:16:49.364 #+switch-master mymaster 192.168.254.129 6379 192.168.254.129 6380
[17660] 19 Mar 08:16:49.364 * +slave slave192.168.254.129:6381 192.168.254.129 6381 @ mymaster 192.168.254.129 6380
[17660] 19 Mar 08:16:49.407 * +slave slave192.168.254.129:6379 192.168.254.129 6379 @ mymaster 192.168.254.129 6380
说明 6380端口上的redis已经充当主机角色
执行java程序,输出
三月 19, 2018 3:16:55 下午 redis.clients.jedis.JedisSentinelPool initSentinels
INFO:Trying to find master from available Sentinels...
三月 19, 2018 3:16:55 下午 redis.clients.jedis.JedisSentinelPool initSentinels
INFO:Redis master running at 192.168.254.129:6380, starting Sentinel listeners...
三月 19, 2018 3:16:55 下午 redis.clients.jedis.JedisSentinelPool initPool
INFO:Created JedisPool to master at 192.168.254.129:6380
123
结构是在新的主机6380端口上查询到的。