zoukankan      html  css  js  c++  java
  • Redis sentinel之集群搭建

    环境

    由于不太熟悉docker,所以,把docker当虚拟机来用,服务器环境如下:

    Redis Server 环境搭建 

    Redis Server 01 搭建 并且制作Redis镜像

    容器建立

    # docker run -i -t --name redis_server_01 --net mynetwork --ip 172.30.1.21 -p 6381:6381 -v /root/redis_data:/redis centos /bin/bash

    容器中必要包下载

    # yum install wget gcc make vim -y

    下载redis-5.0.0

    # mkdir /soft
    # cd /soft/
    # wget http://download.redis.io/releases/redis-5.0.0.tar.gz

    安装redis

    # tar xf redis-5.0.0.tar.gz 
    # cd redis-5.0.0
    # make PREFIX=/usr/local/redis install
    # make install

    配置redis.conf

    # cp /soft/redis-5.0.0/redis.conf /redis/
    # mv /redis/redis.conf /redis/conf-redis-6381.conf
    修改效果如下: 
    # cat /redis/conf-redis-6381.conf | grep -Ev "^$|^#"
    protected-mode yes
    port 6381
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    daemonize yes
    supervised no
    pidfile /redis/pid-redis-6381.pid
    loglevel notice
    logfile "log-redis-6381.log"
    databases 16
    always-show-logo yes
    save 900 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename rdb-6381.rdb
    dir /redis
    masterauth j2H2n@e6Gvrhsc1Enr4^yxf*l43*ht
    replica-serve-stale-data yes
    replica-read-only yes
    repl-diskless-sync no
    repl-diskless-sync-delay 5
    repl-disable-tcp-nodelay no
    replica-priority 100
    requirepass j2H2n@e6Gvrhsc1Enr4^yxf*l43*ht
    lazyfree-lazy-eviction no
    lazyfree-lazy-expire no
    lazyfree-lazy-server-del no
    replica-lazy-flush no
    appendonly no
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    aof-use-rdb-preamble yes
    lua-time-limit 5000
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    latency-monitor-threshold 0
    notify-keyspace-events ""
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    stream-node-max-bytes 4096
    stream-node-max-entries 100
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit replica 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    dynamic-hz yes
    aof-rewrite-incremental-fsync yes
    rdb-save-incremental-fsync yes
    # 

    开启服务并且制作镜像

    # redis-server /redis/conf-redis-6381.conf
    退出容器制作镜像

    Ctrl + P + Q 可以退出容器而使之不停止
    寻找CONTAINER ID并且制作为镜像
    # docker ps | grep redis_server_01
    制作镜像 
    # docker commit 1ce7c0cf1364 redis_server_sentinel
    查看镜像
    # docker images | grep redis_server_sentinel

    Redis Server 02 / Redis Server 03搭建 

    容器建立

    # docker run -i -t --name redis_server_02 --net mynetwork --ip 172.30.1.22 -p 6382:6382 -v /root/redis_data:/redis redis_server_sentinel /bin/bash

    配置redis.conf

    # cp /redis/conf-redis-6381.conf conf-redis-6382.conf
    相比于redis server 01 的配置文档,server 02的配置文档有差异的地方如下:

    # cat /redis/conf-redis-6382.conf | grep '6382'
    port 6382
    pidfile /redis/pid-redis-6382.pid
    logfile "log-redis-6382.log"
    dbfilename rdb-6382.rdb
    # 

    开启服务

    # redis-server /redis/conf-redis-6382.conf

    用类似的方法配置redis server 03服务器

    # docker run -i -t --name redis_server_03 --net mynetwork --ip 172.30.1.23 -p 6383:6383 -v /root/redis_data:/redis redis_server_sentinel /bin/bash
    
    # cp /redis/conf-redis-6382.conf /redis/conf-redis-6383.conf
    
    # cat /redis/conf-redis-6383.conf | grep "6383"
    port 6383
    pidfile /redis/pid-redis-6383.pid
    logfile "log-redis-6383.log"
    dbfilename rdb-6383.rdb
    # 
    
    # redis-server /redis/conf-redis-6383.conf

    Redis Server 主从复制搭建

    将6382/6383 作为 6381 的从库 
    # docker attach redis_server_02
    # redis-cli -p 6382
    127.0.0.1:6382> AUTH j2H2n@e6Gvrhsc1Enr4^yxf*l43*ht
    OK
    127.0.0.1:6382> SLAVEOF 172.30.1.21 6381
    OK
    127.0.0.1:6382> exit
    
    # docker attach redis_server_03
    # redis-cli -p 6383
    127.0.0.1:6383> AUTH j2H2n@e6Gvrhsc1Enr4^yxf*l43*ht
    OK
    127.0.0.1:6383> SLAVEOF 172.30.1.21 6381
    OK
    127.0.0.1:6383> exit
    验证主从复制 
    # docker attach redis_server_01
    # redis-cli -p 6381
    127.0.0.1:6381> AUTH j2H2n@e6Gvrhsc1Enr4^yxf*l43*ht
    OK
    127.0.0.1:6381> INFO replication
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=172.30.1.22,port=6382,state=online,offset=294,lag=0
    slave1:ip=172.30.1.23,port=6383,state=online,offset=294,lag=1
    master_replid:bc1ecc220927ba0d9c368a3837c5fe43e718d1b3
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:294
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:294
    127.0.0.1:6381> 

    Redis Sentinel 环境搭建 

    Redis Sentinel 01 搭建

    容器建立

    # docker run -i -t --name redis_sentinel_01 --net mynetwork --ip 172.30.1.24 -p 26381:26381 -v /root/redis_data:/redis redis_server_sentinel /bin/bash

    定义邮件发送

    # mkdir /redis
    # cd /redis
    # yum install python
    
    定义python发送脚本
    # cat sentinel_mail.py 
        #!/usr/bin/env python
        import sys
        import smtplib
        import email.mime.text
    
        def SamMail(message):
            HOST = "SMTP服务器"
            SUBJECT = 'redis_docker_sentinel'
            TO = "发送给谁"
            FROM = "谁发送的"
    
            msg = email.mime.text.MIMEText(
            """
                %s
            """ %(message),"html","utf-8")
    
            msg['Subject'] = SUBJECT
            msg['From'] = FROM
            msg['TO'] = TO
    
            server = smtplib.SMTP_SSL(HOST,'465')
            server.login("用户名","密码")
            server.sendmail(FROM,TO.split(','),msg.as_string())
            server.quit
    
        def main():
            message = ""
            for argv_text in sys.argv[1:]:
                message = message + argv_text
            SamMail(message)
    
        if __name__=="__main__":
            main()
    #
    测试发送
    # ./sentinel_mail.py 123

    配置sentinel.conf 

    # cp /soft/redis-5.0.0/sentinel.conf /redis/conf-sentinel-26381.conf
    # cat conf-sentinel-26381.conf | grep -Ev "^$|^#"
    port 26381
    protected-mode no
    daemonize yes
    pidfile /redis/pid-redis-sentinel-26381.pid
    logfile "/redis/log-sentinel-26381.log"
    dir /tmp
    sentinel monitor docker_sentinel 172.30.1.21 6381 2
    sentinel auth-pass docker_sentinel j2H2n@e6Gvrhsc1Enr4^yxf*l43*ht
    sentinel down-after-milliseconds docker_sentinel 30000
    sentinel parallel-syncs docker_sentinel 1
    sentinel failover-timeout docker_sentinel 180000
    sentinel notification-script docker_sentinel /redis/sentinel_mail.py
    sentinel deny-scripts-reconfig yes
    # 

    制作镜像 

    # docker commit 5d61d56f35f4 redis_sentinel_server

    Redis Sentinel 02 / Redis Sentinel 03 搭建

    redis sentinel 2 容器建立

    # docker run -i -t --name redis_sentinel_02 --net mynetwork --ip 172.30.1.25 -p 26382:26382 -v /root/redis_data:/redis redis_server_sentinel /bin/bash

    配置文件修改

    相比于conf-sentinel-26381.conf,conf-sentinel-26382.conf不同点在于
    # cp conf-sentinel-26381.conf conf-sentinel-26382.conf 
    # cat conf-sentinel-26382.conf | grep '26382'
    port 26382
    pidfile "/redis/pid-redis-sentinel-26382.pid"
    logfile "/redis/log-sentinel-26382.log"
    # 

    redis sentinel 3 容器建立

    # docker run -i -t --name redis_sentinel_03 --net mynetwork --ip 172.30.1.26 -p 26383:26383 -v /root/redis_data:/redis redis_server_sentinel /bin/bash

    配置文件修改

    相比于conf-sentinel-26382.conf,conf-sentinel-26383.conf不同点在于
    # cp conf-sentinel-26382.conf conf-sentinel-26383.conf
    # cat conf-sentinel-26383.conf | grep 26383
    port 26383
    pidfile "/redis/pid-redis-sentinel-26383.pid"
    logfile "/redis/log-sentinel-26383.log"
    # 

    依次启动26381,26382,26383 sentinel

    # docker attach redis_sentinel_01
    # redis-sentinel /redis/conf-sentinel-26381.conf 
    # docker attach redis_sentinel_02
    # redis-sentinel /redis/conf-sentinel-26382.conf
    # docker attach redis_sentinel_03
    # redis-sentinel /redis/conf-sentinel-26383.conf 
    重启完毕后,立马接收邮件如下:
    

     

    从宿主机访问redis sentinel

    # cat redis_sentinel.py 
    #!/usr/bin/env python3
    
    import redis
    import redis.sentinel
    
    sentinel_list = redis.sentinel.Sentinel([
    ('172.30.1.24',26381),
    ('172.30.1.25',26382),
    ('172.30.1.26',26383),
    ])
    
    #获取主服务器信息
    get_master_info = sentinel_list.discover_master('docker_sentinel')
    print (get_master_info)
    
    #获取从服务器信息
    get_slave_info = sentinel_list.discover_slaves('docker_sentinel')
    print (get_slave_info)
    
    # 

    执行如下

    # ./redis_sentinel.py 
    ('172.30.1.21', 6381)
    [('172.30.1.22', 6382), ('172.30.1.23', 6383)]
    # 

    模拟灾难切换

    模拟脚本

     在宿主机上定义python flask 脚本,用于获取主库和从库IP 

    #!/usr/bin/env python3
    
    import redis
    import redis.sentinel
    import random
    from flask import Flask
    import logging
    
    app = Flask(__name__)
    
    @app.route('/master_info')
    def get_redis_master_info() :
            sentinel_list = redis.sentinel.Sentinel([
                    ('172.30.1.24',26381),
                    ('172.30.1.24',26382),
                    ('172.30.1.24',26383),
            ])
    
            get_master_info = sentinel_list.discover_master('docker_sentinel')
            return str(get_master_info[1])
    
    @app.route('/slave_info')
    def get_redis_slave_info() :
            sentinel_list = redis.sentinel.Sentinel([
                    ('172.30.1.24',26381),
                    ('172.30.1.24',26382),
                    ('172.30.1.24',26383),
            ])
    
            get_slave_info = sentinel_list.discover_slaves('docker_sentinel')
            return_get_slave_info = get_slave_info[random.randint(0,len(get_slave_info)-1)]
    
            return str(return_get_slave_info[1])
    
    
    @app.route('/')
    def index():
            return 'hello world'
    
    if __name__ == '__main__':
            app.debug = True
            app.run(host='0.0.0.0',port=9001)

    脚本获取的效果如下:

    # curl 127.0.0.1:9001/slave_info
    6383
    # curl 127.0.0.1:9001/master_info
    6381
    # 

    由于是docker环境,故,域名是固定的,只需要知道端口就行了

    模拟主库挂掉

    关掉主库

    # docker stop redis_server_01
    redis_server_01
    # 

    收到的邮件:

    再次用脚本获取当前主库和从库:

    # ./redis_sentinel.py 
    ('172.30.1.23', 6383)
    [('172.30.1.22', 6382)]
    # curl 127.0.0.1:9001/master_info
    6383
    # curl 127.0.0.1:9001/slave_info
    6382
    # 

    再次将6380给开启:

    # docker start redis_server_01
    redis_server_01
    # docker attach redis_server_01
    # redis-server /redis/conf-redis-6381.conf 
    # 

    邮件如下:

    再次用脚本测试如下

    # ./redis_sentinel.py 
    ('172.30.1.23', 6383)
    [('172.30.1.22', 6382), ('172.30.1.21', 6381)]
    # curl 127.0.0.1:9001/slave_info
    6381
    # curl 127.0.0.1:9001/slave_info
    6381
    # curl 127.0.0.1:9001/slave_info
    6382
    # curl 127.0.0.1:9001/master_info
    6383
    # 

    可见,虽然在主库挂掉的时候,大约会有30秒的切换时间,但是总的来说,还是不错的 

     
    欢迎转发! 请保留源地址: https://www.cnblogs.com/NoneID
  • 相关阅读:
    easyui中的combobox小知识点~~
    nodejs+express+mysql 增删改查
    建库和表的脚本.sql
    linux服务器最大连接数
    java高级主题
    java线程池ThreadPoolExecutor
    关于Future
    git rebase
    bash shell for循环
    accept()出的socket不会使用新的端口号
  • 原文地址:https://www.cnblogs.com/NoneID/p/9972399.html
Copyright © 2011-2022 走看看