1. 部署环境

1.1 Version

> OS: CentOS 6.5 64bit
> Redis: 3.0.2

1.2 Machine

> 192.168.199.182 master
> 192.168.199.229 slave1
> 192.168.199.237 slave2
> 192.168.199.231 client

1.3 Redis Sentinel系统构成

> Master: master:6379, slave1:6379, slave2:6379
> Slave: master:6380, slave1:6380, slave2:6380
> Sentinel: master:26379, slave1:26379, slave2:26379

1.4 Redis安装位置

> /home/user1/app/redis-3.0.2/redis-sentinel    #后面以“$REDIS_HOME”表示

2. 编译Redis

$ cd $REDIS_HOME
$ make

3. 配置Sentinel

3.1 Redis Master

$REDIS_HOME/redis_6379.conf

$ cd $REDIS_HOME
$ mkdir dbfile logs
$ cp redis.conf redis_6379.conf
#$ mv redis.conf redis.conf.template
$ vim redis_6379.conf
    #指定端口
    port 6379
    #数据库文件的名称
    dbfilename dump_6379.rdb
    #数据库文件的保存位置
    dir ./dbfile/
    #日志文件的保存位置
    logfile logs/redis_6379.log

3.2 Redis Slave

$REDIS_HOME/redis_6380.conf

$ cd $REDIS_HOME
$ mkdir dbfile logs
$ cp redis.conf redis_6380.conf
#$ mv redis.conf redis.conf.template

###在master节点(192.168.199.182)
$ vim redis_6380.conf
    #指定端口
    port 6380
    #数据库文件的名称
    dbfilename dump_6380.rdb
    #数据库文件的保存位置
    dir ./dbfile/
    #日志文件的保存位置
    logfile logs/redis_6380.log
    #指定主服务器的地址和端口
    slaveof 192.168.199.182 6379

###在slave1节点(192.168.199.229)
$ vim redis_6380.conf
    #指定端口
    port 6380
    #数据库文件的名称
    dbfilename dump_6380.rdb
    #数据库文件的保存位置
    dir ./dbfile/
    #日志文件的保存位置
    logfile logs/redis_6380.log
    #指定主服务器的地址和端口
    slaveof 192.168.199.229 6379

###在slave2节点(192.168.199.237)
$ vim redis_6380.conf
    #指定端口
    port 6380
    #数据库文件的名称
    dbfilename dump_6380.rdb
    #数据库文件的保存位置
    dir ./dbfile/
    #日志文件的保存位置
    logfile logs/redis_6380.log
    #指定主服务器的地址和端口
    slaveof 192.168.199.237 6379

3.3 Redis Sentinel

$ cd $REDIS_HOME
$ cp sentinel.conf sentinel_26379.conf
#$ mv sentinel.conf sentinel.conf.template
$ vim sentinel_26379.conf
    #指定端口
    port 26379

    #监控master节点(192.168.199.182)的6379端口
    sentinel monitor master1 192.168.199.182 6379 2
    sentinel down-after-milliseconds master1 30000
    sentinel parallel-syncs master1 1
    sentinel failover-timeout master1 180000

    #监控slave1节点(192.168.199.229)的6379端口
    sentinel monitor master2 192.168.199.229 6379 2
    sentinel down-after-milliseconds master2 30000
    sentinel parallel-syncs master2 1
    sentinel failover-timeout master2 180000

    #监控slave2节点(192.168.199.237)的6379端口
    sentinel monitor master3 192.168.199.237 6379 2
    sentinel down-after-milliseconds master3 30000
    sentinel parallel-syncs master3 1
    sentinel failover-timeout master3 180000

4. 启动Sentinel

4.1 Redis Master

$ cd $REDIS_HOME
$ src/redis-server ./redis_6379.conf &

4.2 Redis Slave

$ cd $REDIS_HOME
$ src/redis-server ./redis_6380.conf &

4.3 Redis Sentinel

$ cd $REDIS_HOME
$ src/redis-sentinel ./sentinel_26379.conf &

5. Sentinel测试

5.1 主从测试

5.1.1 Redis客户端连接Redis的主节点

$ src/redis-cli -h master -p 6379
master:6379> set k1 100
OK
master:6379> get k1
"100"

5.1.2 Redis客户端连接Redis的从节点

$ src/redis-cli -h master -p 6380
master:6380> get k1
"100"
master:6380> set k2 999
(error) READONLY You can't write against a read only slave.

5.2 Sentinel测试

5.2.1 杀死Redis主服务器的服务

$ ps -ef | grep redis

user1 7893 1784 0 07:15 pts/0 00:00:03 src/redis-server :6379 #主服务器的服务
user1 7897 1784 0 07:16 pts/0 00:00:03 src/redis-server
:6380
user1 7903 1784 1 07:17 pts/0 00:00:08 src/redis-sentinel *:26379 [sentinel]
user1 7924 1784 0 07:27 pts/0 00:00:00 grep redis

$ kill -9 7893

#Sentinel输出以下信息,[192.168.199.182 6380]成为主服务
4974:X 18 Jun 07:28:42.385 # +sdown master master1 192.168.199.182 6379
4974:X 18 Jun 07:28:42.449 # +new-epoch 1
4974:X 18 Jun 07:28:42.455 # +vote-for-leader 127048c0998044968c0143d4ea0ac3064049e90f 1
4974:X 18 Jun 07:28:42.456 # +odown master master1 192.168.199.182 6379 #quorum 3/2
4974:X 18 Jun 07:28:42.456 # Next failover delay: I will not start a failover before Thu Jun 18 07:34:42 2015
4974:X 18 Jun 07:28:43.535 # +config-update-from sentinel 192.168.199.229:26379 192.168.199.229 26379 @ master1 192.168.199.182 6379
4974:X 18 Jun 07:28:43.535 # +switch-master master1 192.168.199.182 6379 192.168.199.182 6380
4974:X 18 Jun 07:28:43.536 * +slave slave 192.168.199.182:6379 192.168.199.182 6379 @ master1 192.168.199.182 6380
4974:X 18 Jun 07:29:13.543 # +sdown slave 192.168.199.182:6379 192.168.199.182 6379 @ master1 192.168.199.182 6380

5.2.2 Redis客户端连接Redis

#尝试连接已经被杀死的服务
$ src/redis-cli -h master -p 6379
Could not connect to Redis at master:6379: Connection refused
not connected> 

#尝试连接从服务器
$ src/redis-cli -h master -p 6380
master:6380> get k1
"100"
master:6380> set kk1 1000 #已经可以进行写操作
OK
master:6380> get kk1
"1000"

#重新启动6379端口的服务
$ src/redis-server ./redis_6379.conf &

#查看master节点(192.168.199.182)在6379端口的服务
$ src/redis-cli -h master -p 6379 INFO replication
# Replication
role:slave #角色:slave
master_host:192.168.199.182
master_port:6380
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:5538
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

#查看master节点(192.168.199.182)在6380端口的服务
$ src/redis-cli -h master -p 6380 INFO replication
# Replication
role:master #角色:master
connected_slaves:1
slave0:ip=192.168.199.182,port=6379,state=online,offset=7122,lag=1
master_repl_offset:7136
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:7135

#查看sentinel集群信息
$ src/redis-cli -h master -p 26379 INFO sentinel
# Sentinel
sentinel_masters:3
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=master3,status=ok,address=192.168.199.237:6379,slaves=1,sentinels=3
master1:name=master1,status=ok,address=192.168.199.182:6380,slaves=1,sentinels=3
master2:name=master2,status=ok,address=192.168.199.229:6379,slaves=1,sentinels=3

6. 体会与总结

(1)多个Master之间不能实现数据共享。
(2)当主从切换之后(主下线,从变主),如果这两个服务重新启动,并且都不在Sentinel的监控之下,这两个服务是独立的,没有主从关系。
(3)与Hadoop集群的比较:Sentinel相当于Hadoop集群中的Zookeeper集群,多Master相当于Hadoop HDFS Federation,Master-Slave结构相当Hadoop HDFS HA。

7. Sentinel集群在开发中存在的问题记录

Jedis在使用过程中出现主从切换的话,会导致Jedis实例抛出异常。
解决办法:使用Spring与Jedis的集成

使用Redisson时的问题 解决办法:最好做成1主2从的部署结构

Jedis没有提供基于Sentinel的ShardedJedisPool