当前位置: 首页 > news >正文

Redis搭建哨兵模式一主两从三哨兵

Redis搭建哨兵模式一主两从三哨兵

目录

Redis搭建哨兵模式一主两从三哨兵

一、Redis哨兵模式

1. 哨兵模式原理:

2. 哨兵的作用:

3.哨兵的结构

4.故障转移机制

故障转移过程如下:

主节点的选举条件:

二、节点规划

三、实施部署

1.关闭防火墙安全内核机制,所有节点全部执行

2.分别修改主机名

3.修改所有节点hosts文件

4.主从部署

5.修改Master节点配置文件

6.修改slave1和slave2两个从节点

8.哨兵部署

9.启动哨兵模式所有节点都要启动

10.在master查看哨兵信息

总结


一、Redis哨兵模式

哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移

1. 哨兵模式原理:

哨兵:是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的Master。所以整个运行哨兵的集群的数量不得少于3个节点。

2. 哨兵的作用:

监控:哨兵会不断地检查主节点和从节点是否运作正常。

自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,他会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。

通知提醒:哨兵可以将故障转移的结果发送给客户端

3.哨兵的结构

哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点就是特殊的redis节点,不存储数据

数据节点:主节点和从节点都是数据节点

注意:

哨兵的启动依赖主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的Redis工作节点是否正常

4.故障转移机制

  由哨兵节点定期监控主节点是否出现了故障,每个哨兵节点每隔1秒会向主节点、从节点及其它哨兵节点发送一次ping命令做一次心跳检测。 如果主节点在一定时间范围内不回复或者是回复一个错误消息,那么这个哨兵就会认为这个主节点主观下线了(单方面的),当超过半数哨兵节点认为该主节点下线了,这样就客观下线了。 此时哨兵节点会通过Raft算法〈选举算法)实现选举机制共同选举出一个哨兵节点为leader,来负责处理主节点的故障转移和通知。

故障转移过程如下:

1.将某一个从节点升级为新的主节点,让其它从节点指向新的主节点;

2.若原主节点恢复也变成从节点,并指向新的主节点

3.通知客户端主节点已经更换

主节点的选举条件:

1.过滤掉不健康的(已下线的),没有回复哨兵ping响应的丛节点

2.选择配置文件中从节点优先级最高的(replication-priority,默认值为100)

3.选择复制偏移量最大的,也就是复制最完整的从节点。

二、节点规划

节点服务器IPCPU内存磁盘版本

master

Almalinux

10.0.20.176

816150

redis-7.4.2.tar.gz

slave1

Almalinux

10.0.20.177

816150

redis-7.4.2.tar.gz

slave2

Almalinux

10.0.20.178

816150

redis-7.4.2.tar.gz

三、实施部署

1.关闭防火墙安全内核机制,所有节点全部执行

[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0

2.分别修改主机名

[root@localhost ~]# hostnamectl set-hostname master && bash    #10.0.20.176
[root@localhost ~]# hostnamectl set-hostname slave1 && bash     #10.0.20.177
[root@localhost ~]# hostnamectl set-hostname slave2 && bash     #10.0.20.178

3.修改所有节点hosts文件

[root@master ~]#  cat >>/etc/hosts<< EOF
10.0.20.176 master
10.0.20.177 slave1
10.0.20.178 slave2
EOF

4.主从部署

所有节点源码编译安装redis(也可以使用下方一键安装脚本)

将源码包上传至/usr/local/src路径下

#!/bin/bash# ====== 配置变量 ======
REDIS_VERSION="7.4.2"
REDIS_PORT="63790"
REDIS_USER="redis"
REDIS_GROUP="redis"
REDIS_HOME="/usr/local/redis"
REDIS_DATA_DIR="/var/lib/redis"
REDIS_LOG_DIR="/var/log/redis"
REDIS_RUN_DIR="/var/run/redis"# ====== 颜色输出函数 ======
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Colorlog_info() {echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}log_warning() {echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}log_error() {echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" >&2
}# ====== 检查并安装依赖 ======
install_dependencies() {log_info "开始安装依赖包..."# 检查并安装tarif ! command -v tar &> /dev/null; thenyum -y install tarlog_info "已安装tar"elselog_info "tar已安装"fi# 检查并安装gccif ! command -v gcc &> /dev/null; thenyum -y install gcclog_info "已安装gcc"elselog_info "gcc已安装"fi# 检查gcc是否安装成功if ! command -v gcc &> /dev/null; thenlog_error "GCC安装失败,请检查YUM源配置"exit 1fi
}# ====== 配置系统参数 ======
configure_system() {log_info "配置系统参数..."# 配置内存过度分配if ! grep -q "vm.overcommit_memory = 1" /etc/sysctl.conf; thenecho "vm.overcommit_memory = 1" >> /etc/sysctl.confsysctl -plog_info "已配置内存过度分配策略"fi# 配置透明大页 (需要重启生效)if [ ! -f /etc/rc.d/rc.local ]; thenecho '#!/bin/bash' > /etc/rc.d/rc.localfichmod +x /etc/rc.d/rc.localif ! grep -q "transparent_hugepage" /etc/rc.d/rc.local; thenecho 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.locallog_info "已配置透明大页禁用(重启后生效)"fi
}# ====== 创建Redis用户和组 ======
create_redis_user() {log_info "创建Redis用户和组..."if ! getent group ${REDIS_GROUP} > /dev/null; thengroupadd -r ${REDIS_GROUP}log_info "已创建Redis组: ${REDIS_GROUP}"fiif ! id -u ${REDIS_USER} > /dev/null 2>&1; thenuseradd -r -g ${REDIS_GROUP} -s /sbin/nologin ${REDIS_USER}log_info "已创建Redis用户: ${REDIS_USER}"fi
}# ====== 安装Redis ======
install_redis() {log_info "开始安装Redis ${REDIS_VERSION}..."# 检查Redis源码包是否存在if [ ! -f "/usr/local/src/redis-${REDIS_VERSION}.tar.gz" ]; thenlog_error "Redis源码包不存在: /usr/local/src/redis-${REDIS_VERSION}.tar.gz"exit 1fi# 解压Redis源码tar -zxf "/usr/local/src/redis-${REDIS_VERSION}.tar.gz" -C /usr/localif [ $? -ne 0 ]; thenlog_error "解压Redis源码包失败"exit 1fi# 重命名目录mv "/usr/local/redis-${REDIS_VERSION}" "${REDIS_HOME}"# 编译安装Rediscd "${REDIS_HOME}"make MALLOC=libcif [ $? -ne 0 ]; thenlog_error "Redis编译失败"exit 1ficd "${REDIS_HOME}/src"make install PREFIX="${REDIS_HOME}"if [ $? -ne 0 ]; thenlog_error "Redis安装失败"exit 1filog_info "Redis ${REDIS_VERSION} 安装成功"
}# ====== 配置Redis ======
configure_redis() {log_info "配置Redis..."# 创建数据和日志目录mkdir -p ${REDIS_DATA_DIR} ${REDIS_LOG_DIR} ${REDIS_RUN_DIR}chown -R ${REDIS_USER}:${REDIS_GROUP} ${REDIS_DATA_DIR} ${REDIS_LOG_DIR} ${REDIS_RUN_DIR}chmod -R 755 ${REDIS_DATA_DIR} ${REDIS_LOG_DIR} ${REDIS_RUN_DIR}# 修改Redis配置文件if [ -f "${REDIS_HOME}/redis.conf" ]; then# 备份原始配置文件cp "${REDIS_HOME}/redis.conf" "${REDIS_HOME}/redis.conf.bak"# 应用配置修改sed -i 's/^bind 127.0.0.1/bind 0.0.0.0/g' "${REDIS_HOME}/redis.conf"   # 开放对外链接sed -i 's/daemonize no/daemonize yes/' "${REDIS_HOME}/redis.conf"      # 守护进程方式启动sed -i 's/protected-mode yes/protected-mode no/' "${REDIS_HOME}/redis.conf"   # 开放外部访问sed -i "s/port 6379/port ${REDIS_PORT}/" "${REDIS_HOME}/redis.conf"    # 修改端口号# 添加额外配置echo "dir ${REDIS_DATA_DIR}" >> "${REDIS_HOME}/redis.conf"echo "logfile ${REDIS_LOG_DIR}/redis.log" >> "${REDIS_HOME}/redis.conf"echo "pidfile ${REDIS_RUN_DIR}/redis.pid" >> "${REDIS_HOME}/redis.conf"# 设置配置文件权限chown ${REDIS_USER}:${REDIS_GROUP} "${REDIS_HOME}/redis.conf"chmod 644 "${REDIS_HOME}/redis.conf"log_info "Redis配置已完成"elselog_error "Redis配置文件不存在: ${REDIS_HOME}/redis.conf"exit 1fi
}# ====== 创建Systemd服务 ======
create_systemd_service() {log_info "创建Systemd服务..."cat > /etc/systemd/system/redis.service << EOF
[Unit]
Description=Redis In-Memory Data Store
Documentation=https://redis.io/documentation
After=network.target[Service]
Type=forking
User=${REDIS_USER}
Group=${REDIS_GROUP}
PIDFile=${REDIS_RUN_DIR}/redis.pid
ExecStart=${REDIS_HOME}/bin/redis-server ${REDIS_HOME}/redis.conf
ExecStop=${REDIS_HOME}/bin/redis-cli -h 127.0.0.1 -p ${REDIS_PORT} shutdown
Restart=always
RestartSec=3
LimitNOFILE=65535
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
PrivateTmp=true[Install]
WantedBy=multi-user.target
EOF# 重新加载Systemd配置systemctl daemon-reloadlog_info "Systemd服务已创建"
}# ====== 创建符号链接 ======
create_symlinks() {log_info "创建符号链接..."ln -sf "${REDIS_HOME}/bin/redis-cli" /usr/local/sbin/redis-cliln -sf "${REDIS_HOME}/bin/redis-server" /usr/local/sbin/redis-server# 添加到PATH环境变量if ! grep -q "${REDIS_HOME}/bin" /etc/profile; thenecho "export PATH=\${PATH}:${REDIS_HOME}/bin" >> /etc/profilesource /etc/profilefilog_info "符号链接已创建"
}# ====== 配置防火墙 ======
configure_firewall() {log_info "配置防火墙..."if systemctl is-active --quiet firewalld; thenfirewall-cmd --permanent --add-port=${REDIS_PORT}/tcpfirewall-cmd --reloadlog_info "已放行TCP ${REDIS_PORT}端口"elselog_warning "firewalld未运行,跳过端口放行"fi
}# ====== 启动Redis服务 ======
start_redis_service() {log_info "启动Redis服务..."# 设置目录权限chown -R ${REDIS_USER}:${REDIS_GROUP} ${REDIS_HOME}# 启动并启用服务systemctl start redissystemctl enable redis# 检查服务状态sleep 2  # 等待服务启动if systemctl is-active --quiet redis; thenlog_info "Redis服务启动成功"systemctl status redis --no-pagerelselog_error "Redis服务启动失败"journalctl -u redis --since "1 minute ago" --no-pagerexit 1fi
}# ====== 安装后提示 ======
post_install_info() {echo ""log_info "========== Redis 安装完成 =========="log_info "版本: Redis ${REDIS_VERSION}"log_info "端口: ${REDIS_PORT}"log_info "配置文件: ${REDIS_HOME}/redis.conf"log_info "数据目录: ${REDIS_DATA_DIR}"log_info "日志文件: ${REDIS_LOG_DIR}/redis.log"log_info "管理命令:"log_info "  启动: systemctl start redis"log_info "  停止: systemctl stop redis"log_info "  状态: systemctl status redis"log_info "  连接: redis-cli -p ${REDIS_PORT}"echo ""log_warning "注意: 当前配置未设置密码,生产环境请设置requirepass"log_warning "      修改配置文件: ${REDIS_HOME}/redis.conf"log_warning "      取消注释: # requirepass foobared 并设置强密码"echo ""
}# ====== 主执行流程 ======
main() {log_info "开始Redis安装流程"# 检查root权限if [ "$(id -u)" != "0" ]; thenlog_error "此脚本必须使用root权限运行"exit 1fi# 执行安装步骤install_dependenciesconfigure_systemcreate_redis_userinstall_redisconfigure_rediscreate_systemd_servicecreate_symlinksconfigure_firewallstart_redis_servicepost_install_infolog_info "Redis安装完成"
}# 执行主函数
main "$@"

执行流程:

[root@master ~]# touch install_redis.sh       #创建脚本文件&&脚本插入进去
[root@master ~]# chmod +x install_redis.sh    #给予执行权限
[root@master ~]# ./install_redis.sh           #执行

预计输出

5.修改Master节点配置文件

[root@master ~]# cp /usr/local/redis/redis.conf redis.conf.bak     #备份(好习惯)
[root@master ~]# vi /usr/local/redis/redis.conf
bind 0.0.0.0                 #88行,注释掉bind项,或修改0.0.0.0默认监听所有端口
daemonize yes               #310行,开启守护进程
logfile /var/log/redis/redis.log   #356行,指定日志文件目录
dir /var/lib/redis              #516行,指定工作目录
# requirepass 密码           #1050行,指定redis登录密码,可不设置
#重启redis
[root@master redis]# systemctl restart redis

6.修改slave1和slave2两个从节点

[root@slave1 ~]# cp /usr/local/redis/redis.conf redis.conf.bak
[root@slave1 ~]# vi /usr/local/redis/redis.conf
bind 0.0.0.0                 #88行,注释掉bind项,或修改0.0.0.0默认监听所有端口
daemonize yes               #310行,开启守护进程
logfile /var/log/redis/redis.log   #356行,指定日志文件目录
dir /var/lib/redis              #516行,指定工作目录
replicaof 10.0.20.176 63790     #539行,指定主节点的ip和端口#重启slave1节点和slave2节点redis服务
[root@slave1 ~]# systemctl restart redis
[root@slave2 ~]# systemctl restart redis

7.验证主从效果

[root@master redis]# tail -f /var/log/redis/redis.log
[root@master redis]# redis-cli -p 63790    #登录redis
127.0.0.1:63790> info replication         #查看
127.0.0.1:63790> set k1 1               #在主库创建文件在从库查看
OK
127.0.0.1:63790> get k1                 #存在
"1"
127.0.0.1:63790> 

在master上动态查看日志:

在master上验证从节点

8.哨兵部署

[root@master ~]# cd /usr/local/redis
[root@master redis]# ll

修改哨兵模式的配置文件(所有节点操作)

[root@master ~]# cp /usr/local/redis/sentinel.conf sentinel.conf.bak  #备份protected-mode no             #6行,关闭保护模式
port 26379                    #10行,哨兵默认端口号
daemonize yes                 #15行,开启后台运行
logfile /var/log/redis/sentinel.log   #34行,指定日志目录
dir /var/lib/redis                 #73行,数据文件#92行,改变master节点地址,指定哨兵节点监控10.0.20.176:63790这个主节点
sentinel monitor mymaster 10.0.20.176 63790 2#133行,可以修改时间,判定服务器down掉的时间周期,默认30000毫秒(30秒)
sentinel down-after-milliseconds mymaster 30000#233行,故障切换时间,故障节点的最大超时时间为180000(180秒)
sentinel failover-timeout mymaster 180000

9.启动哨兵模式所有节点都要启动

#注意:先启动主节点,在启从节点

[root@master redis]# /usr/local/redis/src/redis-sentinel sentinel.conf &
[1]13569
[root@slave1 redis]# /usr/local/redis/src/redis-sentinel sentinel.conf &
[1] 13496
[root@slave2 redis]# /usr/local/redis/src/redis-sentinel sentinel.conf &
[1] 13754

10.在master查看哨兵信息

所有节点都可以查看哨兵info sentinel

[root@master redis]# redis-cli -p 26379 info Sentinel

11.验证哨兵,模拟故障

[root@master redis]# ps -ef |grep redis
[root@master redis]# systemctl stop redis
[root@master redis]# tail -f /var/log/redis/sentinel.log

在Slave1上查看是否转换成功

[root@slave1 redis]#  redis-cli -p 26379 INFO Sentinel

在slave2上查看是否转换成功

[root@slave2 redis]#  redis-cli -p 26379 INFO Sentinel

当原来的master修复后会做为slave从新加入

[root@master redis]# redis-cli -p 26379
127.0.0.1:26379> info

将权重值调成默认方便下次选举

总结

哨兵系统中的主从节点,与普通的主从节点并没有什么区别,故障发现和转移是由哨兵来控制和完成的。

哨兵节点本质上是Redis节点.

每个哨兵节点,只需要配置监控主节点,便可以自动发现其他的哨兵节点和从节点.

在哨兵节点启动和故障转移阶段,各个节点的配置文件会被重写(Config Rewrite)。

故障转移分三步

1.从下线的主服务的所有从服务里面挑选一个从服务, 将其转成主服务

2.已下线主服务的所有从服务改为复制新的主服务 挑选出新的主服务之后,领头sentinel 向原主服务的从服务发送 slaveof 新主服务 的命令,复制新master。

3.将已下线的主服务设置成新的主服务的从服务, 当其回复正常时,复制新的主服务,变成新的主服务的从服务 当已下线的服务重新上线时,sentinel会向其发送slaveof命令, 让其成为新主的从。

查看[root@master redis-5.0.9]下的master节点信息
sentinel master imooc-master查看[root@master redis-5.0.9]下的slaves节点信息
sentinel slaves imooc-master

欢迎一起交流

http://www.xdnf.cn/news/1395307.html

相关文章:

  • 线程安全及死锁问题
  • 【好题推荐】运算符的构造运用
  • 光伏发多少电才够用?匹配家庭用电需求
  • #医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(五)
  • Linux内核进程管理子系统有什么第三十八回 —— 进程主结构详解(34)
  • JUC并发编程09 - 内存(01) - JMM/cache
  • 嵌入式Linux设备树驱动开发 - dtsof驱动
  • Unity DateTime 相关
  • 处理器(CPU/MPU)的双发射是什么?
  • 命令扩展与重定向
  • 可解释人工智能XAI
  • 【机器学习深度学习】Embedding 与 RAG:让 AI 更“聪明”的秘密
  • leetcode 191 位1的个数
  • 【0422】SMgrRelationData 中 md_num_open_segs 和 md_seg_fds 数组为什么是 4 个元素? 第四个元素表示什么?
  • Ubuntu磁盘分区重新挂载读写指南
  • 不一样的发票管理模式-发票识别+发票查验接口
  • ContextMenuManager for Win:优化右键菜单,解决用户痛点
  • lxml库如何使用
  • ElasticSearch对比Solr
  • C语言————操作符详解
  • TypeScript的Type
  • MySQL 中如果发生死锁应该如何解决?
  • 每日算法题【二叉树】:对称二叉树、二叉树的前中后序遍历
  • 回车换行、缓冲区刷新、倒计时小程序
  • MQTT高延迟通信优化指南
  • Python的Listd 数据格式 V0.1
  • 深入解析Nginx核心模块
  • DAY 17 常见聚类算法-2025.8.29
  • 将数据赋值到多个文档里,并将多个word放入压缩包并下载
  • 非标设计 机架模板 misumi 设计组合案例