精华内容
下载资源
问答
  • redis 主从原理

    2020-08-11 14:02:44
    1.Redis主从搭建 主从的搭建很简单,主节点设置连接密码,从节点的配置上主节点的ip和端口,以及密码,一般从节点我们都设置只读模式。 主节点配置:  主节点密码:  requirepass xxx 从节点中配置:  #主...

    https://www.cnblogs.com/nijunyang/p/12494774.html

    1.Redis主从搭建

    主从的搭建很简单,主节点设置连接密码,从节点的配置上主节点的ip和端口,以及密码,一般从节点我们都设置只读模式。

    主节点配置:

      主节点密码:

      requirepass xxx

    从节点中配置:

      #主节点

      replicaof 192.168.0.67 6379

      #从节点只读

      replica-read-only yes

      #主节点连接密码

      masterauth root

    使用对应的配置文件启动master和slave服务即可。

    如果不使用密码来连接可能出现,从节点能识别主节点,但是却无法连接到主上面去,如下主从信息如下情况:

     

     

    这样的Redis主从只是一个数据的备份关系,如果master挂了,需要手动去讲salve切换成master并且将客户端连接切换到新的master上面去。

    同时还可以搭建多级结构,也就是说slave-A也可以成为别的slave-B的master。

    使用主从结构一来是备份数据,二来也可以实现读写分离作用,master写数据,salve读数据

    2.主从复制原理

    全量复制:

    如果为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个SYNC命 令给master请求复制数据。 master收到SYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间, master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以 后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。 当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多 个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。 当master和slave断开重连后,一般都会对整份数据进行复制。

     

     

    增量复制:

    从2.8版本开始,slave与master能够在网络连接断开重连后只进行部分数据复制。 master会在其内存中创建一个复制数据用的缓存队列buffer,缓存最近一段时间的数据,默认大小1m,如果超过这个大小就会清理掉,但是这些数据是在AOF或者RDB快照中的,master和它所有的 slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master 继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标 offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。从2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据。

    展开全文
  • Redis主从原理

    千次阅读 2017-04-07 21:34:59
    1. 概述 ...如果是重新连接,且满足增量同步的条件(3.1中详述),那么redis会将内存缓存队列中的命令发给slave, 完成增量同步(Partial resynchronization)。否则进行全量同步。  2. 正常同步开始 

    1. 概述

    整体过程概述如下: 
    1. 初始化 
    配置好主从后,无论slave是初次还是重新连接到master, slave都会发送PSYNC命令到master。 
    如果是重新连接,且满足增量同步的条件(3.1中详述),那么redis会将内存缓存队列中的命令发给slave, 完成增量同步(Partial resynchronization)。否则进行全量同步。 
    2. 正常同步开始 
    任何对master的写操作都会以redis命令的方式,通过网络发送给slave。

    2. 全量同步(full resynchronization)

    2.1 过程

    1. slave发送PSYNC
    2. master执行bgsave生成RDB快照文件,同时将这之后新的写命令记入缓冲区
    3. master向slave发送快照文件,并继续记录写命令
    4. slave接收并保存快照
    5. slave将快照文件载入内存
    6. slave开始接收master中缓冲区的命令完成同步

    2.2 实例

    环境: 
    - master 127.0.0.1:7779 
    - slave 127.0.0.1:9303 进程号10967 只有一个key

    strace -p 10967 -s 1024 -o redis.strace.full
    • 1

    然后连接到slave, 执行slaveof 127.0.0.1 7779,从strace文件看到的同步过程中,slave侧的动作如下(只摘重要部分)

    /*从client执行slaveof命令*/
    read(6, "*3\r\n$7\r\nslaveof\r\n$9\r\n127.0.0.1\r\n$4\r\n7779\r\n", 16384) = 42
    /*返回给client OK*/
    write(6, "+OK\r\n", 5)
    /*连接到master*/
    connect(7, {sa_family=AF_INET, sin_port=htons(7779), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
    /*以下判断master是活着的*/
    write(7, "PING\r\n", 6) 
    read(7, "+", 1)                         = 1
    read(7, "P", 1)                         = 1
    read(7, "O", 1)                         = 1
    read(7, "N", 1)                         = 1
    read(7, "G", 1)                         = 1
    read(7, "\r", 1)                        = 1
    read(7, "\n", 1)                        = 1
    /*同步开始,向master发PSYNC*/
    write(7, "PSYNC ? -1\r\n", 12)          = 12
    /*master告诉salve要执行全量同步*/
    read(7, "+", 1)                         = 1
    read(7, "F", 1)                         = 1
    read(7, "U", 1)                         = 1
    read(7, "L", 1)                         = 1
    read(7, "L", 1)                         = 1
    read(7, "R", 1)                         = 1
    read(7, "E", 1)                         = 1
    read(7, "S", 1)                         = 1
    read(7, "Y", 1)                         = 1
    read(7, "N", 1)                         = 1
    read(7, "C", 1)                         = 1
    /*打开本地临时rdb文件*/
    open("temp-1472206877.10967.rdb", O_WRONLY|O_CREAT|O_EXCL, 0644) = 8
    /*接收master发来的rdb文件*/
    read(7, "REDIS0006\376\0\0\4name\4xuan\376\1\r\16HOTEL_JUMP_NUM\33\33\0\0\0\30\0\0\0\4\0\0\320\325\2\220\6\6\365\2\320\334\230(\7\6\370\377\377\336\260\222\330\261\317\371\345", 77) = 77
    /*将接收的rdb写入临时rdb*/
    write(8, "REDIS0006\376\0\0\4name\4xuan\376\1\r\16HOTEL_JUMP_NUM\33\33\0\0\0\30\0\0\0\4\0\0\320\325\2\220\6\6\365\2\320\334\230(\7\6\370\377\377\336\260\222\330\261\317\371\345", 77) = 77
    /*临时rdb文件重命名*/
    rename("temp-1472206877.10967.rdb", "dump.rdb") = 0
    /*打开本地rdb文件*/
    open("dump.rdb", O_RDONLY) = 9
    /* 从rdb文件加载数据到slave*/
    read(9, "REDIS0006\376\0\0\4name\4xuan\376\1\r\16HOTEL_JUMP_NUM\33\33\0\0\0\30\0\0\0\4\0\0\320\325\2\220\6\6\365\2\320\334\230(\7\6\370\377\377\336\260\222\330\261\317\371\345", 4096) = 77
    /*sync成功完成,记录日志*/
    open("/tmp/redis.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8
    fstat(8, {st_mode=S_IFREG|0644, st_size=7627, ...}) = 0
    write(8, "[10967] 26 Aug 18:21:17.450 * MASTER <-> SLAVE sync: Finished with success\n", 75) = 75
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    整个过程,与2.1所述一样,只是因为我们在同步过程中没对master做操作,所以strace没有体现出2.1中的第6步。

    slave的redis.log也反应了上面的过程。

    [10967] 26 Aug 18:21:17.250 * SLAVE OF 127.0.0.1:7779 enabled (user request)
    [10967] 26 Aug 18:21:17.410 * Connecting to MASTER 127.0.0.1:7779
    [10967] 26 Aug 18:21:17.413 * MASTER <-> SLAVE sync started
    [10967] 26 Aug 18:21:17.415 * Non blocking connect for SYNC fired the event.
    [10967] 26 Aug 18:21:17.418 * Master replied to PING, replication can continue...
    [10967] 26 Aug 18:21:17.421 * Partial resynchronization not possible (no cached master)
    [10967] 26 Aug 18:21:17.432 * Full resync from master: 1d13fbd06f644eeb4b50d65f11e65bffd9e596f6:43774
    [10967] 26 Aug 18:21:17.444 * MASTER <-> SLAVE sync: receiving 77 bytes from master
    [10967] 26 Aug 18:21:17.446 * MASTER <-> SLAVE sync: Flushing old data
    [10967] 26 Aug 18:21:17.447 * MASTER <-> SLAVE sync: Loading DB in memory
    [10967] 26 Aug 18:21:17.450 * MASTER <-> SLAVE sync: Finished with success
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3. 增量同步(partial resynchronization)

    3.1 增量同步的条件

    几个重要概念: 
    - 内存缓存队列(in-memory backlog):用于记录连接断开时master收到的写操作 
    - 复制偏移量(replication offset):master, slave都有一个偏移,记录当前同步记录的位置 
    - master服务器id(master run ID):master唯一标识,2.2的redis.log中的1d13fbd06f644eeb4b50d65f11e65bffd9e596f6,就是一个master服务器id。

    现网络连接断开后,slave将尝试重连master。当满足下列条件时,重连后会进行增量同步: 
    1. slave记录的master服务器id和当前要连接的master服务器id相同 
    2. slave的复制偏移量比master的偏移量靠前。比如slave是1000, master是1100 
    3. slave的复制偏移量所指定的数据仍然保存在主服务器的内存缓存队列中

    3.2 同步过程

    确认执行增量同步后,redis会将内存缓存队列中的命令通过网络发给slave, 完成增量同步

    3.3 实例

    环境: 
    - master 10.136.30.144:7779 
    - slave 10.136.31.213 9303 有一个key “h”

    首先我们strace slave的进程,然后,为了模拟网络断线,我们在master机器上增加iptables规则,扔掉了所有发往slave的包。

    /sbin/iptables -A OUTPUT -d 10.136.31.213 -j DROP
    • 1

    然后,在master上删除key h

    del h
    • 1

    最后,我们删除iptables规则,模拟出网络恢复的状况。

    /sbin/iptables -F
    • 1

    我们先来看slave的日志

    [25667] 26 Aug 15:29:33.241 # Connection with master lost.
    [25667] 26 Aug 15:29:33.241 * Caching the disconnected master state.
    [25667] 26 Aug 15:29:33.241 * Connecting to MASTER 10.136.30.144:7779
    [25667] 26 Aug 15:29:33.241 * MASTER <-> SLAVE sync started
    [25667] 26 Aug 15:29:54.240 # Error condition on socket for SYNC: Connection timed out
    [25667] 26 Aug 15:29:54.262 * Connecting to MASTER 10.136.30.144:7779
    [25667] 26 Aug 15:29:54.263 * MASTER <-> SLAVE sync started
    [25667] 26 Aug 15:30:15.270 # Error condition on socket for SYNC: Connection timed out
    [25667] 26 Aug 15:30:15.726 * Connecting to MASTER 10.136.30.144:7779
    [25667] 26 Aug 15:30:15.726 * MASTER <-> SLAVE sync started
    [25667] 26 Aug 15:30:36.728 # Error condition on socket for SYNC: Connection timed out
    [25667] 26 Aug 15:30:37.272 * Connecting to MASTER 10.136.30.144:7779
    [25667] 26 Aug 15:30:37.279 * MASTER <-> SLAVE sync started
    [25667] 26 Aug 15:30:37.282 * Non blocking connect for SYNC fired the event.
    [25667] 26 Aug 15:30:37.289 * Master replied to PING, replication can continue...
    [25667] 26 Aug 15:30:37.293 * Trying a partial resynchronization (request 1d13fbd06f644eeb4b50d65f11e65bffd9e596f6:29265).
    [25667] 26 Aug 15:30:37.300 * Successful partial resynchronization with master.
    [25667] 26 Aug 15:30:37.302 * MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    slave发现与master断开后,一直尝试重新连接master,直到连接成功后尝试增量同步(partial resynchronization)并最终完成了增量同步。

    starce的结果同样反应了上面的过程,摘要如下:

    /*重新连接master*/
    connect(6, {sa_family=AF_INET, sin_port=htons(7779), sin_addr=inet_addr("10.136.30.144")}, 16) = -1 EINPROGRESS (Operation now in progress)
    /*以下判断master是活着的*/
    write(6, "PING\r\n", 6) 
    read(6, "+", 1)                         = 1
    read(6, "P", 1)                         = 1
    read(6, "O", 1)                         = 1
    read(6, "N", 1)                         = 1
    read(6, "G", 1)                         = 1
    read(6, "\r", 1)                        = 1
    read(6, "\n", 1)                        = 1
    /*slave尝试增量同步,master表示同意*/
    write(6, "PSYNC 1d13fbd06f644eeb4b50d65f11"..., 54) = 54
    read(6, "+", 1)                         = 1
    read(6, "C", 1)                         = 1
    read(6, "O", 1)                         = 1
    read(6, "N", 1)                         = 1
    read(6, "T", 1)                         = 1
    read(6, "I", 1)                         = 1
    read(6, "N", 1)                         = 1
    read(6, "U", 1)                         = 1
    read(6, "E", 1)                         = 1
    read(6, "\r", 1)                        = 1
    read(6, "\n", 1)                        = 1
    /*读取断线期间的增量命令: del h*/
    read(6, "*1\r\n$4\r\nPING\r\n*2\r\n$3\r\ndel\r\n$1\r\nh"..., 16384) = 188
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4. 备注

    1. 本文主要描述reids2.8及以上版本的同步过程,2.8之前的版本会略有不同。
    2. 参考 http://redis.io/topics/replication
    展开全文
  • 博客参考:散尽浮华的Redis主从复制下的工作原理梳理 此作者写的非常好,此处只做挪用,方便自己查看。 Redis主从复制的配置十分简单,它可以使从服务器是主服务器的完全拷贝。需要清除Redis主从复制的几点重要...

     

    博客参考:散尽浮华的Redis主从复制下的工作原理梳理

    此作者写的非常好,此处只做挪用,方便自己查看。

     

    Redis主从复制的配置十分简单,它可以使从服务器是主服务器的完全拷贝。需要清除Redis主从复制的几点重要内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1)Redis使用异步复制。但从Redis 2.8开始,从服务器会周期性的应答从复制流中处理的数据量。
    2)一个主服务器可以有多个从服务器。
    3)从服务器也可以接受其他从服务器的连接。除了多个从服务器连接到一个主服务器之外,多个从服务器也可以连接到一个从服务器上,形成一个
       图状结构。
    4)Redis主从复制不阻塞主服务器端。也就是说当若干个从服务器在进行初始同步时,主服务器仍然可以处理请求。
    5)主从复制也不阻塞从服务器端。当从服务器进行初始同步时,它使用旧版本的数据来应对查询请求,假设你在redis.conf配置文件是这么配置的。
       否则的话,你可以配置当复制流关闭时让从服务器给客户端返回一个错误。但是,当初始同步完成后,需要删除旧的数据集和加载新的数据集,在
       这个短暂的时间内,从服务器会阻塞连接进来的请求。
    6)主从复制可以用来增强扩展性,使用多个从服务器来处理只读的请求(比如,繁重的排序操作可以放到从服务器去做),也可以简单的用来做数据冗余。
    7)使用主从复制可以为主服务器免除把数据写入磁盘的消耗:在主服务器的redis.conf文件中配置“避免保存”(注释掉所有“保存“命令),然后连接一个配
       置为“进行保存”的从服务器即可。但是这个配置要确保主服务器不会自动重启(要获得更多信息请阅读下一段)

    当主服务器不进行持久化时复制的安全性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    在进行主从复制设置时,强烈建议在主服务器上开启持久化,当不能这么做时,比如考虑到延迟的问题,应该将实例配置为避免自动重启。
     
    为什么不持久化的主服务器自动重启非常危险呢?
    为了更好的理解这个问题,看下面这个失败的例子,其中主服务器和从服务器中数据库都被删除了。
     
    设置节点A为主服务器,关闭持久化,节点B和C从节点A复制数据。
    这时出现了一个崩溃,但Redis具有自动重启系统,重启了进程,因为关闭了持久化,节点重启后只有一个空的数据集。
    节点B和C从节点A进行复制,现在节点A是空的,所以节点B和C上的复制数据也会被删除。
    当在高可用系统中使用Redis Sentinel,关闭了主服务器的持久化,并且允许自动重启,这种情况是很危险的。
    比如主服务器可能在很短的时间就完成了重启,以至于Sentinel都无法检测到这次失败,那么上面说的这种失败的情况就发生了。
     
    如果数据比较重要,并且在使用主从复制时关闭了主服务器持久化功能的场景中,都应该禁止实例自动重启。

    Redis主从复制是如何工作的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    如果设置了一个从服务器,在连接时它发送了一个SYNC命令,不管它是第一次连接还是再次连接都没有关系。
     
    然后主服务器开始后台存储,并且开始缓存新连接进来的修改数据的命令。当后台存储完成后,主服务器把数据文件发送到从服务器,
    从服务器将其保存在磁盘上,然后加载到内存中。然后主服务器把刚才缓存的命令发送到从服务器。这是作为命令流来完成的,并且
    和Redis协议本身格式相同。
     
    你可以通过telnet自己尝试一下。在Redis服务器工作时连接到Redis端口,发送SYNC命令,会看到一个批量的传输,并且主服务器接收
    的每一个命令都会通过telnet会话重新发送一遍。
     
    当主从服务器之间的连接由于某些原因断开时,从服务器可以自动进行重连接。当有多个从服务器同时请求同步时,主服务器只进行一个后台存储。
     
    当连接断开又重新连上之后,一般都会进行一个完整的重新同步,但是从Redis2.8开始,只重新同步一部分也可以。

    部分重新同步

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    从Redis 2.8开始,如果遭遇连接断开,重新连接之后可以从中断处继续进行复制,而不必重新同步。
     
    它的工作原理是这样:
    主服务器端为复制流维护一个内存缓冲区(in-memory backlog)。主从服务器都维护一个复制偏移量(replication offset)和master run id
    当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,假如主从服务器的两个master run id相同,并且指定的偏移量在内存缓冲
    区中还有效,复制就会从上次中断的点开始继续。如果其中一个条件不满足,就会进行完全重新同步(在2.8版本之前就是直接进行完全重新同步)。
    因为主运行id不保存在磁盘中,如果从服务器重启了的话就只能进行完全同步了。
     
    部分重新同步这个新特性内部使用PSYNC命令,旧的实现中使用SYNC命令。Redis2.8版本可以检测出它所连接的服务器是否支持PSYNC命令,不支持的
    话使用SYNC命令。

    无磁盘复制

    1
    2
    3
    4
    通常来讲,一个完全重新同步需要在磁盘上创建一个RDB文件,然后加载这个文件以便为从服务器发送数据。
     
    如果使用比较低速的磁盘,这种操作会给主服务器带来较大的压力。Redis从2.8.18版本开始尝试支持无磁盘的复制。
    使用这种设置时,子进程直接将RDB通过网络发送给从服务器,不使用磁盘作为中间存储。

    配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    主从复制的配置十分简单:把下面这行加入到从服务器的配置文件中即可。
    slaveof 192.168.1.1 6379
     
    当然你需要把其中的192.168.1.1 6379替换为你自己的主服务器IP(或者主机名hostname)和端口。另外你可以调用SLAVEOF命令,
    主服务器就会开始与从服务器同步。
     
    关于部分重新同步,还有一些针对复制内存缓冲区的优化参数。查看Redis介质中的Redis.conf示例获得更多信息。
     
    使用repl-diskless-sync配置参数来启动无磁盘复制。使用repl-diskless-sync-delay 参数来配置传输开始的延迟时间,以便等待
    更多的从服务器连接上来。查看Redis介质中的Redis.conf示例获得更多信息。

    只读从服务器

    1
    2
    3
    4
    5
    6
    7
    8
    从Redis 2.6开始,从服务器支持只读模式,并且是默认模式。这个行为是由Redis.conf文件中的slave-read-only 参数控制的,
    可以在运行中通过CONFIG SET来启用或者禁用。
     
    只读的从服务器会拒绝所有写命令,所以对从服务器不会有误写操作。但这不表示可以把从服务器实例暴露在危险的网络环境下,
    因为像DEBUG或者CONFIG这样的管理命令还是可以运行的。不过你可以通过使用rename-command命令来为这些命令改名来增加安全性。
     
    你可能想知道为什么只读限制还可以被还原,使得从服务器还可以进行写操作。虽然当主从服务器进行重新同步或者从服务器重启后,
    这些写操作都会失效,还是有一些使用场景会想从服务器中写入临时数据的,但将来这个特性可能会被去掉。

    限制有N个以上从服务器才允许写入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    从Redis 2.8版本开始,可以配置主服务器连接N个以上从服务器才允许对主服务器进行写操作。但是,因为Redis使用的是异步主从复制,
    没办法确保从服务器确实收到了要写入的数据,所以还是有一定的数据丢失的可能性。
     
    这一特性的工作原理如下:
    1)从服务器每秒钟ping一次主服务器,确认处理的复制流数量。
    2)主服务器记住每个从服务器最近一次ping的时间。
    3)用户可以配置最少要有N个服务器有小于M秒的确认延迟。
    4)如果有N个以上从服务器,并且确认延迟小于M秒,主服务器接受写操作。
     
    还可以把这看做是CAP原则(一致性,可用性,分区容错性)不严格的一致性实现,虽然不能百分百确保一致性,但至少保证了丢失的数据不会超过M秒内的数据量。
     
    如果条件不满足,主服务器会拒绝写操作并返回一个错误。
    1)min-slaves-to-write(最小从服务器数)
    2)min-slaves-max-lag(从服务器最大确认延迟)

    转载于:https://www.cnblogs.com/fengzhongzhuzu/p/8807803.html

    展开全文
  • 配置Redis主从复制服务3.模拟主服务器挂掉后三、哨兵模式原理1.哨兵的主要作用1.现象2.原因2.哨兵部署流程1.模拟主服务器出现问题down下来,查看从服务器状态变化2.查看之前配置的哨兵检测的主服务器地址情况3.查看...

    一、主从复制原理

    在这里插入图片描述
    ①:从服务器slave先于主服务器master建立socket长连接
    ②:从服务器slave向主服务器master发送一个PSYNC命令,请求复制数据。
    ③:主服务器master接收到PSYNC命令后,会通过bgsave命令利用子线程生成最新的rdb快照文件,并发送给从服务器slave。
    持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存repl buffer中
    ④:slave清掉无用数据,并接受master传来的数据加载到内存中
    ⑤:master再将之前持久化时缓存在内存中的命令发送给slave。
    ⑥:slave接受master发过来的新命令并执行
    ⑦:此时数据已同步完毕,当master再有新的写操作,会通过socket长连接持续的发给slave,保证主从数据一致性!
    注意: 如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

    1、如果在主从传输过程中,从节点挂了怎么办?

    当salve因为网络等原因接收到一半数据时挂掉了,经过一段时间后,人为的重启了salve从节点,那么此时的数据传输是怎么处理呢?
    答:从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。流程图如下:
    在这里插入图片描述
    ①:首先redis在运行时会默认开启一个缓存池,用于缓存最近的redis命令,可以在6379.conf中配置
    repl-backlog-size 1mb ####redis命令缓存池,默认大小为1Mb
    ②:当slave与master断开并重新建立连接时,slave会向master发送PSYNC命令,并通过offset偏移量定位到断开连接时传输数据的位置,从这个位置开始进行断点续传
    ③:如果slave节点断开时间太久,导致偏移量太旧,已经在master中的命令缓存池中找不到对应的位置,那么就会进行一次全量数据的复制。无法使用断点续传了!

    2.什么是主从复制风暴?

    主从复制风暴:多个从节点同时复制主节点导致主节点压力过大
    为了解决主从复制风暴问题,可以让部分从节点与从节点同步数据,架构如下设计:
    在这里插入图片描述

    3.主从复制优缺点

    1.优点

    在这里插入图片描述

    2.缺点

    在这里插入图片描述

    二、Redis项目部署

    1. 项目拓扑图

    在这里插入图片描述

    2.环境

     一台主服务器  master :192.168.1.10
    两台备服务器   slave1 :192.168.1.11
                 slave2 :192.168.1.12
    

    1.安装redis

    主备服务器都需安装
    通过xshell文件传输redis安装包

    1.解压缩

    [root@master ~]# tar zxvf redis-5.0.4.tar.gz   
    [root@master ~]# cd redis-5.0.4/
    [root@master redis-5.0.4]# make 配置安装
    [root@master redis-5.0.4]# make DREFIX=/usr/local/redis install
    更改安装路径可以用make PREFIX=安装路径 install
    [root@master redis-5.0.4]# cd
    

    2.创建链接

    [root@master ~]# ln -s /usr/local/redis/bin/* /usr/local/bin/    
    [root@master ~]# cd redis-5.0.4/utils/    
    [root@master utils]# ls -lh    查看安装脚本
    [root@master utils]# ./install_server.sh    运行脚本
    [root@master utils]# netstat -anpt | grep redis   查看端口状态
    

    在这里插入图片描述
    提示安装成功后,表示Redis的基础配置完成

    2.配置Redis主从复制服务

    在主master服务器上

    [root@master utils]# cd
    [root@master ~]# vi /etc/redis/6379.conf 
    [root@master ~]# /etc/init.d/redis_6379 stop    #服务关闭
    [root@master ~]# /etc/init.d/redis_6379 start    #服务开启
    修改添加
    bind 0.0.0.0                     修改监听地址为0.0.0.0
    daemonize yes                    开启守护进程
    logfile /var/log/redis_6379.log  修改日志文件目录
    dir /var/lib/redis/6379          修改工作目录
    appendonly yes                   开启AOF持久化功能
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在备1、2上编辑配置

    [root@slave1 utils]# vi /etc/redis/6379.conf 
    [root@slave1 utils]# /etc/init.d/redis_6379 restart  服务重启
    修改添加
    bind 0.0.0.0                 修改监听地址为0.0.0.0
    appendonly yes               开启AOF持久化功能
    replicaof 192.168.1.10 6379     增加一个同步master节点IP和端口
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在master服务器上查看
    验证主从效果

    [root@master ~]# tail -f /var/log/redis_6379.log 
    

    在这里插入图片描述
    备2服务器同上

    测试主从数据复制功能
    在master主服务器上

    [root@master ~]# redis-cli   #进入数据库
    127.0.0.1:6379> set fa a     #设置fa键得值为a
    127.0.0.1:6379> get fa       #查看fa键得值
    127.0.0.1:6379> info replication   #信息复制,状态信息
    

    在这里插入图片描述
    在备1服务器上

    [root@slave1 ~]# redis-cli    #进入数据库
    127.0.0.1:6379> get fa        #获取fa键得值
    127.0.0.1:6379> info replication     #信息复制,状态信息
    

    在这里插入图片描述
    在备2服务器上

    // An highlighted block
    var foo = 'bar';
    

    在这里插入图片描述

    3.模拟主服务器挂掉后

    在master主服务器上,关闭服务

    [root@master ~]# /etc/init.d/redis_6379 stop      关闭服务
    [root@master ~]# tail -f /var/log/redis_6379.log  查看日志
    

    在这里插入图片描述
    在备1服务器查看现象

    [root@slave1 ~]# tail -f /var/log/redis_6379.log 查看日志
    [root@slave1 ~]# redis-cli                       进入数据库
    127.0.0.1:6379> get k                            获取k的键值                    
    "aa"                                                  
    127.0.0.1:6379> info replication               信息复制,状态信息
    # Replication
    role:slave                                    状态:从服务器
    master_host:192.168.1.10        
    

    在这里插入图片描述
    在备2服务器上
    在这里插入图片描述
    可以看到把主服务器关闭后,从服务器的状态不会转化成主服务器,但数据会复制转移过来,是可以读取查看到的

    解决办法:
    通过哨兵功能可以实现在主服务器失效时,主从的状态自动转换

    先恢复到之前状态
    master上
    恢复上线

    [root@master ~]# /etc/init.d/redis_6379 start      服务启动
    [root@master ~]# tail -f /var/log/redis_6379.log   查看日志
    [root@master ~]# redis-cli                         进入数据库
    127.0.0.1:6379> info replication            信息复制,状态查看
    # Replication
    role:master          主服务 
    connected_slaves:2   连接2个服务器
    slave0:ip=192.168.1.11,port=6379,state=online,offset=84,lag=1
    slave1:ip=192.168.1.12,port=6379,state=online,offset=84,lag=0
    master_replid:087088c1aa398b11c1e4759e93eb8abb6bc277e2
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:84
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:84
    127.0.0.1:6379> set nb b      添加nb键值为b
    OK
    127.0.0.1:6379> get nb        获取nb的键值
    "b"
    

    在这里插入图片描述
    在备1服务器上

    [root@slave1 ~]# tail -f /var/log/redis_6379.log   #查看日志
    [root@slave1 ~]# redis-cli             
    

    在这里插入图片描述

    三、哨兵模式原理

    • sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点的状态!
    • 哨兵架构下client端第一次请求redis服务时,会先从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
    • 在这里插入图片描述

    1.哨兵的主要作用

    1.现象

    当master节点挂掉后,服务端控制台会打印 连接超时错误,当过一段时间后,又恢复正常,可以继续向redis中写入数据!

    2.原因

    • 原因就是哨兵会时刻监视着master节点,当master节点挂掉,此时服务端控制台会打印连接超时错误。但同时哨兵经过半数机制确认master挂掉,会选举出一个slave作为新的master
    • 选举的这顿时间内,控制台还是会打印错误,一旦选举成功,就会恢复正常连接,这也是出现以上现象的原因!!
    • 当原来挂掉的master节点重新恢复时,将自动称为新的master的丛节点,完成哨兵高可用架构!

    哨兵要设为奇数,最少三台,里面涉及到投票问题!!

    2.哨兵部署流程

    在master服务器上
    编辑哨兵模式的配置文件

    [root@master ~]# vi redis-5.0.4/sentinel.conf 
    修改添加
    protected-mode no               关闭安全模式
    daemonize yes                   指定sentine1为后台启动,开启守护进程
    logfile "/var/log/sentinel.log" 指定日志存放路径
    dir /var/lib/redis/6379         指定数据库存放路径
    
    sentinel monitor mymaster 192.168.1.10 6379 2     
    指定几个哨兵(slave)检测主服务器故障,才会进行故障迁移(主服务器ip地址,端口号,slave数)
    
    sentinel down-after-milliseconds mymaster 3000  
     判定服务器down掉的时间周期,默认30000毫秒(30秒)
     
    sentinel failover-timeout mymaster 100000
    故障节点的最大超时时间为100000毫秒(100秒)
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    拷贝文件到slave1,slave2上

    [root@master ~]# scp redis-5.0.4/sentinel.conf root@192.168.1.11:/root/redis-5.0.4
    [root@master ~]# scp redis-5.0.4/sentinel.conf root@192.168.1.12:/root/redis-5.0.4
    

    在这里插入图片描述
    启动哨兵模式
    先启master服务器,后启slave服务器

    [root@master ~]# redis-sentinel redis-5.0.4/sentinel.conf &
    [1] 69742
    [root@slave1 ~]# redis-sentinel redis-5.0.4/sentinel.conf &
    [1] 62685
    [root@slave2 ~]# redis-sentinel redis-5.0.4/sentinel.conf &
    [1] 62250
    

    在master服务器上
    1.查看日志

    [root@master ~]# tail -f /var/log/sentinel.log 
    

    2.查看进程状态

    [root@master ~]# ps aux | grep redis
    [root@master ~]# ps aux | grep sentinel
    

    在这里插入图片描述
    表明哨兵服务已经启动
    3.远程登录数据库查看哨兵状态

    [root@master ~]# redis-cli -h 192.168.1.10 -p 26379 info sentinel
    [root@master ~]# redis-cli -h 192.168.1.10 -p 6379 info replication
    

    1.模拟主服务器出现问题down下来,查看从服务器状态变化

    在master服务器上

    [root@master ~]# /etc/init.d/redis_6379 stop  停止服务
    [root@master ~]# ps aux | grep redis        查看进程状态
    

    在这里插入图片描述
    在从服务器上进行日志查看

    [root@slave1 ~]#  tail -f /var/log/sentinel.log 
    

    发现master状态转移到从备1上

    在slave2查看远程登录查看哨兵信息

    [root@slave2 ~]# redis-cli -h 192.168.1.11 -p 26379 info sentinel
    

    2.查看之前配置的哨兵检测的主服务器地址情况

    在备1服务器上

    [root@slave1 ~]# vi redis-5.0.4/sentinel.conf 
    

    在这里插入图片描述
    在主服务器上
    在这里插入图片描述
    发现的配置地址变化,在自动切换主状态时也会自动变更检测地址

    3.查看当原master服务器恢复上线时,状态变化

    在master服务器上

    [root@master ~]# /etc/init.d/redis_6379 start  服务启动
    [root@master ~]# ps aux | grep redis           查看进程端口状态
    [root@master ~]# tail -f /var/log/sentinel.log 查看日志文件
    

    在这里插入图片描述

    在slave2上
    查看数据库哨兵状态

    [root@slave2 ~]# redis-cli -h 192.168.1.11 -p 26379 info sentinel
    

    发现在原主服务器出现上线后,master状态并不会再次转换重新到自己上,这一点不同于vrrp服务,原因vrrp有优先级设置,此处服务没有。

    展开全文
  • Redis 主从原理分析

    2020-11-06 15:53:19
    文章目录数据全量复制数据部分复制主从复制风暴 如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个PSYNC命令给master请求复制数据。 master收到PSYNC命令后,会在后台进行...
  • Sentinel(哨兵)的来由书接上文,我们学习了redis的replication的原理,我们这一章来讨论一下redis主从策略的高可用性。这个哨兵的插件是我们redis里面集成了的(部署简单略),哨兵会监控主从的各个节点状态,当主...
  • 作用 我们正常在项目中对redis进行应用,一般都不会是单点的。因为,单点的宕机即不可用,不能保证可用性。... redis主从策略分为两大类知识点:1,replication复制策略。2,sentinal高可用性故...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,567
精华内容 1,026
关键字:

redis主从原理

redis 订阅