第二十一周作业

1、简述redis集群的实现原理

  • 开启cluster功能的redis节点间,通过使用ping机制互通并通告自己的hash slots,通过Gossip协议通告各自所知的其他node的信息,然后建立连接。

  • 集群中某个节点是否失效是通过集群中超过半数节点的探测都失效来决定的,因此为了避免出现脑裂(偶数节点之间是否sdown的投票出现均分),redis cluster的Master节点最少数目是3个

  • redis集群支持16384个hash slot,存储key时,crc16校验算法根据key值计算出校验值,然后取模16384,得到的结果落在0-16383之间的某个slot上,集群中的Master节点会分配0-16383中某一段范围的slot,key会根据slot存储在对应的Master节点上。

  • 由于每个Master节点都只存储一定范围内的slot,因此存在slot的单点故障,需要通过主从复制实现Master节点的高可用;但集群复制只能支持一层,不支持树形复制结构,也不支持级联复制;

  • 客户端通过跨集群命令,将key写入到集群的任意节点,节点根据计算得到key对应的slot,判断如果slot指向自身,则直接执行命令;否则节点会返回客户端MOVED重定向,客户端将命令重定向发送给目标节点。

2、基于redis5的redis cluster部署

按照如下脚本,完成1,2项redis的安装和配置:

#!/bin/bash
#****************************************************************************************#
#Author:                        Yabao11
#QQ:                            what QQ,no QQ
#Date:                          2022-01-04
#FileName:                      nginx.sh
#URL:                           https://github.com/yabao11
#Description:                   Test Script
#Copyright (C):                 2022 All rights reserved
#*******************************定义颜色*************************************************#
RED="\e[1;31m"
GREEN="\e[1;32m"
SKYBLUE="\e[1;36m"
YELLOW="\e[1;43m"
BLUE="\e[1;44m"
END="\e[0m"
RandomColor="\e[1;32m"
#****************************************************************************************#
function Ostype {
    if grep -i -q "release 6" /etc/centos-release;then
      echo Centos6
    elif grep -i -q Centos-8 /etc/os-release;then
      echo Centos
    elif grep -i -q Centos-7 /etc/os-release;then
      echo Centos7
    elif grep -i -q Ubuntu /etc/os-release;then
      echo Ubuntu
    elif grep -i -q "RedHat" /etc/os-release;then
      echo Redhat
    fi
}

function color {
  RES_COL=60
  MOVE_TO_COL="echo -en \E[${RES_COL}G"
  SETCOLOR_SUCCESS="echo -en \E[1;32m"
  SETCOLOR_FAILURE="echo -en \E[1;31m"
  SETCOLOR_WARNING="echo -en \E[1;33m"
  SETCOLOR_NORMAL="echo -en \E[0m"
  echo -n "$1" && $MOVE_TO_COL
  echo -n "["
  if [[ $2 = "success" || $2 = "0" ]]; then
    ${SETCOLOR_SUCCESS}
    echo -n "  OK  "
  elif [[ $2 = "failure" || $2 = "1" ]]; then
    ${SETCOLOR_FAILURE}
    echo -n "FAILED"
  else
    ${SETCOLOR_WARNING}
    echo -n "WARNING"
  fi
  ${SETCOLOR_NORMAL}
  echo -n "]"
  echo
}

function redis_install {
    echo -e $GREEN"关闭selinux..."$END
    setenforce 0
    sed -i.bak -r 's|SELINUX=enforcing|SELINUX=disabled|' /etc/selinux/config
    systemctl disable --now firewalld && color "firewalld已关闭" 0
    yum  -y install gcc jemalloc-devel systemd-devel wget || { color "编译软件安装失败!" 1;exit; }
    [ -e /root/${redis_version}.tar.gz ] || wget http://download.redis.io/releases/${redis_version}.tar.gz -P /root/
    tar xvf ${redis_version}.tar.gz || { color "文件解压失败" 1;exit; }
    cd ${redis_version}
    make USE_SYSTEMD=yes PREFIX=${redis_path} install > /dev.null && color "安装成功" 0 || color "安装失败,检查配置参数" 1
    echo 'PATH=/data/redis/bin:$PATH' > /etc/profile.d/redis.sh
    . /etc/profile.d/redis.sh
    id redis || ( useradd -r -s /sbin/nologin redis && color "新增用户redis" 0 || color "用户redis新建失败" 1 )
    mkdir /data/redis/{etc,log,data,run}
    { cp redis.conf ${redis_path}/etc/;cp sentinel.conf ${redis_path}/etc/; } && color "配置文件复制完成" 0
    chown -R redis.redis ${redis_path} && color "文件权限修改完毕" 0 || color "文件权限修改失败" 1
    cat >> /etc/sysctl.conf <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
    sysctl -p && color "全连接队列和内存超额分配内核参数修改完成" 0 || color "内核参数修改失败" 1
    echo never > /sys/kernel/mm/transparent_hugepage/enabled && color "关闭THP(透明大页)" 0 || "关闭THP失败" 1
    echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local
    chmod +x /etc/rc.d/rc.local
    [ -e /lib/systemd/system/redis@.service ] && rm -rf /lib/systemd/system/redis@.service
    cat > /lib/systemd/system/redis@.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=${redis_path}/bin/redis-server ${redis_path}/etc/%i.conf --supervised systemd
#ExecStop=/usr/libexec/redis-shutdown
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable --now redis@redis
}

function redis_config {
    sed -i.bak -r -e 's/(^bind\s).*/\10.0.0.0/' \
    -e 's/daemonize no/daemonize yes/' \
    -e 's|^pidfile.*|pidfile '${redis_path}'/run/redis.pid|' \
    -e 's|^logfile.*|logfile '${redis_path}'/log/redis.log|' \
    -e 's|^dir.*|dir '${redis_path}'/data|' \
    ${redis_path}/etc/redis.conf && color "redis.conf配置文件修改完毕!" 0
    systemctl restart redis@redis
}

function redis_slave {
    while true;do
        read -p "是否需要将当前节点配置为slave节点?" askuser1
        askuser1=`echo $askuser1 | tr 'A-Z' 'a-z'`
        case $askuser1 in
        y|yes)
            read -p "输入主节点IP地址:" slaveip
            if [ -z ${slaveip} ];then
                while [ -z ${slaveip} ];do
                    read -p "请输入主节点IP地址:" slaveip
                done
            fi
            echo "replicaof ${slaveip} 6379" >>  /data/redis/etc/redis.conf && color "redis.conf配置文件修改完毕!" 0
            systemctl restart redis@redis && color "服务重启完成!" 0
            break
        ;;
        n|no)
            break
        ;;
        *)
            inputerror
            continue
        ;;
        esac
    done
}

function sentinel_config {
    read -p "输入主节点IP地址:" masterip
    if [ -z ${masterip} ];then
        while [ -z ${masterip} ];do
            read -p "请输入主节点IP地址:" masterip
        done
    fi
    sed -i.bak -r -e '/#\s+bind\s+127.0.0.1/ibind 0.0.0.0' \
    -e 's|^daemonize.*|daemonize yes|' \
    -e 's|^logfile.*|logfile '${redis_path}'/log/redis-sentinel.log|' \
    -e 's|^sentinel\smonitor\smymaster.*|sentinel monitor mymaster '${masterip}' 6379 2|' \
    -e 's|^sentinel\sdown-after-milliseconds.*|sentinel down-after-milliseconds mymaster 3000|' \
    ${redis_path}/etc/sentinel.conf && color "sentinel配置文件修改成功!" 0
    cat > /lib/systemd/system/redis-sentinel.service <<EOF
[Unit]
Description=Redis Sentinel
After=network.target

[Service]
ExecStart=${redis_path}/bin/redis-sentinel ${redis_path}/etc/sentinel.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
User=redis
Group=redis
Type=notify
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl restart redis-sentinel.service
}

    read -p "请输入希望安装的redis版本,回车使用默认版本:redis-6.2.6" redis
    read -p "请输入希望安装的redis路径,回车使用默认路径:/data/redis" predis
    redis_version=${redis:-redis-6.2.6}
    redis_path=${predis:-/data/redis}

#exec
PS3="请选择您要执行的操作!:"
MENU="
安装redis
配置redis
配置为从节点
配置sentinel
退出
"
select M in $MENU ;do
    case $REPLY in
        1)
            redis_install
        ;;
        2)
            redis_config
        ;;
        3)
            redis_slave
        ;;
        4)
            sentinel_config
        ;;
        *)
        exit
        ;;
    esac
done

开启cluster

sed -i.bak -e 's/bind 127.0.0.1/bind 0.0.0.0/' \
-e '/# cluster-enabled yes/a cluster-enabled yes' \
-e '/# cluster-config-file nodes-6379.conf/a cluster-config-file /data/redis/etc/nodes-6379.conf' \
-e '/cluster-require-full-coverage yes/c cluster-require-full-coverage no' /data/redis/etc/redis.conf

使用redis-cli创建cluster

redis-cli --cluster create 192.168.32.187:6379 192.168.32.188:6379 192.168.32.189:6379 <<EOF
yes
EOF

#6台机器的主备部署参考如下配置,前三台是master,后三台一一对应前三台作为slave,同时hash slot也会均匀分布到三台master
#redis-cli --cluster create 10.0.0.8:6379 10.0.0.18:6379 10.0.0.28:6379 10.0.0.38:6379 10.0.0.48:6379 10.0.0.58:6379 --cluster-replicas 1

结果确认

[root@centos8mini ~]# redis-cli cluster nodes
a9576816037f5f6f103def47473ce8a63c095e9e 192.168.32.188:6379@16379 master - 0 1644374438466 2 connected 5461-10922
df7e0425f345c1bc494c350be88cb1d73acb1932 192.168.32.187:6379@16379 myself,master - 0 1644374434000 1 connected 0-5460
4054278384642524b50caa222820b77fd51f02b0 192.168.32.189:6379@16379 master - 0 1644374437446 3 connected 10923-16383
[root@centos8mini ~]# redis-cli cluster info
cluster_state:ok
cluster_slots_assigned:16384  #分配的hash slot
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3  #3个节点
cluster_size:3  #3台master
cluster_current_epoch:3
cluster_my_epoch:1
cluster_stats_messages_ping_sent:78
cluster_stats_messages_pong_sent:73
cluster_stats_messages_sent:151
cluster_stats_messages_ping_received:71
cluster_stats_messages_pong_received:78
cluster_stats_messages_meet_received:2
cluster_stats_messages_received:151

[root@centos8mini ~]# redis-cli -c set k1 v1
OK
[root@centos8mini ~]# redis-cli -c set k2 v2
OK
[root@centos8mini ~]# redis-cli -c set k3 v2
OK
[root@centos8mini ~]# redis-cli -c set k3 v3
OK
[root@centos8mini ~]# redis-cli -c get k1
"v1"
[root@centos8mini ~]# redis-cli -c get k2
"v2"
[root@centos8mini ~]# redis-cli -c get k3
"v3"

[root@centos8mini ~]# redis-cli --cluster info 192.168.32.187:6379
192.168.32.187:6379 (df7e0425...) -> 3 keys | 5461 slots | 0 slaves.
192.168.32.188:6379 (a9576816...) -> 1 keys | 5462 slots | 0 slaves.
192.168.32.189:6379 (40542783...) -> 2 keys | 5461 slots | 0 slaves.
[OK] 6 keys in 3 masters.
0.00 keys per slot on average.
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • ▲就业班和全程班的小伙伴看这里:(学习老王视频的作业第41节) 配置nginx反向代理,实现api.x.com域名...
    一心1977阅读 181评论 0 0
  • 本周学习书籍:《乌合之众》— 【中】沐风 整理人:路痴鱼-20180204 一、作业说明: 1.作业要求:自由命题...
    路痴鱼阅读 155评论 0 0
  • 1.集群与分布式的概述 1.1 分布式 分布式是指将不同的业务分布在不同的地方. web应用和数据库服务分开 1....
    程序员Darker阅读 454评论 1 1
  • redis最开始使用主从模式做集群,若master宕机需要手动配置slave转为master;后来为了高可用提出来...
    学编程的小屁孩阅读 320评论 0 0
  • 1、简述PV,UV,QPS的含义及计算方式 PV(访问量):既Page View,页面浏览或点击量,用户每次刷新即...
    阿杜ddq阅读 342评论 0 0