Bootstrap

Redis详解(十)进阶:如何配置主从复制

Redis主从复制

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。

默认情况下,每台Redis服务器都是主节点,一个主节点可以有0个或者多个从节点,但每个从节点只能由一个主节点。

作用

  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
  • 故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
  • 负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
  • 高可用基石:主从复制还是哨兵和集群能够实施的基础。

环境配置

  • 查看当前库的信息 info repliacation

    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:7d80795751effcf72641bf424258d5dc5429b59d
    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.conf配置文件,修改对应的信息

    [root@hecs-66166 mconfig]# ls
    redis.conf
    [root@hecs-66166 mconfig]# cp redis.conf redis6379.conf 
    [root@hecs-66166 mconfig]# cp redis.conf redis6380.conf 
    [root@hecs-66166 mconfig]# cp redis.conf redis6381.conf 
    [root@hecs-66166 mconfig]# ls
    redis6379.conf  redis6380.conf  redis6381.conf  redis.confxxxxxxxxxx # cp redis.conf redis6379.conf# cp redis.conf 
    
  • 依次修改对应的三个配置信息, **:wq!**保存退出

    • 端口号

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLkwkY0e-1667247809150)(Redis.assets/image-20221031174127526.png)]

    • pid名字

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qkr2w4Tk-1667247809152)(Redis.assets/image-20221031174211171.png)]

    • log文件名称

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dM4mRsEA-1667247809152)(Redis.assets/image-20221031174510274.png)]

    • rdb文件名称

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-28cMnat8-1667247809153)(Redis.assets/image-20221031174604381.png)]

  • 分别启动三个redis

    • 注意,如果遇到-bash: redis-server: command not found这种错误,只需要将/redis/src/下的redis-server复制移动到/usr/bin/下即可((相当于创建一个全局快捷方式)
    [root@hecs-66166 mconfig]# redis-server redis6379.conf
    [root@hecs-66166 mconfig]# redis-server redis6380.conf
    [root@hecs-66166 mconfig]# redis-server redis6381.conf
    [root@hecs-66166 mconfig]# ps -ef |grep redis
    root      240286       1  0 17:50 ?        00:00:00 redis-server 127.0.0.1:6379
    root      240292       1  0 17:50 ?        00:00:00 redis-server 127.0.0.1:6380
    root      240298       1  0 17:50 ?        00:00:00 redis-server 127.0.0.1:6381
    root      240306  233038  0 17:50 pts/1    00:00:00 grep --color=auto redis
    
  • 分别查看每台redis的信息(默认情况下每一台redis都是主机)

    ############################6379#########################
    [root@hecs-66166 bin]# redis-cli -p 6379
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:bb5fcefe6abb7444d7b032596398279686e12c0d
    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
    ############################6380#########################
    [root@hecs-66166 ~]# redis-cli -p 6380
    127.0.0.1:6380> ping
    PONG
    127.0.0.1:6380> info replication
    # Replication
    role:master
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:5d418ab0fec977b80fd9c53a281264a1c0d94530
    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
    ############################6381#########################
    [root@hecs-66166 ~]# redis-cli -p 6381
    127.0.0.1:6381> ping
    PONG
    127.0.0.1:6381> info replication
    # Replication
    role:master
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:3a4e7a6e162b9c6f2fe4831ef4f060561d899ad6
    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
    
  • 配置从机(1主(6379)2从 (6380、6381))

    • 配置从机
    127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
    OK
    127.0.0.1:6380> info replication
    # Replication
    role:slave
    master_host:127.0.0.1
    master_port:6379
    master_link_status:down
    master_last_io_seconds_ago:-1
    master_sync_in_progress:0
    slave_read_repl_offset:0
    slave_repl_offset:0
    master_link_down_since_seconds:-1
    slave_priority:100
    slave_read_only:1
    replica_announced:1
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:5d418ab0fec977b80fd9c53a281264a1c0d94530
    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
    
    ###另一台同理,端口修改即可####
    
    • 查看主机
    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=127.0.0.1,port=6380,state=online,offset=112,lag=1
    slave1:ip=127.0.0.1,port=6381,state=online,offset=126,lag=1
    master_failover_state:no-failover
    master_replid:41bd19475f7bb08d322fd8ff78c6f593c74bc127
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:126
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:126
    

    我们这里是使用命令搭建,是暂时的,==真实开发中应该在从机的配置文件中进行配置,==这样的话是永久的。

    ################################# REPLICATION #################################
    
    # Master-Replica replication. Use replicaof to make a Redis instance a copy of
    # another Redis server. A few things to understand ASAP about Redis replication.
    #
    #   +------------------+      +---------------+
    #   |      Master      | ---> |    Replica    |
    #   | (receive writes) |      |  (exact copy) |
    #   +------------------+      +---------------+
    #
    # 1) Redis replication is asynchronous, but you can configure a master to
    #    stop accepting writes if it appears to be not connected with at least
    #    a given number of replicas.
    # 2) Redis replicas are able to perform a partial resynchronization with the
    #    master if the replication link is lost for a relatively small amount of
    #    time. You may want to configure the replication backlog size (see the next
    #    sections of this file) with a sensible value depending on your needs.
    # 3) Replication is automatic and does not need user intervention. After a
    #    network partition replicas automatically try to reconnect to masters
    #    and resynchronize with them.
    #
    # replicaof <masterip> <masterport>   #配置主机的信息
    
    # If the master is password protected (using the "requirepass" configuration
    # directive below) it is possible to tell the replica to authenticate before
    # starting the replication synchronization process, otherwise the master will
    # refuse the replica request.
    #
    # masterauth <master-password>  #若有密码验证,配置密码即可
    

使用规则

  • 主机可读可写但是多用于写, 从机只能读,不能写。

    #######################测试从机写数据################
    127.0.0.1:6380> keys *
    (empty array)
    127.0.0.1:6380> set k1 v1
    (error) READONLY You can't write against a read only replica.
    
    #####################测试主机写数据##################
    127.0.0.1:6379> keys *
    (empty array)
    127.0.0.1:6379> set k1 v1
    OK
    
    #####################测试从机读数据##################
    127.0.0.1:6380> get k1
    "v1"
    
  • 当主机断电宕机后,默认情况下从机的角色不会发生变化 ,集群中只是失去了写操作,当主机恢复以后,又会连接上从机恢复原状。

    #####################测试主机宕机##################
    127.0.0.1:6379> SHUTDOWN
    not connected> exit
    [root@iZ2zedw5vursd09dhzivjnZ bin]# 
        
    #####################查看从机信息##################
    127.0.0.1:6380> info replication
    # Replication
    role:slave
    master_host:127.0.0.1
    master_port:6379
    master_link_status:down
    master_last_io_seconds_ago:-1
    master_sync_in_progress:0
    slave_read_repl_offset:290
    slave_repl_offset:290
    master_link_down_since_seconds:21
    slave_priority:100
    slave_read_only:1
    replica_announced:1
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:41bd19475f7bb08d322fd8ff78c6f593c74bc127
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:290
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:290
    
        
    ###################重启主机信息####################
    [root@hecs-66166 bin]# redis-cli -p 6379
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=127.0.0.1,port=6380,state=online,offset=360,lag=1
    slave1:ip=127.0.0.1,port=6381,state=online,offset=360,lag=0
    master_failover_state:no-failover
    master_replid:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff
    master_replid2:41bd19475f7bb08d322fd8ff78c6f593c74bc127
    master_repl_offset:360
    second_repl_offset:291
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:291
    repl_backlog_histlen:70
    
    
  • 当从机断电宕机后,若不是使用配置文件配置的从机,再次启动后默认作为主机是无法获取之前原主机的数据的,若此时重新配置称为从机,又可以获取到主机的所有数据。这里就要提到一个同步原理。

    #################测试从机宕机########################
    127.0.0.1:6381> SHUTDOWN
    not connected> exit
    #################查看进程###########################
    [root@hecs-66166 mconfig]# ps -ef |grep redis
    root      240292       1  0 17:50 ?        00:00:00 redis-server 127.0.0.1:6380
    root      240340  240315  0 17:52 pts/2    00:00:00 redis-cli -p 6380
    root      240473       1  0 17:59 ?        00:00:00 redis-server 127.0.0.1:6379
    root      240518  232062  0 18:00 pts/0    00:00:00 redis-cli -p 6379
    root      240535  233038  0 18:01 pts/1    00:00:00 grep --color=auto redis
    
    #################查看主机信息###########################
    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=127.0.0.1,port=6380,state=online,offset=500,lag=1
    master_failover_state:no-failover
    master_replid:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff
    master_replid2:41bd19475f7bb08d322fd8ff78c6f593c74bc127
    master_repl_offset:500
    second_repl_offset:291
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:291
    repl_backlog_histlen:210
        
    ####################重启从机########################
    [root@hecs-66166 bin]# redis-server ./mconfig/redis6381.conf 
    [root@hecs-66166 bin]# redis-cli -p 6381
    127.0.0.1:6381> ping
    PONG
    127.0.0.1:6381> info replication
    # Replication
    role:master
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:0c54e4dd76325946d42fb3b5d1df9ba672008566
    master_replid2:410d8f04b43af61d9517da4e4d25c217b670e296
    master_repl_offset:1690
    second_repl_offset:1691
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1691
    repl_backlog_histlen:0
        
    ###################测试获取原来主机的数据################
    127.0.0.1:6381> get k1
    (nil)
    
    ######################################################
    我们会发现这一台已经成为了主机,但获取不了原主机的数据,我们需要再次配置从机信息后才能获取到主机写入的数据    
    ######################################################
    
    ###################配置从机信息########################
    127.0.0.1:6381> SLAVEOF 127.0.0.1 6379
    OK
    127.0.0.1:6381> info replication
    # Replication
    role:slave
    master_host:127.0.0.1
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:2
    master_sync_in_progress:0
    slave_read_repl_offset:49626
    slave_repl_offset:49626
    slave_priority:100
    slave_read_only:1
    replica_announced:1
    connected_slaves:0
    master_failover_state:no-failover
    master_replid:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:49626
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:49627
    repl_backlog_histlen:0
    127.0.0.1:6381> get k1
    "v1"
    
    
  • 第二条中提到,默认情况下,主机故障后,不会出现新的主机,有两种方式可以产生新的主机:

    • 从机手动执行命令slaveof no one,这样执行以后从机会独立出来成为一个主机,其他的节点就可以手动连接到最新的主节点(手动)

      127.0.0.1:6381> SLAVEOF no one
      OK
      127.0.0.1:6381> INFO REPLICATION
      # Replication
      role:master
      connected_slaves:0
      master_failover_state:no-failover
      master_replid:fcc781049a15be144093e78741548b99da093a69
      master_replid2:b5a15a566fa2df80ef2f9d49b4e2b99e4d45c2ff
      master_repl_offset:50592
      second_repl_offset:50593
      repl_backlog_active:1
      repl_backlog_size:1048576
      repl_backlog_first_byte_offset:49627
      repl_backlog_histlen:966
      #####如果后续主机恢复了,那么就相当于光杆司令了,只能再重新配置主从复制######
      
    • 使用哨兵模式(自动选举),下一篇文章会介绍到

复制原理

  • Slave命令启动成功连接到Master主机后会发送psync命令(Redis2.8之前版本是sync命令),开始进行数据同步
  • Master主机接收到psync命令,启动后台的存盘进程,同时收集所有接收到的写的命令,在后台进程执行完毕之后,Mater会将整个数据文件传送到Slave,并完成一次完全同步
  • 全量复制:Slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
  • 增量复制:Master服务继续将修改的命令一次传送到Slave服务,完成同步
  • 但是只要重新连接Master,一次完全同步(全量复制)将自动执行!我们的数据一定可以在从机中看到

层层链路

上一个Master主机链接下一个Slave从机

也就是6379是主机,6380既是主机也是从机 ,6381是6380的从机

我们在获取数据的时候,6380显示的信息依旧是6379的从机,它能读6379的数据,6381也能读6379的数据

#################################测试6379主机##################################
[root@hecs-66166 ~]# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=28,lag=0
master_failover_state:no-failover
master_replid:1893a9622491d130a17c0afb55e26829d2b89137
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 v1
OK



#################################测试6380主机从机##################################
[root@hecs-66166 ~]# redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_read_repl_offset:280
slave_repl_offset:280
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=280,lag=0
master_failover_state:no-failover
master_replid:1893a9622491d130a17c0afb55e26829d2b89137
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:280
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:280
127.0.0.1:6380> get k1
"v1"

#################################测试6381从机##################################
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_read_repl_offset:50592
slave_repl_offset:50592
master_link_down_since_seconds:-1
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:fea79ddb9f0b1da3c2b64e96b224fbec8689e28f
master_replid2:fcc781049a15be144093e78741548b99da093a69
master_repl_offset:50592
second_repl_offset:50593
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:50593
repl_backlog_histlen:0
127.0.0.1:6381> get k1
"v1"

;