Redis持久化与主从复制的实践

为什么需要持久化

Redis是基于内存的NoSQL数据库,读写速度自然快,但内存是瞬时的,在redis服务关闭或重启之后,redis存放在内存的数据就会丢失,为了解决这个问题,redis提供了两种持久化方式,以便在发生故障后恢复数据。

持久化选项

redis提供了两种不同的持久化方式来将数据存储到硬盘中。一种是快照方式(也叫RDB方式),它可以将莫一时刻存在于redis中的所有数据存储到硬盘;另一种叫只追加文件(AOF)方式,它会定时的复制redis执行的所有写命令到硬盘。这两种持久化方式各有千秋,既可以同时使用,也可以独立使用,在某些情况下甚至可以两种都不使用。

RDB方式

RDB方式也称快照方式,通过创建快照来保存某个时间点上的数据副本(.rdb)到硬盘。在重启服务器后,redis会加载这个rdb文件来还原数据。先来看一下rdb持久化配置。
vi redis.conf打开redis的配置文件,找到SNAPSHOTTING部分,发现如下内容:

save 900 1
save 300 10
save 60 10000
……
dbfilename dump.rdb
dir ./

说明

  • save seconds changes:表示在seconds秒后,如果有不少与changes个key发生改变,则保存一次快照。可以看到,rdb持久化默认是开启的,并且配置了三个save选项,如果想要关闭rdb持久化,将所有的save注释掉就好了
  • dbfilename:rdb文件名
  • dir:rdb文件存放路径

创建快照

BGSAVE:
BGSAVE命令可以用于创建一个快照,在redis接收到BGSAVE命令后会fork出一个子进程,子进程负责将快照写入硬盘,而父进程则继续处理命令请求。需要注意的是redis在创建子进程时会阻塞父进程,时间长短与redis占用的内存大小成正比。
除了手动的调用BGSAVE命令外,BGSAVE命令的触发条件有如下两种:

  • 用户配置了save选项,从redis最近一次创建快照开始算起,当任意一个save选项的条件被满足时,会触发一次BGSAVE命令。
  • 在进行主从复制连接时,刚连上来的从服务器会向主服务器发送SYNC命令请求数据同步,在主服务器收到SYNC命令后,会执行一次BGSAVE命令,后将生成的rdb文件发送给从服务器进行数据同步。

SAVE:
SAVE命令同样可以创建一个快照,但与BGSAVE命令不同的是SAVE命令不会创建子进程,所以接收到SAVE命令的redis服务器在快照创建完毕之前不会响应其他任何命令。由于在创建快照的过程中没有其他进程抢夺资源,所以SAVE命令创建快照的速度会比BGSAVE命令创建快照更快一些。即使这样,SAVE命令也并不常用,通常只会在没有足够内存或等待快照生成完毕也无所谓的情况下才会使用。
例如,当redis收到SHUTDOWN命令关闭服务时,就会执行一次SAVE命令,阻塞所有客户端,并在SAVE命令执行完毕后关闭。

RDB方式的优劣

优势:

仅用一个文件备份数据,灾后易于恢复相比于aof,rdb文件更小,并且加载rdb文件恢复数据也更快

劣势:

如果redis服务因故障关闭或重启,会丢失最近一次快照创建后写入的数据当数据量很大的时候,创建子进程会导致redis较长时间的停顿

AOF方式

简单来说,AOF持久化会将被执行的写命令写到aof文件的末尾,以此来记录数据发生的变化。因此,redis只要从头到尾重新执行一遍aof文件中包含的所有写命令,就可以恢复数据。

打开redis配置文件可以看到:

# 是否开启aof持久化,默认为关闭(no)
appendonly yes
# 设置对aof文件的同步频率
# 每接收到一条写命令就进行一次同步,数据保障最有力,但对性能影响十分严重
appendfsync always
# 每秒进行一次同步,推荐
appendfsync everysec
# 由操作系统来决定何时进行同步
appendfsync no
# 重写aof相关
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

重写/压缩aof文件

由于aof持久化会不断地记录redis的写命令,随着redis的运行,aof文件会越来越大,占用过多的硬盘空间,并增加redis进行数据还原操作的时间。因此,必须要有避免aof文件体积过大的控制方案。

redis提供了BGREWRITEAOF命令对aof文件进行重写,BGREWRITEAOF会通过移除原aof文件中冗余的命令来尽可能的减小aof文件的体积。BGREWRITEAOF的工作原理与BGSAVE很像,会由redis创建一个子进程,再由子进程对aof文件进行重写。

当然,BGREWRITEAOF命令同样也有自动触发的机制,可通过配置auto-aof-rewrite-percentageauto-aof-rewrite-min-size来自动执行。例如,配置了auto-aof-rewrite-percentage 100 和 auto-aof-rewrite-min-size 64mb,并且开启了aof持久化,那么在aof文件体积大于64mb且当前文件比上一次重写后的文件体积大了一倍(100%)以上时,redis会自动执行BGREWRITEAOF命令。

AOF持久化的优劣

优势

可以将丢失数据的时间窗口降低至1秒,并且不会对性能在成太大影响aof对于日志文件采用的是追加模式,因此在写入过程中即使出现宕机,也不会破坏日志文件中已经存在的内容;若只写入一半数据就宕机,在redis下次启动时,可通过redis-check-aod工具来解决数据一致性的问题

劣势

aof文件的体积一直是AOF持久化最大的缺陷,即使有重写aof文件的机制存在载入aof文件恢复数据的过程会比载入rdb文件耗时更长

主从复制

尽管redis性能十分优秀,但还是会遇到无法快速处理请求的问题,为了抗高并发带来的数据库性能问题,redis可以像关系型数据库一样进行主从复制、读写分离。即向主服务器写入数据,从服务器实时收到更新,并使用从服务器处理所有的读请求,而不是像以前一样将所有读请求都发送给主服务器,造成主服务器压力过大,通常读请求会随机地选择使用哪一个从服务器,从而使负载均衡地分配到每一个从服务器上。下图是一个简单的redis主从架构。

主从复制配置

首先在你的redis目录下执行vi redis6380.conf在当前目录下创建一个redis配置文件,写入如下内容:

include /usr/local/redis-4.0.13/redis.conf
port 6380
pidfile /var/run/redis_6380.pid
logfile 6380.log
dbfilename dump6380.rdb

说明:

  • include:向当前配置文件中引入所指向的配置文件的配置信息,这里引入的是redis默认配置文件,其中已经设置过远程访问、密码等,没必要在新的配置文件中重新设置。对于有必要重新配置的配置信息来说(如端口号),include行下进行的配置可以覆盖引用的配置。
  • port:端口号,我们的主从服务器是跑在同一台虚拟机上的,因此需要配置不同的端口号。
  • pidfile:自定义的pid文件,后台程序的pid存在这个文件里。
  • logfile:日志文件。
  • dbfilename:rdb文件的名字。

经过上述操作,一个新的主服务器就配置好了,接下来配置从服务器,同样在当前目录下创建一个redis配置文件起名redis6382vi redis6382.conf

include /usr/local/redis-4.0.13/redis.conf
port 6382
pidfile /var/run/redis_6382.pid
logfile 6382.log
dbfilename dump6382.rdb
slaveof 127.0.0.1 6380
masterauth 主服务器的密码

其中有一些从服务器额外的配置:

  • slaveof:表示我是谁的从服务器,需要制定主服务器的ip地址和端口号
  • masterauth:假如你的主服务器配置了密码,那么需要在此进行配置,否则从服务器将无法连接到主服务器

其他的从服务器配置也都类似,注意分配端口号,我这里又配置了一个6384。
配置成功后,在src目录下使用./redis-server ../redis6380.conf就可以开启主服务器了,接下来开启从服务器会自动连到主服务器上,注意指定对应的配置文件。
执行ps -ef | grep redis看到如下内容则表示主从服务器启动成功:

root      2625     1  0 16:15 ?        00:00:00 ./redis-server *:6380
root      2630     1  0 16:15 ?        00:00:00 ./redis-server *:6382
root      2636     1  0 16:15 ?        00:00:00 ./redis-server *:6384

在主从服务器都启动好了以后,进入主服务器的客户端./redis-cli -p 6380 -a 你的密码,执行info replication可以查看主从服务器信息,如下

127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6382,state=online,offset=336,lag=1
slave1:ip=127.0.0.1,port=6384,state=online,offset=336,lag=1
master_replid:b5c68a979b28d2a9ef53476510758b5d1795418b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:336
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:336

同样,在从服务器客户端中执行上述命令,也能够得到信息

127.0.0.1:6384> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:686
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:b5c68a979b28d2a9ef53476510758b5d1795418b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:686
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:672

至此,一个一主两从、读写分离的redis架构已经配置好并成功启动了。

主从复制的启动过程

上图是旧版主从Redis的启动过程,需要特殊说明的几点是:

  • 从服务器在进行初始连接的时候,数据库中原有的所有数据都将被丢失,并替换成主服务器发送来的数据
  • 从服务器不负责key的过期操作,而是被动的接受主服务器发来的命令,当一个 master 让一个 key 到期(或由于 LRU 算法将之驱逐)时,它会合成一个 DEL 命令并传输到所有的 slave
  • SYNC是一个非常耗费资源的操作,在BGSAVE期间主服务器的总吞吐量下降,接着耗费大量的主从服务器的网络资源传送rdb文件,在从服务器载入rdb文件时会无法响应客户端的请求;但SYNC最大的缺陷是在从服务器因断线进行重新连接时,没必要申请一个rdb文件从头再加载一次,因为这个新的rdb文件中包含的大部分数据很可能在断线之前就已经写入了从服务器,此时从服务器只需要得到在断线期间写入的数据就得了

部分重同步

为了弥补旧版复制的缺陷,Redis从2.8版本开始使用PSYNC命令代替SYNC命令。PSYNC有完整重同步和部分重同步两种模式,其中完整重同步和上述的旧版同步差不多,也是得发个rdb。但是部分重同步很牛X了:它可以只将断线期间的写入主服务器的写命令发送给从服务器,耗费资源更少,速度也快的多。如下图。

部分重同步的实现原理并不复杂,由三部分构成:复制偏移量(offset)、复制积压缓冲区和服务器运行id(runid)

复制偏移量
复制偏移量是用来确认主从服务器的同步状态的。主从服务器各自维护一份复制偏移量,当主服务器向从服务器发送了N个字节的数据时,就将自己的复制偏移量加上N;从服务器收到N个字节的数据也会将自己的复制偏移量加上N。通过比较主从双方的复制偏移量就可以很容易的确认同步状态。

复制积压缓冲区
复制积压缓冲区是由主服务器维护的一个固定长度的先进先出的队列,在主服务器进行命令传播的时候会顺道让命令入队到复制积压缓冲区中,如下:

由于复制积压缓冲区是一个固定长度的队列,所以它只会保存最近一段时间内执行的写命令,并为队列中的每个字节记录对应的复制偏移量。在从服务器发送PSYNC命令时,会携带上自己的复制偏移量,主服务器拿着这个偏移量去自己的复制积压缓冲区中查看offset+1(即断线后执行的下一个命令)还在不在队列中。如果还在,表示可以执行部分重同步,后面会将从offset+1到队尾的所有数据发送给从服务器;如果不在,那从服务器只能老老实实的去做完全重同步。

服务器运行Id
服务器运行Id说白了就是看主从服务器断线之前是不是一家子。每一个redis服务器都有自己的运行id,主从初次连接时,主服务器会把自己的服务器运行id发送给从服务器保存起来,从服务器在重连接的时候会把之前保存的主服务器runid一并发给主服务器,主服务器会拿着这个runid和自己的runid进行比对。如果一致,则表示该从服务器之前确实是从自己这里断线的,接下来进行偏移量的检查;如果不一致,则表示这个从服务器先前是其他主服务器的slave,直接打去做完全重同步。

在之前执行info replication命令的时候就可以看到服务器运行id和复制偏移量。

综上,一个新版redis复制的同步过程大致如下:

到此这篇关于Redis持久化与主从复制的实践的文章就介绍到这了,更多相关Redis持久化与主从复制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 使用Docker搭建Redis主从复制的集群

    在主从复制模式的集群里,主节点一般是一个,从节点一般是两个或多个,写入主节点的数据会被复制到从节点上,这样一旦主节点出现故障,应用系统能切换到从节点去读写数据,这样能提升系统的可用性.而且如果再采用主从复制模式里默认的读写分离的机制,更能提升系统的缓存读写性能.所以对性能和实时性不高的系统而言,主从复制模式足以满足一般的性能和安全性方面的需求. 1 概述主从复制模式 在实际应用中,如果有相应的设置,在向一台Redis服务器里写数据后,这个数据可以复制到另外一台(或多台)Redis服务器,这里数据

  • Redis教程(九):主从复制配置实例

    一.Redis的Replication: 这里首先需要说明的是,在Redis中配置Master-Slave模式真是太简单了.相信在阅读完这篇Blog之后你也可以轻松做到.这里我们还是先列出一些理论性的知识,后面给出实际操作的案例. 下面的列表清楚的解释了Redis Replication的特点和优势. 1). 同一个Master可以同步多个Slaves.     2). Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力.因此我们可以将Redis的R

  • redis主从复制原理的深入讲解

    前言 Redis持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障. 本文主要针对redis主从复制的原理进行了讲解,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 slaveof 命令. 从节点只是保存了

  • Redis主从复制问题和扩容问题的解决思路

    一.解决主从复制问题 当使用Redis作为存储引擎的时候,并且使用Redis读写分离,从机作为读的情况,从机宕机或者和主机断开连接都需要重新连接主机,重新连接主机都会触发全量的主从复制,这时候主机会生成内存快照,主机依然可以对外提供服务,但是作为读的从机,就无法提供对外服务了,如果数据量大,恢复的时间会相当的长.为了解决Redis主从Copy的问题,有如下两个解决方案: 主动复制所谓主动复制,就是业务层双写多个Redis,避开Redis自带的主从复制.但是自己干同步,就会产生一致性问题,为了保证

  • Redis主从复制详解

    单机Redis存在的问题 无法故障转移 ,无法避免单点故障 磁盘空间的瓶颈 QPS瓶颈 Redis主从复制的作用 提供数据副本 扩展读性能 配置方法 通过命令 通过配置文件 演示 为方便演示,在一台服务器上搭建redis主从(生产上不会这样做),根据端口区分. 主库 6379 从库 6380 编辑配置文件 vi  redis-6379.conf #后台进程启动 daemonize yes #端口 port 6379 #日志文件名称 logfile "6379.log" #Redis工作

  • Redis持久化与主从复制的实践

    为什么需要持久化 Redis是基于内存的NoSQL数据库,读写速度自然快,但内存是瞬时的,在redis服务关闭或重启之后,redis存放在内存的数据就会丢失,为了解决这个问题,redis提供了两种持久化方式,以便在发生故障后恢复数据. 持久化选项 redis提供了两种不同的持久化方式来将数据存储到硬盘中.一种是快照方式(也叫RDB方式),它可以将莫一时刻存在于redis中的所有数据存储到硬盘:另一种叫只追加文件(AOF)方式,它会定时的复制redis执行的所有写命令到硬盘.这两种持久化方式各有千

  • Redis持久化RDB和AOF区别详解

    RDB是Redis内存到硬盘的快照,用于redis持久化,创建RDB二进制文件,将存储在内存中的数据,持久化的放到硬盘中,当我们需要这些数据的时候,启动载入RDB文件,数据将会被存入内存中,其实RDB就是一种快照的方式持久化存储数据,也可以作为一种复制媒介,这个我们后面在谈. RDB 触发机制--主要三种方式 save 同步命令(会阻塞redis) bgsave 异步命令(fork) 自动 Save同步命令 save 文件策略:生成一个临时文件,如果存在老的文件,将会替换旧文件 bgsave 异

  • Redis持久化深入详解

    1.概述 Redis 是内存数据库,如果不能将内存中的数据保存到磁盘中,那么一旦服务器进程退出,服务器的数据库数据也会消失,所以Redis提供了持久化的功能,redis分为两种持久化方式:RDB和AOF.有以下几个特点: 1.RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储. 2.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件后台重写,使得AOF文件的

  • 浅谈Redis在直播场景的实践方案

    背景信息 视频直播间作为直播系统对外的表现形式,是整个系统的核心之一.除了视频直播窗口外,直播间的在线用户.礼物.评论.点赞.排行榜等数据信息时效性高,互动性强,对系统时延有着非常高的要求,非常适合使用Redis缓存服务来处理. 本篇最佳实践将向您展示使用Redis版搭建视频直播间信息系统的示例.您将了解三类信息的构建方法: 实时排行类信息 计数类信息 时间线信息 实时排行类信息 实时排行类信息包含直播间在线用户列表.各种礼物的排行榜.弹幕消息(类似于按消息维度排序的消息排行榜)等,适合使用Re

  • Redis 持久化 RDB 与 AOF的执行过程

    目录 前言 一.RDB 1. save 命令 2. bgsave 命令 3. 内部触发 RDB 场景 4. RDB 参数配置 5. RDB 缺点 二.AOF 1. 参数配置 2. AOF 执行流程 前言 Redis 持久化支持两种方式 RDB 与 AOF,文章记录两者的执行过程与配置. 一.RDB RDB 持久化是把当前进程数据生成快照保存到硬盘的过程,触发 RDB 持久化过程分为手动触发和自动触发. 1. save 命令 会堵塞当前 Redis 服务器,直到 RDB 结束为止,对数据量较大或者

  • MySQL实现配置主从复制项目实践

    目录 一.检测通信 二.master配置 1. 开启二进制日志 2. 创建一个用于主从库通信用的账号 3. 获取binlog文件名和position 三.slave配置 1. 配置全局唯一的server-id 2. 使用master创建的账户读取binlog同步数据 3. 开启slave服务 四.配置中可能出现的问题 1. 网络连接问题 2. binlog的position问题 3. SQL线程出错 一.检测通信 查看master(centos7)和slave(win10)的ip地址,并检测是否

  • Redis键值设计的实践

    目录 1 优雅的key结构 2 拒绝BigKey 2.1 判断BigKey 2.2 BigKey的危害 2.3 如何发现BigKey 2.4 如何删除BigKey 3 恰当的数据类型 3.1 存储对象 3.2 Hash优化 在Redis中,良好的键值设计可以达成事半功倍的效果,而不好的键值设计可能会带来Redis服务停滞,网络阻塞,CPU使用率飙升等一系列问题,今天就教大家如何设计一个良好的key-value 1 优雅的key结构 Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约

  • 从源码解读redis持久化

    为什么需要持久化? 由于Redis是一种内存型数据库,即服务器在运行时,系统为其分配了一部分内存存储数据,一旦服务器挂了,或者突然宕机了,那么数据库里面的数据将会丢失,为了使服务器即使突然关机也能保存数据,必须通过持久化的方式将数据从内存保存到磁盘中. 对于进行持久化的程序来说,数据从程序写到计算机的磁盘的流程如下: 1.客户端发送一个写指令给数据库(此时数据在客户端的内存) 2.数据库接收到写的指令以及数据(数据此时在服务端的内存) 3.数据库发起一个系统调用,把数据写到磁盘(此时数据在内核的

  • 内存型数据库Redis持久化小结

    因为Redis是内存型数据库,所以为了防止因为系统崩溃等原因导致数据丢失的问题,Redis提供了两种不同的持久化方法来将数据存储在硬盘里面,一种方法是快照(RDB),它可以将存在于某一个时刻的所有数据都写入到硬盘里面,另外一种方法是只追加文件(AOF),它会在执行写命令时,将被执行的写命令都写入到硬盘里面. 快照持久化 Redis可以通过创建快照来获得在内存里面的数据在某一个时间点上的副本.在创建快照之后,用户可以对快照进行备份,可以将快照复制到其它服务器从而创建具有相同数据的服务器副本,还可以

  • redis持久化的介绍

    1. RDB 1.1 RDB简介 RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里. 工作机制:每隔一段时间,就把内存中的数据保存到硬盘上的指定文件中. RDB是默认开启的! Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件.整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对

随机推荐