Redis-主从复制部署记录

Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步

主从模式介绍

作用

  1. 数据冗余:主从复制实现数据热备份,是持久化之外的数据冗余方式。
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速故障恢复。
  3. 负载均衡:在主从复制基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务
    (即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是
    在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  4. 读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,
    同时可根据需求的变化,改变从库的数量;
  5. 高可用:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用基础

工作原理

  1. 连接并发送 SYNC 命令:从库通过执行 SLAVEOF 10.0.0.31 6379 命令连接到主库,并发送 SYNC 命令给主库。
  2. 生成并发送 RDB 快照:主库接收到 SYNC 命令后,会立即触发 BGSAVE 命令,在后台生成 RDB 快照,并将该快照发送给从库。
  3. 应用 RDB 快照:从库接收并应用 RDB 快照,更新自身的数据。
  4. 同步新操作:主库将生成快照期间的新操作记录下来,并陆续发送给从库。
  5. 正常运行:完成上述步骤后,主从复制集开始正常工作。
  6. 命令传播:之后,主库发生的任何新操作都会自动以命令形式发送给从库,以保持数据同步。
  7. 查看复制信息:所有与复制相关的信息都可以通过 INFO 命令查询,即使重启任何节点,主从关系依然存在。
  8. 处理断开重连:如果主从关系断开,从库的数据不会受损。在重新连接后,从库发送 PSYNC 命令给主库。
  9. 增量同步:主库只会将从库缺失的数据部分同步给从库,以快速恢复主从架构的同步状态。

image.png

全量同步

Redis 全量复制通常发生在从节点初始化阶段,此时从节点需要将主节点上的所有数据复制一份。具体步骤如下:

  1. 连接并发送 SYNC 命令:从节点连接到主节点,并发送 SYNC 命令请求全量同步。
  2. 生成 RDB 文件:主节点接收到 SYNC 命令后,执行 BGSAVE 命令生成 RDB 文件,并使用缓冲区记录此后执行的所有写命令。
  3. 发送快照文件:主节点 BGSAVE 执行完毕后,向所有从节点发送生成的快照文件。在此期间,主节点继续记录新的写命令。
  4. 从节点载入快照:从节点收到快照文件后,丢弃所有旧数据,并载入新的快照。
  5. 发送缓冲区写命令:主节点发送完快照文件后,开始向从节点发送缓冲区中记录的写命令。
  6. 从节点同步命令:从节点完成快照的载入后,开始接收并执行来自主节点缓冲区中的写命令。

增量同步

Redis 增量复制指的是当从节点初始化后正常工作时,将主节点发生的写操作同步到从节点的过程。具体步骤如下:

  1. 建立复制连接:从节点与主节点建立复制连接。
  2. 发送 PSYNC 命令:从节点通过发送 PSYNC 命令请求进行增量同步。
  3. 增量复制过程:在增量复制过程中,主节点每执行一个写操作,就会将相同的写命令发送给从节点,从节点接收并执行这些写命令。

主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
**需要注意: **如果多个Slave断线了,需重启时,因为只要Slave启动,就会发送sync请求和主机全量同步,当多个同时出现的时候,可能会导致Master IO剧增宕机

主库是否要开启持久化?

1)为了缓解主redis服务器写磁盘压力带来的开销,可以配置让主redis不将将数据持久化到磁盘,
而是通过连接让一个配置的从redis服务器及时的将相关数据持久化到磁盘,不过这样会存在一个问题,
就是主redis服务器一旦重启,因为主redis服务器数据为空,这时候通过主从同步可能导致从redis
服务器上的数据也被清空;
2)主库要开持久化,主redis服务器写磁盘压力带来的开销,重启数据不会丢失。

生产环境中,建议开启master库持久化功能,避免因主库意外重启而导致缓存丢失。举个例子,master库有1w条数据,replica库在某一时刻仅有9k数据,还有1k数据未来得及同步master库时,master库意外重启导致KEY为0,此时replica库同步master库数据会将replica库已有的9k缓存数据删除以达到和master库同步的目的

主从搭建过程

主机规划

操作系统 IP 主机名 关系 CPU/内存 版本
麒麟信安3.3 10.0.0.31 redis1 2核+2G 6.2.6
麒麟信安3.3 10.0.0.32 redis2 2核+2G 6.2.6
麒麟信安3.3 10.0.0.33 redis3 2核+2G 6.2.6

下载redis

wget http://download.redis.io/releases/redis-6.2.6.tar.gz

安装依赖

yum -y install gcc automake autoconf libtool make

关闭防火墙

1.#闭防火墙、selinux、dnsmasq/NetworkManager
systemctl disable --now firewalld
systemctl disable --now dnsmasq
systemctl disable --now NetworkManager

setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
#检查
grep ^SELINUX= /etc/selinux/config

编译安装redis

tar xf redis-6.2.6.tar.gz
mv redis-6.2.6 /usr/local/redis

cd /usr/local/redis
make

所有主机配置环境变量

#/usr/local/redis/src
cat>>/etc/profile<<'EOF' 
export PATH=/usr/local/redis/src:$PATH
EOF
tail -1 /etc/profile 
source /etc/profile 
echo $PATH

所有主机创建Redis的数据存储目录

 mkdir /data/6379/ -p

所有主机创建配置文件

  • 31配置文件
cat > /data/6379/redis.conf <<EOF
port 6379
bind 10.0.0.31 127.0.0.1
daemonize yes
pidfile /data/6379/redis.pid
loglevel notice
logfile "/data/6379/redis.log"
dbfilename dump.rdb
dir /data/6379
requirepass 123
masterauth 123
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
# 配置AOF持久化
appendonly yes
appendfsync everysec
EOF
  • 32 配置文件
cat > /data/6379/redis.conf <<EOF
port 6379
bind 10.0.0.32 127.0.0.1
daemonize yes
pidfile /data/6379/redis.pid
loglevel notice
logfile "/data/6379/redis.log"
dbfilename dump.rdb
dir /data/6379
requirepass 123
masterauth 123
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
# 配置AOF持久化
appendonly yes
appendfsync everysec
EOF
  • 33配置文件
cat > /data/6379/redis.conf <<EOF
port 6379
bind 10.0.0.33 127.0.0.1
daemonize yes
pidfile /data/6379/redis.pid
loglevel notice
logfile "/data/6379/redis.log"
dbfilename dump.rdb
dir /data/6379
requirepass 123
masterauth 123
# 配置RDB持久化策略
save 900 1
save 300 10
save 60 10000
# 配置AOF持久化
appendonly yes
appendfsync everysec
EOF

启动redis

redis-server /data/6379/redis.conf 
netstat  -lantup | grep 6379
  • 脚本管理
#!/bin/bash
REDIS_CONFIG_PATH=/data/6379/redis.conf
choice=$1

start(){
 echo "开始启动redis"
 PID=$(ps -ef | grep redis-server | grep -v grep | wc -l)
 if [ $PID -eq 0 ]; then
   /usr/local/redis/src/redis-server $REDIS_CONFIG_PATH
   sleep 2
   echo "redis启动成功"
 else
   echo "redis已启动"
 fi
}

stop(){
 echo "开始停止redis"
 PID=$(ps -ef | grep redis-server | grep -v grep | wc -l)
 if [ $PID -eq 1 ]; then
   redis-cli -h 127.0.0.1 -p 6379 -a 123 shutdown
   sleep 2
   echo "redis停止成功"
 else
   echo "redis已停止"
 fi
}

case "$choice" in
   start)
    start
    ;;
   stop)
    stop
    ;;
   restart)
    stop
    start
    ;;
   *)
    echo "请输入正确的格式: sh $0 {start|stop|restart}"
    ;;
esac

使用system管理

cat >/usr/lib/systemd/system/redis.service<<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
ExecStart=/usr/local/redis/src/redis-server /data/6379/redis.conf --supervised systemd
ExecStop=/usr/local/redis/src/redis-cli shutdown
Type=notify
User=root
Group=root
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now redis.service
systemctl status  redis.service
netstat  -lantup | grep 6379

启动警告处理

echo '511' > /proc/sys/net/core/somaxconn
echo never > /sys/kernel/mm/transparent_hugepage/enabled
ulimit -SHn 65535
echo "*    -    nofile  65535" >>/etc/security/limits.conf  #永久生效

开启主从

以"31"实例为主库,以"32"实例和"33"实例为从库。

从库开启主从

  • 32从库执行
redis-cli -h 10.0.0.32 -p  6379 -a 123 SLAVEOF 10.0.0.31 6379

image.png

  • 33从库执行
redis-cli  -h 10.0.0.33 -p 6379 -a 123 SLAVEOF 10.0.0.31 6379

image.png

主库查看主从信息

[服务未授权][root@redis1 6379]# redis-cli -p 6379 -a 123 INFO REPLICATION
# Replication
role:master
connected_slaves:2
slave0:ip=10.0.0.32,port=6379,state=online,offset=770,lag=0
slave1:ip=10.0.0.33,port=6379,state=online,offset=770,lag=0
master_failover_state:no-failover
master_replid:66003cae539c0cfa8239c8c4580a7a2561cfa1a9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:770
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:770

从库查看主从信息

[服务未授权][root@redis2 ~]# redis-cli -p 6379 -a 123 INFO REPLICATION
# Replication
role:slave
master_host:10.0.0.31
master_port:6379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_read_repl_offset:854
slave_repl_offset:854
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:66003cae539c0cfa8239c8c4580a7a2561cfa1a9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:854
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:854

验证主从配置是否生效

  • 在"redis31"实例主库创建测试数据
[服务未授权][root@redis1 6379]# redis-cli -p 6379 -a 123 
127.0.0.1:6379> 
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set name jiajia
OK
127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> 

image.png

  • 在"31"实例和"32"实例从库查看数据是否同步
[服务未授权][root@redis2 ~]# redis-cli -p 6379 -a 123 
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name
"jiajia"
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> 

[服务未授权][root@redis3 ~]# redis-cli -p 6379 -a 123 
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> get name
"jiajia"
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> 

redis主从复制默认是读写分离的,即:
主节点上可以读写操作;从节点上只能进行读操作,不能写数据
image.png

主从切换

  • 停止主节点master的redis
[服务未授权][root@redis1 6379]# redis-cli -p 6379 -a 123  shutdown 
[服务未授权][root@redis1 6379]# netstat  -lntup | grep 6379

  • 将从节点slave32实例的redis设成主redis

这条命了只是临时将该节点设置为主节点;当redis重启后,就会失效;可以登录redis,通过info信息查看!

redis-cli -a 123  -h 127.0.0.1 -p 6379 slaveof NO ONE

变为主redis后,slave就可以进行写入操作了

10.0.0.32:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:a5764bd08d52ee8956b96047fa56363765e570c4
master_replid2:66003cae539c0cfa8239c8c4580a7a2561cfa1a9
master_repl_offset:3658
second_repl_offset:3659
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:3658
10.0.0.32:6379> set name xiaomin
OK
10.0.0.32:6379> get name
"xiaomin"
10.0.0.32:6379> 

  • 原来的主redis恢复正常了,要重新切换回去

原来的主节点恢复了,发现只有一个从节点33。另一个从节点32在31节点故障期间临时变为主节点

[服务未授权][root@redis1 6379]# netstat  -lntup | grep 6379
[服务未授权][root@redis1 6379]# systemctl start redis
[服务未授权][root@redis1 6379]# netstat  -lntup | grep 6379
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      14896/redis-server  
tcp        0      0 10.0.0.31:6379          0.0.0.0:*               LISTEN      14896/redis-server  
[服务未授权][root@redis1 6379]# redis-cli -p 6379 -a 123 
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=10.0.0.33,port=6379,state=online,offset=14,lag=1
master_failover_state:no-failover
master_replid:01c66d4f28fe9bfa4b4320d68e412807174f6407
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
127.0.0.1:6379> 

image.png
那么现在要重新将主节点切换回去。步骤如下:
登录临时切换的主节点32

[服务未授权][root@redis2 ~]# redis-cli -a 123  -h 10.0.0.32  -p 6379
10.0.0.32:6379> set num 100
OK
10.0.0.32:6379> save
OK
10.0.0.32:6379> 

将现在的主redis(即32节点,临时设置的主节点)/data/6379/目录下文件和dump.rdb文件拷贝覆盖到原来主redis的根目录(覆盖前将原来主redis下的持久化文件备份下)
31节点备份

[服务未授权][root@redis1 6379]# cd /data/6379/
[服务未授权][root@redis1 6379]# ls
appendonly.aof  dump.rdb  redis.conf  redis.log  redis.pid
[服务未授权][root@redis1 6379]# mkdir  buckup
[服务未授权][root@redis1 6379]# cp appendonly.aof dump.rdb   buckup/

32节点拷贝覆盖到31

rsync -e "ssh -p22" -avpgolr /data/6379/dump.rdb 10.0.0.31:/data/6379
rsync -e "ssh -p22" -avpgolr /data/6379/appendonly.aof 10.0.0.31:/data/6379

重启原来的主redis(即31节点)

[服务未授权][root@redis1 6379]# systemctl restart redis

在现在的主redis(即32节点)中切换(或者直接重启该节点的redis,因为redis.conf文件中已经配置了;如果不想重启redis,就使用下面的命令)

[服务未授权][root@redis2 6379]# redis-cli -a 123 -h 127.0.0.1 -p 6379 slaveof 10.0.0.31 6379

登录到原来的master节点查看(31节点)

10.0.0.31:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=10.0.0.33,port=6379,state=online,offset=182,lag=1
slave1:ip=10.0.0.32,port=6379,state=online,offset=182,lag=0
master_failover_state:no-failover
master_replid:049068be0a73b1d6958c091388eb7a60e7500850
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:182
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:182
10.0.0.31:6379> keys *
1) "num"
2) "age"
3) "name"
10.0.0.31:6379> get num
"100"
10.0.0.31:6379> 

注意事项
如果使用主从复制,那么要确保你的master激活了持久化,或者确保它不会在当掉后自动重启,原因:

  • slave是master的完整备份,因此如果master通过一个空数据集重启,slave也会被清掉。
  • 在配置redis复制功能的时候,如果主数据库设置了密码,需要在从数据的配置文件中通过masterauth参数设置主数据库的密码,这样从数据库在连接
  • 主数据库时就会自动使用auth命令认证了。相当于做了一个免密码登录。(我上面的例子中没有设置密码)

解除主从关系

32 解除主从关系

[服务未授权][root@redis2 ~]# redis-cli -p 6379 -h 10.0.0.32  -a 123 SLAVEOF NO ONE  
OK

33 解除主从关系

[服务未授权][root@redis3 ~]# redis-cli -p 6379 -h 10.0.0.33  -a 123 SLAVEOF NO ONE  
OK

31 master节点查看主从关系,可以看到connected_slaves数量为0

[服务未授权][root@redis1 6379]# redis-cli -p 6379 -a 123  -h 10.0.0.31 info replication
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:049068be0a73b1d6958c091388eb7a60e7500850
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:756
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:756
posted @ 2024-08-09 15:29  &UnstopPable  阅读(7)  评论(0编辑  收藏  举报