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


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

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


    1、sdown和odown转换机制

    sdown和odown两种失败状态

    sdown是主观宕机,就一个哨兵如果自己觉得一个master宕机了,那么就是主观宕机

    odown是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那么就是客观宕机

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

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

    2、哨兵集群的自动发现机制

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

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

    每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在

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

    3、slave配置的自动纠正

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

    4、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

    5、quorum和majority

    每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个哨兵来做切换,这个哨兵还得得到majority哨兵的授权,才能正式执行切换

    如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换

    但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换

    6、configuration epoch

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

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

    如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的version号

    7、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压测工具,是最快捷最方便的,当然啦,这个工具比较简单,用一些简单的操作和场景去压测

    1、对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

    1、QPS,自己不同公司,不同服务器,自己去测试,跟生产环境还有区别

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

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

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

    2、水平扩容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

    哨兵节点相关配置

    1、哨兵节点的增加和删除

    增加sentinal,会自动发现

    删除sentinal的步骤

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

    2、slave的永久下线

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

    3、slave切换为Master的优先级

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

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

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

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

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

    5、容灾演练

    通过哨兵看一下当前的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状态时
  • 相关阅读:
    kubernetes 二进制安装v2
    Istio
    linux的history指令显示时间
    echarts折线图y轴刻度值按照某个值的倍数
    ubuntu下tesseract 4.0安装及参数使用
    chrome 浏览器下载大文件断掉的问题
    强化学习
    第十一篇 -- 2020总结以及2021期待
    字符串时间yyyyMMddHHmmss转成yyyy-MM-dd HH-mm-ss字符串格式
    windows安装mongodb,密码访问
  • 原文地址:https://www.cnblogs.com/lihonglin2016/p/10037808.html
Copyright © 2020-2023  润新知