• Redis集群命令行部署工具


    使用之前准备工作:
    1)配置好与端口无关的公共redis.conf文件,和工具放在同一目录下
    2)配置好与端口相关的模板redis-PORT.conf文件,也和工具放在同一目录下(部署时PORT会被替换成具体的端口号)
    3)配置好组成集群的节点文件redis_cluster.nodes,也和工具放在同一目录下
    redis_cluster.nodes的文件格式为每行一个组成Redis集群的节点,支持“#”打头的注释行,格式示例:
    127.0.0.1 6381
    127.0.0.1 6382
    127.0.0.1 6383
    127.0.0.1 6384
    127.0.0.1 6385
    127.0.0.1 6386
    4)创建好安装redis的目录(可建筑批量工具mooon_ssh完成,deploy_redis_cluster.sh主要也是利用了该批量工具)
    5)其它更详细的可以直接看源代码,有详细的说明。

    建立将https://github.com/eyjian/redis-tools/tree/master/deploy下载到一个目录,运行deploy_redis_cluster.sh工具时,它会提示各种前置条件,比如redis-cli是否可用等。

    源码(可从https://github.com/eyjian/redis-tools下载):

    #!/bin/bash
    # 源代码:https://github.com/eyjian/redis-tools
    # a tool to deploy a redis cluster
    #
    # 自动化部署redis集群工具,
    # 远程操作即可,不需登录到Redis集群中的任何机器。
    #
    # 以root用户批量创建用户redis示例:
    # export H=192.168.0.5,192.168.0.6,192.168.0.7,192.168.0.8,192.168.0.9
    # export U=root
    # export P='root^1234'
    # mooon_ssh -c='groupadd redis; useradd -g redis -m redis; echo "redis:redis#1234"|chpasswd'
    #
    # 批量创建redis安装目录/data/redis-4.0.11,并设置owner为用户redis,用户组为redis示例:
    # mooon_ssh -c='mkdir /data/redis-4.0.11;ln -s /data/redis-4.0.11 /data/redis;chown redis:redis /data/redis*'
    #
    # 可使用process_monitor.sh监控redis-server进程重启:
    # https://github.com/eyjian/libmooon/blob/master/shell/process_monitor.sh
    # 使用示例:
    # * * * * * /usr/local/bin/process_monitor.sh "/usr/local/redis/bin/redis-server 6379" "/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf"
    # * * * * * /usr/local/bin/process_monitor.sh "/usr/local/redis/bin/redis-server 6380" "/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf"
    # 可在/tmp目录找到process_monitor.sh的运行日志,当对应端口的进程不在时,5秒内即会重启对应端口的进程。
    #
    # 运行参数:
    # 参数1 SSH端口
    # 参数2 安装用户
    # 参数3 安装用户密码
    # 参数4 安装目录
    #
    # 前置条件(可借助批量工具mooon_ssh和mooon_upload完成):
    # 1)安装用户已经创建好
    # 2)安装用户密码已经设置好
    # 3)安装目录已经创建好,并且目录的owner为安装用户
    # 4)执行本工具的机器上安装好了ruby,且版本号不低于2.0.0
    # 5)执行本工具的机器上安装好了redis-X.Y.Z.gem,且版本号不低于redis-3.0.0.gem
    #
    # 6)同目录下存在以下几个可执行文件:
    # 6.1)redis-server
    # 6.2)redis-cli
    # 6.3)redis-check-rdb
    # 6.4)redis-check-aof
    # 6.5)redis-trib.rb
    #
    # 7)同目录下存在以下两个配置文件:
    # 7.1)redis.conf
    # 7.2)redis-PORT.conf
    # 其中redis.conf为公共配置文件,
    # redis-PORT.conf为指定端口的配置文件模板,
    # 同时,需要将redis-PORT.conf文件中的目录和端口分别使用INSTALLDIR和REDISPORT替代,示例:
    # include INSTALLDIR/conf/redis.conf
    # pidfile INSTALLDIR/bin/redis-REDISPORT.pid
    # logfile INSTALLDIR/log/redis-REDISPORT.log
    # port REDISPORT
    # dbfilename dump-REDISPORT.rdb
    # dir INSTALLDIR/data/REDISPORT
    #
    # 其中INSTALLDIR将使用参数4的值替换,
    # 而REDISPORT将使用redis_cluster.nodes中的端口号替代
    #
    # 配置文件redis_cluster.nodes,定义了安装redis的节点
    # 文件格式(以“#”打头的为注释):
    # 每行由IP和端口号组成,两者间可以:空格、逗号、分号、或TAB符分隔
    #
    # 依赖:
    # 1)mooon_ssh 远程操作多台机器批量命令工具
    # 2)mooon_upload 远程操作多台机器批量上传工具
    # 3)https://raw.githubusercontent.com/eyjian/libmooon
    # 4)libmooon又依赖libssh2(http://www.libssh2.org/)
    
    BASEDIR=$(dirname $(readlink -f $0))
    REDIS_CLUSTER_NODES=$BASEDIR/redis_cluster.nodes
    
    # 批量命令工具
    MOOON_SSH=mooon_ssh
    # 批量上传工具
    MOOON_UPLOAD=mooon_upload
    # 创建redis集群工具
    REDIS_TRIB=$BASEDIR/redis-trib.rb
    # redis-server
    REDIS_SERVER=$BASEDIR/redis-server
    # redis-cli
    REDIS_CLI=$BASEDIR/redis-cli
    # redis-check-aof
    REDIS_CHECK_AOF=$BASEDIR/redis-check-aof
    # redis-check-rdb
    REDIS_CHECK_RDB=$BASEDIR/redis-check-rdb
    # redis.conf
    REDIS_CONF=$BASEDIR/redis.conf
    # redis-PORT.conf
    REDIS_PORT_CONF=$BASEDIR/redis-PORT.conf
    
    # 全局变量
    # 组成redis集群的总共节点数
    num_nodes=0
    # 组成redis集群的所有IP数组
    redis_node_ip_array=()
    # 组成redis集群的所有节点数组(IP+port构造一个redis节点)
    redis_node_array=()
    
    # 用法
    function usage()
    {
        echo -e "33[1;33mUsage33[m: `basename $0` 33[0;32;32mssh-port33[m install-user 33[0;32;32minstall-user-password33[m install-dir"
        echo -e "33[1;33mExample33[m: `basename $0` 33[0;32;32m2233[m redis 33[0;32;32mredis^123433[m /usr/local/redis-4.0.11"
    }
    
    # 需要指定五个参数
    if test $# -ne 4; then
        usage
        echo ""
        exit 1
    fi
    
    ssh_port="$1"
    install_user="$2"
    install_user_password="$3"
    install_dir="$4"
    echo -e "[ssh port] 33[1;33m$ssh_port33[m"
    echo -e "[install user] 33[1;33m$install_user33[m"
    echo -e "[install directory] 33[1;33m$install_dir33[m"
    echo ""
    
    # 检查ruby是否可用
    which ruby > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking ruby OK"
    else
        echo -e "ruby 33[0;32;31mnot exists or not executable33[m"
        echo "https://www.ruby-lang.org"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查gem是否可用
    which gem > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking gem OK"
    else
        echo -e "gem 33[0;32;31mnot exists or not executable33[m"
        echo "https://rubygems.org/pages/download"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查mooon_ssh是否可用
    which "$MOOON_SSH" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $MOOON_SSH OK"
    else
        echo -e "$MOOON_SSH 33[0;32;31mnot exists or not executable33[m"
        echo "There are two versions: C++ and GO:"
        echo "https://github.com/eyjian/libmooon/releases"
        echo "https://raw.githubusercontent.com/eyjian/libmooon/master/tools/mooon_ssh.cpp"
        echo "https://raw.githubusercontent.com/eyjian/libmooon/master/tools/mooon_ssh.go"    
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查mooon_upload是否可用
    which "$MOOON_UPLOAD" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $MOOON_UPLOAD OK"
    else
        echo -e "$MOOON_UPLOAD 33[0;32;31mnot exists or not executable33[m"
        echo "There are two versions: C++ and GO:"
        echo "https://github.com/eyjian/libmooon/releases"
        echo "https://raw.githubusercontent.com/eyjian/libmooon/master/tools/mooon_upload.cpp"
        echo "https://raw.githubusercontent.com/eyjian/libmooon/master/tools/mooon_upload.go"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis-trib.rb是否可用
    which "$REDIS_TRIB" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $REDIS_TRIB OK"
    else
        echo -e "$REDIS_TRIB 33[0;32;31mnot exists or not executable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis-server是否可用
    which "$REDIS_SERVER" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $REDIS_SERVER OK"
    else
        echo -e "$REDIS_SERVER 33[0;32;31mnot exists or not executable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis-cli是否可用
    which "$REDIS_CLI" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $REDIS_CLI OK"
    else
        echo -e "$REDIS_CLI 33[0;32;31mnot exists or not executable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis-check-aof是否可用
    which "$REDIS_CHECK_AOF" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $REDIS_CHECK_AOF OK"
    else
        echo -e "$REDIS_CHECK_AOF 33[0;32;31mnot exists or not executable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis-check-rdb是否可用
    which "$REDIS_CHECK_RDB" > /dev/null 2>&1
    if test $? -eq 0; then
        echo -e "Checking $REDIS_CHECK_RDB OK"
    else
        echo -e "$REDIS_CHECK_RDB 33[0;32;31mnot exists or not executable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis.conf是否可用
    if test -r "$REDIS_CONF"; then
        echo -e "Checking $REDIS_CONF OK"
    else
        echo -e "$REDIS_CONF 33[0;32;31mnot exists or not readable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 检查redis-PORT.conf是否可用
    if test -r "$REDIS_PORT_CONF"; then
        echo -e "Checking $REDIS_PORT_CONF OK"
    else
        echo -e "$REDIS_PORT_CONF 33[0;32;31mnot exists or not readable33[m"
        echo -e "Exit now
    "
        exit 1
    fi
    
    # 解析redis_cluster.nodes文件,
    # 从而得到组成redis集群的所有节点。
    function parse_redis_cluster_nodes()
    {    
        redis_nodes_str=
        redis_nodes_ip_str=
        while read line
        do
            # 删除前尾空格
            line=`echo "$line" | xargs`
            if test -z "$line" -o "$line" = "#"; then
                continue
            fi
    
            # 跳过注释
            begin_char=${line:0:1}
            if test "$begin_char" = "#"; then
                continue
            fi
    
            # 取得IP和端口
            eval $(echo "$line" | awk -F[ :,;	]+ '{ printf("ip=%s
    port=%s
    ",$1,$2); }')
    
            # IP和端口都必须有
            if test ! -z "$ip" -a ! -z "$port"; then
                if test -z "$redis_nodes_ip_str"; then
                    redis_nodes_ip_str=$ip
                else
                    redis_nodes_ip_str="$redis_nodes_ip_str,$ip"
                fi
    
                if test -z "$redis_nodes_str"; then
                    redis_nodes_str="$ip:$port"
                else
                    redis_nodes_str="$redis_nodes_str,$ip:$port"
                fi          
            fi
        done < $REDIS_CLUSTER_NODES   
        
        if test -z "$redis_nodes_ip_str"; then
            num_nodes=0
        else
            # 得到IP数组redis_node_ip_array    
            redis_node_ip_array=`echo "$redis_nodes_ip_str" | tr ',' '
    ' | sort | uniq`
    
            # 得到节点数组redis_node_array
            redis_node_array=`echo "$redis_nodes_str" | tr ',' '
    ' | sort | uniq`
            
            for redis_node in ${redis_node_array[@]};
            do
                num_nodes=$((++num_nodes))
                echo "$redis_node"
            done
        fi
    }
    
    # check redis_cluster.nodes
    if test ! -r $REDIS_CLUSTER_NODES; then
        echo -e "File $REDIS_CLUSTER_NODES 33[0;32;31mnot exits33[m"
        echo ""
        echo -e "33[0;32;32mFile format33[m (columns delimited by space, tab, comma, semicolon or colon):"
        echo "IP1 port1"
        echo "IP2 port2"
        echo ""
        echo -e "33[0;32;32mExample33[m:"
        echo "127.0.0.1 6381"
        echo "127.0.0.1 6382"
        echo "127.0.0.1 6383"
        echo "127.0.0.1 6384"
        echo "127.0.0.1 6385"
        echo "127.0.0.1 6386"
        echo -e "Exit now
    "
        exit 1
    else    
        echo -e "33[0;32;32m"
        parse_redis_cluster_nodes
        echo -e "33[m"
    
        if test $num_nodes -lt 1; then
            echo -e "Checking $REDIS_CLUSTER_NODES 33[0;32;32mfailed33[m: no any node"
            echo -e "Exit now
    "
            exit 1
        else
            echo -e "Checking $REDIS_CLUSTER_NODES OK, the number of nodes is 33[1;33m${num_nodes}33[m"
        fi
    fi
    
    # 确认后再继续
    while true
    do
        # 组成一个redis集群至少需要六个节点
        if test $num_nodes -lt 6; then
            echo -e "33[0;32;32mAt least 6 nodes are required to create a redis cluster33[m"
        fi
    
        # 提示是否继续
        echo -en "Are you sure to continue? [33[1;33myes33[m/33[1;33mno33[m]"
        read -r -p " " input
    
        if test "$input" = "no"; then
            echo -e "Exit now
    "
            exit 1
        elif test "$input" = "yes"; then
            echo "Starting to install ..."
            echo ""
            break
        fi
    done
    
    # 是否先清空安装目录再安装?
    clear_install_directory=
    while true
    do
        echo -en "Clear install directory? [33[1;33myes33[m/33[1;33mno33[m]"
        read -r -p " " clear_install_directory
    
        if test "$clear_install_directory" = "no"; then
            echo ""
            break
        elif test "$clear_install_directory" = "yes"; then        
            echo ""
            break
        fi
    done
    
    # 安装公共的,包括可执行程序文件和公共配置文件
    function install_common()
    {
        redis_ip="$1"
        
        # 检查安装目录是否存在,且有读写权限
        echo "$MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="test -d $install_dir && test -r $install_dir && test -w $install_dir && test -x $install_dir""
        $MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="test -d $install_dir && test -r $install_dir && test -w $install_dir && test -x $install_dir"
        if test $? -ne 0; then
            echo ""
            echo -e "Directory $install_dir 33[1;33mnot exists or no (rwx) permission33[m"
            echo -e "Exit now
    "
            exit 1
        fi
    
        # 清空安装目录
        if test "$clear_install_directory" = "yes"; then
            echo ""
            echo "$MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="killall -q -w -u $install_user redis-server""
            $MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="killall -q -w -u $install_user redis-server"
    
            echo "$MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="rm -fr $install_dir/*""
            $MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="rm -fr $install_dir/*"
            if test $? -ne 0; then
                echo -e "Exit now
    "
                exit 1
            fi
        fi
    
        # 创建公共目录(create directory)
        echo ""
        echo "$MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="cd $install_dir;mkdir -p bin conf log data""
        $MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="cd $install_dir;mkdir -p bin conf log data"
        if test $? -ne 0; then
            echo -e "Exit now
    "
            exit 1
        fi
    
        # 上传公共配置文件(upload configuration files)
        echo ""
        echo "$MOOON_UPLOAD -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -s=redis.conf -d=$install_dir/conf"
        $MOOON_UPLOAD -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -s=redis.conf -d=$install_dir/conf 
        if test $? -ne 0; then
            echo -e "Exit now
    "
            exit 1
        fi
    
        # 上传公共执行文件(upload executable files)
        echo ""
        echo "$MOOON_UPLOAD -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -s=redis-server,redis-cli,redis-check-aof,redis-check-rdb -d=$install_dir/bin"    
        $MOOON_UPLOAD -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -s=redis-server,redis-cli,redis-check-aof,redis-check-rdb,redis-trib.rb -d=$install_dir/bin
        if test $? -ne 0; then
            echo -e "Exit now
    "
            exit 1
        fi
    }
    
    # 安装节点配置文件
    function install_node_conf()
    {
        redis_ip="$1"
        redis_port="$2"
    
        # 生成节点配置文件
        cp redis-PORT.conf redis-$redis_port.conf
        sed -i "s|INSTALLDIR|$install_dir|g;s|REDISPORT|$redis_port|g" redis-$redis_port.conf
    
        # 创建节点数据目录(create data directory for the given node)
        echo ""
        echo "$MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="cd $install_dir;mkdir -p data/$redis_port""
        $MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="cd $install_dir;mkdir -p data/$redis_port"
        if test $? -ne 0; then
            rm -f redis-$redis_port.conf
            echo -e "Exit now
    "
            exit 1
        fi
    
        # 上传节点配置文件(upload configuration files)
        echo ""
        echo "$MOOON_UPLOAD -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -s=redis-$redis_port.conf -d=$install_dir/conf"
        $MOOON_UPLOAD -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -s=redis-$redis_port.conf -d=$install_dir/conf    
        if test $? -ne 0; then
            rm -f redis-$redis_port.conf
            echo -e "Exit now
    "
            exit 1
        fi
    
        rm -f redis-$redis_port.conf
    }
    
    function start_redis_node()
    {
        redis_ip="$1"
        redis_port="$2"
    
        # 启动redis实例(start redis instance)
        echo ""
        echo "$MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="$install_dir/bin/redis-server $install_dir/conf/redis-$redis_port.conf""    
        $MOOON_SSH -h=$redis_ip -P=$ssh_port -u=$install_user -p=$install_user_password -c="nohup $install_dir/bin/redis-server $install_dir/conf/redis-$redis_port.conf > /dev/null 2>&1 &"
        if test $? -ne 0; then
            echo -e "Exit now
    "
            exit 1
        fi
    }
    
    # 安装公共的,包括可执行程序文件和公共配置文件
    echo ""
    echo -e "33[1;33m================================33[m"
    for redis_node_ip in $redis_node_ip_array;
    do
        echo -e "[33[1;33m$redis_node_ip33[m] Installing common ..."
        install_common $redis_node_ip
    done
    
    # 安装节点配置文件
    echo ""
    echo -e "33[1;33m================================33[m"
    for redis_node in ${redis_node_array[@]};
    do
        node_ip=
        node_port=
    
        eval $(echo "$redis_node" | awk -F[ :,;	]+ '{ printf("node_ip=%s
    node_port=%s
    ",$1,$2); }')
        if test -z "$node_ip" -o -z "$node_port"; then
            continue
        fi
        
        echo -e "[33[1;33m$node_ip:$node_port33[m] Installing node ..."
        install_node_conf $node_ip $node_port
    done
    
    # 确认后再继续
    echo ""
    echo -e "33[1;33m================================33[m"
    while true
    do
        echo -en "Start redis? [33[1;33myes33[m/33[1;33mno33[m]"
        read -r -p " " input
    
        if test "$input" = "no"; then
            echo ""
            exit 1
        elif test "$input" = "yes"; then
            echo "Starting to start redis ..."
            echo ""
            break
        fi
    done
    
    # 启动redis实例(start redis instance)
    for redis_node in ${redis_node_array[@]};
    do
        eval $(echo "$redis_node" | awk -F[ :,;	]+ '{ printf("node_ip=%s
    node_port=%s
    ",$1,$2); }')
        if test -z "$node_ip" -o -z "$node_port"; then
            continue
        fi
    
        echo -e "[33[1;33m$node_ip:$node_port33[m] Starting node ..."
        start_redis_node $node_ip $node_port
    done
    
    echo ""
    echo -e "33[1;33m================================33[m"
    echo "Number of nodes: $num_nodes"
    if test $num_nodes -lt 6; then
        echo "Number of nodes less than 6, can not create redis cluster"
        echo -e "Exit now
    "
        exit 1
    else
        redis_nodes_str=`echo "$redis_nodes_str" | tr ',' ' '`
    
        # 确认后再继续
        echo ""
        while true
        do
            echo -en "Create redis cluster? [33[1;33myes33[m/33[1;33mno33[m]"
            read -r -p " " input
    
            if test "$input" = "no"; then
                echo ""
                exit 1
            elif test "$input" = "yes"; then
                echo "Starting to create redis cluster with $redis_nodes_str ... ..."
                echo ""
                break
            fi
        done
    
        # 创建redis集群(create redis cluster)
        # redis-trib.rb create --replicas 1    
        $REDIS_TRIB create --replicas 1 $redis_nodes_str
        echo -e "Exit now
    "
        exit 0
    fi
    
  • 相关阅读:
    leetcode 746. 使用最小花费爬楼梯
    leetcode 474.一和零
    leetcode 221.最大正方形
    leetcode 525.连续数组
    leetcode 32.最长有效括号
    leetcode 46.全排列
    如何把word文档导入到数据库中——java POI
    leetcode 198.打家劫舍
    leetcode 581.最短无序连续子数组
    02需求工程-软件建模与分析阅读笔记之二
  • 原文地址:https://www.cnblogs.com/aquester/p/9891480.html
Copyright © 2020-2023  润新知