搭建redis-sentinel(哨兵机制)集群

redis怎么才能作到高可用
对于redis主从架构,slave能够对应多个自己能够保障高可用,可是对于一个master节点,若是宕机,整个缓存系统就没法进行写的操做,显然整个系统会没法作到高可用
sentinel哨兵能够监测master节点是否正常运行(会自动识别出全部的slave信息),若是出现宕机,则会在对应的slave节点中经过投票的方式来选取一个slave节点做为新的master节点,
旧的master节点恢复以后会被接管成为新的master节点的slave节点。同时sentinel哨兵节点自己也是集群的方式部署来保障自身的高可用,而且一个sentinel是能够同时监听多个master节点

对于sentinel哨兵节点的一些核心概念:redis


一、sdown和odown转换机制算法

sdown和odown两种失败状态json

sdown是主观宕机,就一个哨兵若是本身以为一个master宕机了,那么就是主观宕机vim

odown是客观宕机,若是quorum数量的哨兵都以为一个master宕机了,那么就是客观宕机centos

sdown达成的条件很简单,若是一个哨兵ping一个master,超过了is-master-down-after-milliseconds指定的毫秒数以后,就主观认为master宕机缓存

sdown到odown转换的条件很简单,若是一个哨兵在指定时间内,收到了quorum指定数量的其余哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机安全

二、哨兵集群的自动发现机制服务器

哨兵互相之间的发现,是经过redis的pub/sub系统实现的,每一个哨兵都会往__sentinel__:hello这个channel里发送一个消息,这时候全部其余哨兵均可以消费到这个消息,并感知到其余的哨兵的存在网络

每隔两秒钟,每一个哨兵都会往本身监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是本身的host、ip和runid还有对这个master的监控配置架构

每一个哨兵也会去监听本身监控的每一个master+slaves对应的__sentinel__:hello channel,而后去感知到一样在监听这个master+slaves的其余哨兵的存在

每一个哨兵还会跟其余哨兵交换对master的监控配置,互相进行监控配置的同步

三、slave配置的自动纠正

哨兵会负责自动纠正slave的一些配置,好比slave若是要成为潜在的master候选人,哨兵会确保slave在复制现有master的数据; 若是slave链接到了一个错误的master上,好比故障转移以后,那么哨兵会确保它们链接到正确的master上

四、slave->master选举算法

若是一个master被认为odown了,并且majority哨兵都容许了主备切换,那么某个哨兵就会执行主备切换操做,此时首先要选举一个slave来

会考虑slave的一些信息

(1)跟master断开链接的时长
(2)slave优先级
(3)复制offset
(4)run id

若是一个slave跟master断开链接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

接下来会对slave进行排序

(1)按照slave优先级进行排序,slave priority越低,优先级就越高
(2)若是slave priority相同,那么看replica offset,哪一个slave复制了越多的数据,offset越靠后,优先级就越高
(3)若是上面两个条件都相同,那么选择一个run id比较小的那个slave

五、quorum和majority

每次一个哨兵要作主备切换,首先须要quorum数量的哨兵认为odown,而后选举出一个哨兵来作切换,这个哨兵还得获得majority哨兵的受权,才能正式执行切换

若是quorum < majority,好比5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵受权就能够执行切换

可是若是quorum >= majority,那么必须quorum数量的哨兵都受权,好比5个哨兵,quorum是5,那么必须5个哨兵都赞成受权,才能执行切换

六、configuration epoch

哨兵会对一套redis master+slave进行监控,有相应的监控的配置

执行切换的那个哨兵,会从要切换到的新master(salve->master)那里获得一个configuration epoch,这就是一个version号,每次切换的version号都必须是惟一的

若是第一个选举出的哨兵切换失败了,那么其余哨兵,会等待failover-timeout时间,而后接替继续执行切换,此时会从新获取一个新的configuration epoch,做为新的version号

七、configuraiton传播

哨兵完成切换以后,会在本身本地更新生成最新的master配置,而后同步给其余的哨兵,就是经过以前说的pub/sub消息机制

这里以前的version号就很重要了,由于各类消息都是经过一个channel去发布和监听的,因此一个哨兵完成一次新的切换以后,新的master配置是跟着新的version号的

其余的哨兵都是根据版本号的大小来更新本身的master配置的

 

1redis安装

解压完成后能够看到INSTALL和README.md文件,查看以获取更多有用信息。

在README文件中能够获取到软件的安装步骤。如下安装步骤基于此。

#step1 进入文件夹,执行编译命令

[root@ redis-3.2.8]# make

#step2 为了后面开发测试的方便,把启动脚本,配置文件,日志文件统一放到redis目录下

[root@ redis-3.2.8]# mkdir /usr/local/redis
[root@ redis-3.2.8]# mkdir /usr/local/redis/logs
[root@ redis-3.2.8]# mkdir /usr/local/redis/bin
[root@ redis-3.2.8]# mkdir /usr/local/redis/conf
[root@ redis-3.2.8]# mkdir /etc/sentinel
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26377
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26378
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26379 [root@ redis-3.2.8]# cp redis.conf sentinel.conf /usr/local/redis/conf/ [root@ src]# cp redis-server redis-sentinel redis-cli /usr/local/redis/bin/

#step3 开启Redis服务,检测其可用性

[root@ bin]# redis-server ../conf/redis.conf 

能够看到日志信息

其中有3个警告

第一个警告:The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

意思是:TCP  backlog设置值,511没有成功,由于 /proc/sys/net/core/somaxconn这个设置的是更小的128.

第二个警告:overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to/etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

意思是:overcommit_memory参数设置为0!在内存不足的状况下,后台程序save可能失败。建议在文件 /etc/sysctl.conf 中将overcommit_memory修改成1。

第三个警告:you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix thisissue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain thesetting after a reboot. Redis must be restarted after THP is disabled.

意思是:你使用的是透明大页,可能致使redis延迟和内存使用问题。执行 echo never > /sys/kernel/mm/transparent_hugepage/enabled 修复该问题。

临时解决方法:

  echo 511 > /proc/sys/net/core/somaxconn

  echo "vm.overcommit_memory=1" > /etc/sysctl.conf

  echo never > /sys/kernel/mm/transparent_hugepage/enabled。

永久解决方法:

vim /etc/sysctl.conf
net.core.somaxconn = 512
vm.overcommit_memory = 1
sysctl -p  #-p 从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf中加载

[root@centos224]# vi /etc/rc.local
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

Redis server使用默认端口6379启动成功。

#step4 修改配置文件,使其之后台服务方式运行。

复制代码
#what?局域网内本机IP。
#我是部署到同一机器上因此IP都同样,端口不一样
bind 127.0.0.1
#修改默认端口,避免被恶意脚本扫描。
port 9999
loglevel debug
logfile /usr/local/redis/logs/redis.log.9999
#为服务设置安全密码
requirepass redispass
#以守护进程方式运行 daemonize yes
复制代码

#step5 从新启动redis。

[root@ bin]# redis-cli -p 9999 -a redispass shutdown
我使用脚本启动方式
  启动脚本 redis_init_script 位于位于Redis的 /utils/ 目录下,redis_init_script脚本代码以下:
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
 
#redis服务器监听的端口
REDISPORT=9999
 
#服务端所处位置
EXEC=/usr/local/bin/redis-server
 
#客户端位置
CLIEXEC=/usr/local/bin/redis-cli
 
#redis的PID文件位置,须要修改
PIDFILE=/var/run/redis_${REDISPORT}.pid
 
#redis的配置文件位置,需将${REDISPORT}修改成文件名
CONF="/etc/redis/${REDISPORT}.conf"
 
case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed"
        else
                echo "Starting Redis server..."
                $EXEC $CONF
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $CLIEXEC -p $REDISPORT shutdown
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac

能够根据你本身端口进行修改

mkdir /etc/redis
cp redis.conf /etc/redis/9999.conf
将启动脚本复制到/etc/init.d目录下,本例将启动脚本命名为redisd(一般都以d结尾表示是后台自启动服务)。
cp redis_init_script /etc/init.d/redis_9999
./redis_9999 start

2开启主从复制(master-slave)

主从模式的两个重要目的,提高系统可靠性和读写分离提高性能。

这里经过修改端口的方式,再启动端口为9997和9998的服务做为备(从)机。

备机启动须要修改配置文件部分属性(在9999配置的基础上)。

复制代码
port 9997
logfile /usr/local/redis/logs/redis.log.9997
#指定master ip port
slaveof 127.0.0.1 9999
#认证master时须要的密码。必须和master配置的requirepass 保持一致
masterauth redispass
requirepass redispass protected-mode no
复制代码

从机9998配置同理

port 9998
logfile /usr/local/redis/logs/redis.log.9998
slaveof 127.0.0.1 9999
masterauth redispass
requirepass redispass protected-mode no

开启从机服务

[root@ bin]# ./redis_9997 start
[root@ bin]# ./redis_9998 start

查看slave 9998日志(省略部分信息),能够看出,slave在启动时成功链接master,并接收到了104字节的同步数据。

6472:S 30 Mar 11:18:17.206 * Connecting to MASTER 127.0.0.1:9999
6472:S 30 Mar 11:18:17.206 * MASTER <-> SLAVE sync started
6472:S 30 Mar 11:18:17.223 * MASTER <-> SLAVE sync: receiving 104 bytes from master
6472:S 30 Mar 11:18:17.223 * MASTER <-> SLAVE sync: Finished with success

redis作一个基准的压测

你若是要对本身刚刚搭建好的redis作一个基准的压测,测一下你的redis的性能和QPS(query per second)

redis本身提供的redis-benchmark压测工具,是最快捷最方便的,固然啦,这个工具比较简单,用一些简单的操做和场景去压测

一、对redis读写分离架构进行压测,单实例写QPS+单实例读QPS

redis-3.2.8/src

./redis-benchmark -h 127.0.0.1

-c <clients> Number of parallel connections (default 50)
-n <requests> Total number of requests (default 100000)
-d <size> Data size of SET/GET value in bytes (default 2)

根据你本身的高峰期的访问量,在高峰期,瞬时最大用户量会达到10万+,-c 100000,-n 10000000,-d 500

一、QPS,本身不一样公司,不一样服务器,本身去测试,跟生产环境还有区别

生产环境,大量的网络请求的调用,网络自己就有开销,你的redis的吞吐量就不必定那么高了

QPS的两个杀手:一个是复杂操做,lrange,挺多的; value很大,2 byte,我以前用redis作大规模的缓存

作商品详情页的cache,多是须要把大串数据,拼接在一块儿,做为一个json串,大小可能都几k,几个byte

二、水平扩容redis读节点,提高度吞吐量

就按照上一节课讲解的,再在其余服务器上搭建redis从节点,单个从节点读请QPS在5万左右,两个redis从节点,全部的读请求打到两台机器上去,承载整个集群读QPS在10万+

3 sentinel模式故障自动迁移

Master-slave主从复制避免了数据丢失带来的灾难性后果。

可是单点故障仍然存在,在运行期间master宕机须要停机手动切换。

Sentinel很好的解决了这个问题,当Master-slave模式中的Master宕机后,可以自主切换,选择另外一个可靠的redis-server充当master角色,使系统仍正常运行。

通常来讲sentinel server须要大于等于3个。

这里经过修改端口的方式开启3个sentinel server。修改配置文件sentinel.conf部分属性

复制代码
#服务运行端口号
port 26379
sentinel monitor mumaster 1270.0.0.1 9999 2 #mymaster为指定的master服务器起一个别名 #master IP和端口号 #2的含义:当开启的sentinel server认为当前master主观下线的(+sdown)数量达到2时,则sentinel server认为当前master客观下线(+odown)系统开始自动迁移。2的计算(建议):
#sentinel server数量的大多数,至少为count(sentinel server)/2 向上取整。2>3/2(主观下线与客观下线?) #master别名和认证密码。这就提醒了用户,在master-slave系统中,各服务的认证密码应该保持一致。 sentinel auth-pass mymaster redispass #以守护进程方式运行 daemonize yes logfile /usr/local/redis/logs/sentinel.log.26379 protected-mode no sentinel down-after-milliseconds mymaster 6000 sentinel failover-timeout mymaster 18000
复制代码

(多开服务只须要在以上配置基础上修改端口号,其它保持不变 port 26378/port 26377)

开启Sentinel服务

redis-sentinel /etc/sentinel/26377.conf
redis-sentinel /etc/sentinel/26378.conf
redis-sentinel /etc/sentinel/26379.conf

启动以后能够看到日志信息,每一个哨兵都能去监控到对应的redis master,并可以自动发现对应的slave,哨兵之间,互相会自动进行发现,用的就是以前说的pub/sub,消息发布和订阅channel消息系统和机制

检查哨兵状态
redis-cli -h 127.0.0.1 -p 26377 -a "redispass"

sentinel master mymaster
SENTINEL slaves mymaster
SENTINEL sentinels mymaster

SENTINEL get-master-addr-by-name mymaster

哨兵节点相关配置

 

一、哨兵节点的增长和删除

增长sentinal,会自动发现

删除sentinal的步骤

(1)中止sentinal进程
(2)SENTINEL RESET *,在全部sentinal上执行,清理全部的master状态
(3)SENTINEL MASTER mastername,在全部sentinal上执行,查看全部sentinal对数量是否达成了一致

二、slave的永久下线

让master摘除某个已经下线的slave:SENTINEL RESET mastername,在全部的哨兵上面执行

三、slave切换为Master的优先级

slave->master选举优先级:slave-priority,值越小优先级越高

四、基于哨兵集群架构下的安全认证

每一个slave都有可能切换成master,因此每一个实例都要配置两个指令

master上启用安全认证,requirepass
master链接口令,masterauth

sentinal,sentinel auth-pass <master-group-name> <pass>

 

五、容灾演练

经过哨兵看一下当前的master:SENTINEL get-master-addr-by-name mymaster

把master节点kill -9掉,pid文件也删除掉

查看sentinal的日志,是否出现+sdown字样,识别出了master的宕机问题; 而后出现+odown字样,就是指定的quorum哨兵数量,都认为master宕机了

(1)三个哨兵进程都认为master是sdown了
(2)超过quorum指定的哨兵进程都认为sdown以后,就变为odown
(3)哨兵1是被选举为要执行后续的主备切换的那个哨兵
(4)哨兵1去新的master(slave)获取了一个新的config version
(5)尝试执行failover
(6)投票选举出一个slave区切换成master,每隔哨兵都会执行一次投票
(7)让salve,slaveof noone,不让它去作任何节点的slave了; 把slave提拔成master; 旧的master认为再也不是master了
(8)哨兵就自动认为以前的master变成slave,将投票出的slave变成master 
(9)哨兵去探查了一下以前的master(变成来salve)的状态,认为它sdown了 

 

故障恢复,再将旧的master从新启动,查看是否被哨兵自动切换成slave节点

查看到结果将9999 切换为slave节点

容灾演练日志
Sentinel ID is ea82430cf7f6d452eb22bbf29b92fcf001c734c8
3010:X 21 Nov 22:37:31.405 # +monitor master mymaster 127.0.0.1 9999 quorum 2
3010:X 21 Nov 23:01:12.589 # +sdown master mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:12.642 # +odown master mymaster 127.0.0.1 9999 #quorum 3/2           -- 进入ODOWN状态时。有三个哨兵认为master当机了
3010:X 21 Nov 23:01:12.642 # +new-epoch 7                                                -- 当前配置版本被更新时。
3010:X 21 Nov 23:01:12.642 # +try-failover master mymaster 127.0.0.1 9999                -- 尝试故障转移,正等待其余sentinel的选举。
3010:X 21 Nov 23:01:12.658 # +vote-for-leader ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7 -- 投票给领导
3010:X 21 Nov 23:01:12.668 # edace82644513417b676ee6eced3184771d6361d voted for ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7
3010:X 21 Nov 23:01:12.668 # 7e68a54266703cbf429f5c6512a50a39ab94b943 voted for ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7
3010:X 21 Nov 23:01:12.716 # +elected-leader master mymaster 127.0.0.1 9999              -- 被选举为去执行failover的时候。
3010:X 21 Nov 23:01:12.716 # +failover-state-select-slave master mymaster 127.0.0.1 9999 -- 开始要选择一个slave当选新master时。
3010:X 21 Nov 23:01:12.792 # +selected-slave slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999 -- 找到了port:9998一个适合的slave来担当新master
                              -- 当把选择为新master的slave的身份进行切换的时候。
3010:X 21 Nov 23:01:12.792 * +failover-state-send-slaveof-noone slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999 
                              -- 等待提高 9998 为新的master
3010:X 21 Nov 23:01:12.851 * +failover-state-wait-promotion slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:13.699 # +promoted-slave slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999        -- 提高 9998 master
3010:X 21 Nov 23:01:13.699 # +failover-state-reconf-slaves master mymaster 127.0.0.1 9999                         -- Failover状态变为reconf-slaves状态时
3010:X 21 Nov 23:01:13.749 * +slave-reconf-sent slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999     -- 从新配置 9997为slave
3010:X 21 Nov 23:01:14.770 # -odown master mymaster 127.0.0.1 9999                                                -- 离开ODOWN状态时。
                             -- inprog 9997 slave被从新配置为9998的master的slave,但数据复制还未发生时。
3010:X 21 Nov 23:01:14.770 * +slave-reconf-inprog slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999 
                             -- done   9997 slave被从新配置为9998的master的slave,而且数据复制已经与master同步时。
3010:X 21 Nov 23:01:14.770 * +slave-reconf-done slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:14.841 # +failover-end master mymaster 127.0.0.1 9999                                        -- 故障转移结束
3010:X 21 Nov 23:01:14.841 # +switch-master mymaster 127.0.0.1 9999 127.0.0.1 9998                               -- master由9999 替换为 9998
3010:X 21 Nov 23:01:14.841 * +slave slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9998                -- 检测到9997slave并添加进slave列表时
3010:X 21 Nov 23:01:14.842 * +slave slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998                -- 检测到9999slave
3010:X 21 Nov 23:01:44.849 # +sdown slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998                -- 进入SDOWN状态时;
3010:X 21 Nov 23:04:19.457 # -sdown slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998                -- 离开SDOWN状态时
相关文章
相关标签/搜索