Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)

目录

redis实现持久化的两种模式

redis主从架构

redis主从集群 -- 数据同步优化

redis主从集群+哨兵框架

redis分片集群


redis实现持久化的两种模式

RDB持久化


RDB全称Redis Database Backup file(Redis数据备份文件),也被称为数据快照,就是把redis内存中的所有数据写入到本地磁盘中, 当服务宕机重启后,可以读取本地磁盘文件来恢复数据,Redis数据备份文件被称为RDB文件,默认是保存在当前运行目录下(可通过配置文件更改相关保存信息)


执行时机:

        1) 执行save命令

        2) 执行bgsave命令

        3) 正常停机时

        4) 达到RDB自动保存的阈值时


save命令:

        执行save命令,会触发一次RDB持久,是主进程在进行磁盘IO, 此时无法对外提供服务,会阻塞请求, 只适用于手动停机,数据迁移的场景

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第1张图片

 bgsave命令:

        与save命令不同的是,bgsave是异步执行的,从主进程fork一个子进程进行持久化操作,在磁盘IO的时候,不会阻塞请求,主进程能够正常的提供服务,值得注意的是在主线程fork的时候是阻塞请求的状态

RDB自动保存阈值:

        Redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:

save 900 1            # 900秒内,如果至少有1个key被修改,则执行bgsave
save 300 10           # 300秒内, 如果至少有10个key被修改,则执行bgsave
save 60 10000         # 60秒内,10000个key

# 如果是save "" 则表示禁用RDB

其他配置:

# 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes

# RDB文件名称
dbfilename dump.rdb  

# 文件保存的路径目录
dir ./ 

RDB执行原理:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第2张图片

 save:

         操作系统会在redis中维护一个虚拟内存表" 页表 " ,页表和物理内存有映射关系,所以redis主进程在持久化的时候,只需要操作虚拟内存中的页表,操作系统会从页表中读取数据,实现磁盘IO

bgsave:

        会从主进程fork出一个子进程,fork的过程是将主进程中的页表复制到子进程中,子进程拥有同样的映射关系后,就可以读取物理内存,生成RDB文件. 这样虽然fork效率高,而且不会影响主进程对外提供服务,但是异步的,就会出现脏读的现象出现,而fork也想到了这一点,采用了copy-on-write技术:

        在子进程读的时候,会把内存数据标记成read-only状态,此时主线程只能进行读取,若要进行写操作,就要在内存中拷贝一份数据副本,对数据副本进行写操作,数据副本产生后,主线程页表就会映射数据副本,

        在redis优化中,会提到在给redis分配内存的时候尽量有一般的内存留余,在极端情况下,有可能子线程读取很慢,而主进程的写操作很多,就会导致拷贝很多的数据副本,甚至会拷贝全部的数据副本,这样redis内存就翻倍了,但这种情况几乎不会出现,但理论上是会出现


RDB的缺点:

        两次RDB操作之间如果服务宕机,就会丢失数据, 无法保证数据的强完整性

        fork子进程,生成RDB文件,压缩RDB文件都比较耗时

  AOF持久化


AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。当需要进行数据恢复的时候,重新执行AOF文件即可

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第3张图片

 AOF模式的开启:

        该模式默认是不开启的,需要我们修改redis.conf配置文件来开启AOF:

# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"

        AOF的IO频率也可以通过配置文件进行更改:

# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always 

# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec 

# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

        三种模式的对比:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第4张图片


AOF的文件命令重写:

        在redis中,往往会有对同一个key有不同的操作,这些操作命令都会被存储在AOF文件中,所以AOF文件会比RDB文件大很多,同时这些对同一个key的多条命令,只有最后一条才有价值,所以我们可以通过执行bgrewriteaof命令对其进行体积优化()BGREWRITEAOF — Redis 命令参考BGREWRITEAOF — Redis 命令参考()BGREWRITEAOF — Redis 命令参考,

         如图,AOF原本有三个命令,但是set num 123 和 set num 666都是对num的操作,第二次会覆盖第一次的值,因此第一个命令记录下来没有意义。 所以重写命令后,AOF文件内容就是:mset name jack num 666   ,

Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置:

# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100

# AOF文件体积最小多大以上才触发重写 
auto-aof-rewrite-min-size 64mb 

 RDB与AOF两种持久化模式对比:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第5张图片

 在企业应用中,我们一般会根据数据的价值,效率等各方条件进行评估,再考虑使用哪种方式

redis主从架构

主从架构


单节点的redis对并发的承受能力是有限的,所以如果业务流量大,我们会对redis搭建主从架构,进行读写分离  redis主从搭建

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第6张图片

redis集群的主从数据同步有两种方式,全量同步/增量同步

全量同步


执行时机:

        在主从服务器第一次连接或者从服务器长时间未同步的时候会执行全量同步,会将master节点上的所有数据同步到slave节点上

        在主从数据同步的时候,会有两个属性, Replication Id,offset用来判断slave是否是第一次连接,slave数据同步到哪里了

Replication Id:

        简称replid,是数据集的标记,master与slave节点都有replid,但是id不一样, 只有在建立连接的时候,slave节点才会继承master分支的replid,所以在进行主从连接的时候, 可以通过id是否一致来判断是需要进行全量同步

offset:

        偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

repl_baklog:

        在master节点执行持久化的时候,会记录所有持久化期间的命令到repl_baklog, 用来计算offset偏移量

因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据。

流程图:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第7张图片

 全量同步是将生成的RDB文件通过网络进行传输,传输成本较高,所以一般都是主从节点第一次连接的时候进行全量同步,全量同步后,就会陆续执行增量同步,来确保数据一致性

 增量同步


执行时机:

        全量同步是将生成的RDB文件通过网络进行传输,传输成本较高,所以一般都是主从节点第一次连接的时候进行全量同步,全量同步后,就会陆续执行增量同步,来确保数据一致性,

        增量同步是通过offset值来判断slave节点同步到哪里了, 然后会将repl_baklog中的偏差记录发送给slave节点,slave节点执行记录使其同步

流程图:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第8张图片

如何通过offset值来确定同步位置的:

这就要说到全量同步时的repl_baklog文件了。这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。repl_baklog中会记录Redis处理过的命令日志及,包括master当前的offset值,和slave已经拷贝到的offset值

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第9张图片此时,master的offset值与slave的offset值的差值,就是slave需要增量同步的数据

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第10张图片随着数据的不断持久化,master的offset值会不断增大,而slave也会不断的进行增量同步

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第11张图片直到数据被填满,,此时master就会覆盖绿色部分(也就是slave已经同步过的数据)

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第12张图片Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第13张图片但如果salve在增量同步的过程中遇到了阻塞,就会导致从节点的进度赶不上主节点的进度,有可能会导致slave的offset被覆盖,如果此时slave状态恢复,就无法进行增量同步了,只能进行全量同步

redis主从集群 -- 数据同步优化

主从同步可以保证主从数据的一致性,非常重要。可以从以下几个方面来优化Redis主从就集群:

- 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
- Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
- 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
- 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第14张图片

redis主从集群+哨兵框架

redis主从集群可以实现高并发读的功能,配合哨兵框架可实现高可用


架构图:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第15张图片

哨兵的作用如下:

        监控:Sentinel 会不断检查您的master和slave是否按预期工作

        自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主

        通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端


集群监控原理:

        Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

        主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。

        客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例**客观下线**。quorum值最好超过Sentinel实例数量的一半。

自动故障恢复原理:

        一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点然后判断slave节点的slave-priority值(默认都为1),越小优先级越高,如果是0则永不参与选举,如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高最后是判断slave节点的运行id大小,越小优先级越高。

        选举成功后的执行流程:

        sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master

        sentinel给所有其它slave发送slaveof (IP地址) + 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。

        最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第16张图片

redis分片集群

分片集群


redis读写分离配合哨兵模式可以实现高可用,高并发读的要求,但不满足海量数据存储,高并发写的要求,所以我们可以搭建redis分片集群

架构图:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第17张图片

分片集群特征:

        集群中有多个master,每个master保存不同数据      

        每个master都可以有多个slave节点 

        master之间拥有心跳检测机制,通过ping监测彼此健康状态

        分片集群中存在散列插槽机制,所以客户端请求可以访问集群任意节点,最终都会被转发到正确节点

 散列插槽(hash插槽)


Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第18张图片

 数据中的key不是与master节点进行绑定的,而是与插槽进行绑定的,所以不用指定访问哪个节点,redis会根据key的插槽值找到key所在的位置,而插槽值是根据key的有效部分计算的, 盘点有效部分有两种情况

- key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分  # key: {a}num  会根据a计算插槽值
- key中不包含“{}”,整个key都是有效部分        # key: num  会根据num计算插槽值

计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。


如何将一类数据分配到统一节点上:

        综上得知,分片集群中的每个节点都是映射16384个插槽的一部分,数据进行存储的时候是计算key的slot值进行存储, 那同一类数据对的key值可能会计算出不同的slot值,就会被分配到不同的节点上,如果要实现对一类数据的群组化,我们就可以利用slot值计算的有效部分,在同一类数据key加上{typeID},这样计算出的slot值就会一样了

 集群伸缩


如何添加一个分片节点:

        Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第19张图片

new_host参数:                新节点的ip地址

new_port参数:                新节点的端口号

existing_host参数:                任意一个已经存在的节点的ip

existing_port参数:                任意一个已经存在的节点的端口

existing_host参数和existing_port参数用于推送新节点上线信息给集群中的其他节点


转移插槽:

        在新节点上线后,是没有插槽映射的,所以需要我们手动分配插槽

命令:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第20张图片

 首先建立连接(这里ip和端口号可以填写任意旧节点的信息):

 选择抽取多少个插槽:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第21张图片

 填写新节点id,接收插槽:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第22张图片

 以哪种方式抽取插槽:

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第23张图片

 - all:代表全部,也就是三个节点各转移一部分
- 具体的id:目标节点的id
- done:没有了

我们这里填写具体的节点id

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第24张图片

 完成

 故障转移


自动故障转移:

        分片集群支持自动故障转移,当一台master故障后, 集群内的心跳机制就会发现,当超过一般的节点认为该节点下线后,就会自动选举一个salve当做新的master,而当故障节点重启后,会以salve的角色进行运行

手动故障转移:

        利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第25张图片

 Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)_第26张图片

 

你可能感兴趣的:(redis高级,redis,架构)