Redis 二进制主从搭建及原理

释放双眼,带上耳机,听听看~!
🤖 由 ChatGPT 生成的文章摘要

主从架构原理

  • 首先是主从库建立连接、协商同步的过程,具体的从库向主库发送 psync 命令,代表要进行数据同步;psync 中包含了主库的 runID(Redis 启动时生成的随机 ID,初始值为:?)和复制进度 offset(设为-1,代表第一次复制)两个参数,主库接收到 psync 命令会,会用 FULLRESYNC 命令返回给从库,包含两个参数:主库 runID 和复制进度 offset;其中 FULLRESYNC 代表的全量复制,会将主库所有的数据都复制给从库;

  • 待从库接收到数据后,在本地完成数据加载,具体的主库执行 bgsave 命令,生成 RDB 文件,然后将文件发给从库,从库接收到 RDB 文件后,首先清空当前数据,然后再加载 RDB 文件;这个过程主库不会被阻塞,仍然可以接受请求,如果存在写操作,刚刚生成的 RDB 文件中是不包含这些新数据的,此时主库会在内存中用专门的 replication buffer 记录 RDB 文件生成后所有的写操作;

  • 最后,主库会把 replication buffer 中的修改操作发给从库,从库重新执行这些操作,就可以实现主从库同步了。

Redis 单节点安装

本次测试版本为redis-7.0.8

所有的搭建都需要提前安装redis,此处可以使用Yum或者Docker 镜像的方式安装

#如果有依赖问题可以提前安装下面的依赖包库
[root@web01 redis]# yum -y install gcc gcc-c++ make autoconf libtool-ltdl-devel gd-devel freetype-devel libxml2-devel libjpeg-devel libpng-devel openssh-clients openssl-devel curl-devel bison patch libmcrypt-devel libmhash-devel ncurses-devel binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel glibc glibc-common glibc-devel libgcj libtiff pam-devel libicu libicu-devel gettext-devel libaio-devel libaio libgcc libstdc++ libstdc++-devel unixODBC unixODBC-devel numactl-devel glibc-headers sudo bzip2 mlocate flex lrzsz sysstat lsof setuptool system-config-network-tui system-config-firewall-tui ntsysv ntp pv lz4 dos2unix unix2dos rsync dstat iotop innotop mytop telnet iftop expect cmake nc gnuplot screen xorg-x11-utils xorg-x11-xinit rdate bc expat-devel compat-expat1 tcpdump sysstat man nmap curl lrzsz elinks finger bind-utils traceroute mtr ntpdate zip unzip vim wget net-tools

[root@web01 redis]# wget http://download.redis.io/releases/redis-7.0.8.tar.gz
[root@web01 redis]# tar xf redis-7.0.8.tar.gz 
[root@web01 redis]# make && make install 

#建议使用PREFIX指定安装目录,后续多台集群方便统一维护以及后续脚本编写
#PREFIX=/opt/redis

前台启动测试

先启动测试,检查是否有版本依赖或其它端口冲突等问题,后续统一调整配置文件

[root@web01 redis-7.0.8]# redis-server  redis.conf  --port 6379
20186:C 15 Mar 2023 01:32:13.854 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
20186:C 15 Mar 2023 01:32:13.854 # Redis version=7.0.8, bits=64, commit=00000000, modified=0, pid=20186, just started
20186:C 15 Mar 2023 01:32:13.854 # Configuration loaded
20186:M 15 Mar 2023 01:32:13.854 * Increased maximum number of open files to 10032 (it was originally set to 1024).
20186:M 15 Mar 2023 01:32:13.854 * monotonic clock: POSIX clock_gettime
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 7.0.8 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                  
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 20186
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           https://redis.io       
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

20186:M 15 Mar 2023 01:32:13.855 # Server initialized
20186:M 15 Mar 2023 01:32:13.855 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
20186:M 15 Mar 2023 01:32:13.856 * Ready to accept connections

不修改配置文件的方式,后台直接启动

[root@web01 redis-7.0.8]# nohup redis-server  redis.conf  --port 6379 &

#redis.conf可以单独指定其它文件

检查启动进程是否正常,可以连接

[root@web01 redis-7.0.8]# netstat -lntup|grep 6379
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      20201/redis-server  
tcp6       0      0 ::1:6379                :::*                    LISTEN      20201/redis-server  

[root@web01 redis-7.0.8]# ps -ef|grep redis
root     20201 15634  0 01:49 pts/0    00:00:00 redis-server 127.0.0.1:6379

检查是否可以正常写入

[root@web01 redis-7.0.8]# redis-cli -p 6379
127.0.0.1:6379> KEYS *
(empty array)
127.0.0.1:6379> 

主从复制配置文件对应参数解释如下

- slaveof <masterip> <masterport>   # 复制选项,slave复制对应的master;
- masterauth <master-password>   # 如果master设置了requirepass,那么slave要连上master,需要有master的密码才行。masterauth就是用来配置master的密码,这样可以在连上master后进行认证;
- slave-serve-stale-data yes   # 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。2) 如果slave-serve-stale-data设置为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误”SYNC with master in progress”;
- slave-read-only yes   # 作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(强烈不建议);
- repl-diskless-sync no   # 是否使用socket方式复制数据。目前redis复制提供两种方式,disk和socket。如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。有2种方式:disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave。disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式;
- repl-diskless-sync-delay 5   # diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间,等更多的slave连上来;
- repl-ping-slave-period 10   #  slave根据指定的时间间隔向服务器发送ping请求。时间间隔可以通过 repl_ping_slave_period 来设置,默认10秒;
- repl-timeout 60   # 复制连接超时时间。master和slave都有超时时间的设置。master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。需要注意的是repl-timeout需要设置一个比repl-ping-slave-period更大的值,不然会经常检测到超时;
- repl-disable-tcp-nodelay no   # 是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。默认是no,即使用tcp nodelay。如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes;
- repl-backlog-size 5mb   # 复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。这样在slave离线的时候,不需要完全复制master的数据,如果可以执行部分同步,只需要把缓冲区的部分数据复制给slave,就能恢复正常复制状态。缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有slave连接的时候才分配内存。没有slave的一段时间,内存会被释放出来,默认1m;
- repl-backlog-ttl 3600   # master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。单位为秒;
- slave-priority 100   # 当master不可用,哨兵会根据slave的优先级选举一个master。值越小优先级越高。但0,永远不会被选举;
- min-slaves-to-write 3   # redis提供了可以让master停止写入的方式,如果配置了min-slaves-to-write,健康的slave的个数小于N,mater就禁止写入。master最少得有多少个健康的slave存活才能执行写命令。这个配置虽然不能保证N个slave都一定能接收到master的写操作,但是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。设置为0是关闭该功能;
- min-slaves-max-lag 10.  # 延迟小于min-slaves-max-lag秒的slave才认为是健康的slave;
- - 设置1或者min-slaves-to-write设置为0,表示禁用这个特性;

主从架构

Redis 二进制主从搭建及原理

如果从库的实例过多,对于主库来说有一定的压力,主库会频繁 fork 子进程以生成 RDB 文件,fork 这个操作会阻塞主线程处理正常请求,导致响应变慢,Redis 采用了主-从-从的模式,可以手动选择一个从库,用来同步其他从库的数据,以减少主库生成 RDB 文件和传输 RDB 文件的压力;

Redis 二进制主从搭建及原理

主从搭建

主机名 节点 IP
web-01 master 192.168.31.70
web-02 slave 192.168.31.71
web-03 slave 192.168.31.72

接下来先配置Master节点配置

这里是redis.conf配置文件,主从部分只介绍主从的相关配置,后续会添加哨兵和集群模式的搭建及相对应的配置

  • 本次的配置文件将slave节点设为只读,禁止写入数据
  • 设置redis密码为123123
  • 采用aof持久化存储
  • 日志存储/opt/redis.log
  • 配置文件后台启动
bind 0.0.0.0
protected-mode yes
requirepass 123123  #密码
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
pidfile /var/run/redis_6379.pid
loglevel notice
logfile "/opt/redis.log"
databases 16
always-show-logo no
set-proc-title yes
proc-title-template "{title} {listen-addr} {server-mode}"
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-sync-max-replicas 0
repl-diskless-load disabled
repl-disable-tcp-nodelay yes
replica-priority 100
acllog-max-len 128
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
lazyfree-lazy-user-flush no
oom-score-adj no
oom-score-adj-values 0 200 800
disable-thp yes

#aof持久化相关配置
appendonly yes
appendfilename "appendonly.aof"
appenddirname "appendonlydir"

#存储目录
dir /opt/

#同步策略
appendfsync always

no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
aof-timestamp-enabled no

slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-listpack-entries 512
hash-max-listpack-value 64
list-max-listpack-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-listpack-entries 128
zset-max-listpack-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes

min-slaves-to-write 0
min-slaves-max-lag 10

启动redis master,写入数据

#因为直接设置了后台进程,所以不需要手动让进程后台运行
[root@web-01 redis-7.0.8]# redis-server redis.conf 

#连接redis
[root@web01 redis-7.0.8]# redis-cli -p 6379

#redis已经设置密码了,所以需要登陆密码
127.0.0.1:6379> auth 123123  #输入密码
127.0.0.1:6379> KEYS *
1) "abc"
2) "age"
3) "stu"
127.0.0.1:6379> get abc
"name"
127.0.0.1:6379> 

目前我们执行info replication只能看到master自己

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:135b31657c35b82c753e69b638cc0c49956aa56a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

Redis从库搭建

从slave配置

#所有从节点,只需要添加一行下面的配置就可以
replicaof 192.168.31.70 6379
masterauth 123123
slave-read-only yes
#Redis masterIP  masterPort
#Redis password
#slave-read-only 从库开启只读

步骤如下

[root@web02 redis-7.0.8]# cp redis.conf{,.bak_2023-03-15}
[root@web02 redis-7.0.8]# >redis.conf
[root@web02 redis-7.0.8]# vim redis.conf
#配置复制master,另外添加下面一行
replicaof 192.168.31.70 6379
masterauth 123123
slave-read-only yes

slave节点启动测试

[root@web-03 redis-7.0.8]# redis-server redis.conf 
[root@web-03 redis-7.0.8]# tail -f /opt/redis.log 
11331:S 15 Mar 2023 04:07:21.171 * Creating AOF incr file temp-appendonly.aof.incr on background rewrite
11331:S 15 Mar 2023 04:07:21.171 * Background append only file rewriting started by pid 11337
11337:C 15 Mar 2023 04:07:21.174 * Successfully created the temporary AOF base file temp-rewriteaof-bg-11337.aof
11337:C 15 Mar 2023 04:07:21.175 * Fork CoW for AOF rewrite: current 4 MB, peak 4 MB, average 4 MB
11331:S 15 Mar 2023 04:07:21.272 * Background AOF rewrite terminated with success
11331:S 15 Mar 2023 04:07:21.272 * Successfully renamed the temporary AOF base file temp-rewriteaof-bg-11337.aof into appendonly.aof.3.base.rdb
11331:S 15 Mar 2023 04:07:21.272 * Successfully renamed the temporary AOF incr file temp-appendonly.aof.incr into appendonly.aof.3.incr.aof
11331:S 15 Mar 2023 04:07:21.288 * Removing the history file appendonly.aof.2.incr.aof in the background
11331:S 15 Mar 2023 04:07:21.288 * Removing the history file appendonly.aof.2.base.rdb in the background
11331:S 15 Mar 2023 04:07:21.290 * Background AOF rewrite finished successfully

##########################################

[root@web-03 redis-7.0.8]# redis-cli 
127.0.0.1:6379> KEYS *
1) "abc"
2) "stu"
3) "age"
127.0.0.1:6379> set nnn abc   #开启slave节点只读
(error) READONLY You can't write against a read only replica.
127.0.0.1:6379> 

当我们2台slave节点都启动完毕后,我们这master节点执行info replication就可以看到slave节点信息

127.0.0.1:6379> info replication
# Replication
role:master

connected_slaves:2

slave0:ip=192.168.31.71,port=6379,state=online,offset=308,lag=0
slave1:ip=192.168.31.72,port=6379,state=online,offset=308,lag=0

master_failover_state:no-failover
master_replid:eba1048b441dc364697f924d8725d729f0ffe36d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:308
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:308

主从架构缺点

主从模式缺点: 当master节点down掉,slave节点无法进行写入,只可以进行只读。主节点由于故障下线了,从节点因为没有主节点而同步中断,因而需要人工进行故障转移工作。并且还有一个问题就是当master节点down后,从节点没有数据同步,当master节点持久化丢失后,redis slave节点也将会删除持久化数据重新进行同步

给TA打赏
共{{data.count}}人
人已打赏
Redis

Redis 开启持久化缓存

2017-10-20 16:59:47

Redis报错锦集

Redis Sentinel哨兵模式停止Master节点后无法调度Slave

2023-3-16 18:39:47

2 条回复 A文章作者 M管理员
  1. […] Redis 二进制主从搭建及原理 […]

  2. […] […]

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索