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.選擇復制偏移量最大的,也就是復制最完整的從節點。
二、節點規劃
節點 | 服務器 | IP | CPU | 內存 | 磁盤 | 版本 |
master | Almalinux | 10.0.20.176 | 8 | 16 | 150 | redis-7.4.2.tar.gz |
slave1 | Almalinux | 10.0.20.177 | 8 | 16 | 150 | redis-7.4.2.tar.gz |
slave2 | Almalinux | 10.0.20.178 | 8 | 16 | 150 | 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
歡迎一起交流