Redis的持久化机制

Redis的高性能网络IO模型

https://blog.csdn.net/luciferlongxu/article/details/119391079

Redis的内存淘汰策略

https://blog.csdn.net/luciferlongxu/article/details/119190895

Redis的持久化机制

持久化机制保证数据可靠性,Redis提供了两种持久化机制:RDB、AOF

RDB(快照模式--默认)

对当前时间点记录在内存中的数据进行拍照,记录内存中保存的数据,实质上就是把内存中的数据写入到磁盘上,生成的快照就是一个名字为dump.rdb的二进制文件

快照触发条件

1、在redis.conf配置文件中可以配置快照触发条件

如下图所示:在3600s内任意一个key发生改变就会触发快照保存,或者300s内有100个key发生改变就触发快照保存,或者60s内有10000个key发生改变就触发

2、SAVE命令、BGSAVE

SAVE命令是同步的,执行SAVE命令触发快照时,应用端无法发送指令到redis,会阻塞等待

BGSAVE命令是异步的,通过fork去创建一个子进程,执行BGSAVE命令触发快照时,应用端可以正常发送指令做其他操作

3、flushall:执行此命令可触发生成快照

类似与delete清空数据,清空数据的同时生成个一个快照,快照中是空的

4、Master-Replica复制的时候会被动触发生成快照

通过快照恢复数据的方式

1、首先shutdown redis服务

2、把备份的快照名字(如dump.rdb.bak)修改成正常的快照(dump.rdb)

3、启动redis服务,数据就会恢复成备份的数据

适用场景:灾备恢复、定期备份

缺陷:生成快照有个间隔时间,在间隔时间内有可能出现数据丢失


AOF(Append Only File)

采用日志的方式来保存每个事物操作,类似mysql的binlog

在redis.conf中配置开启AOF模式

# 配置开启aof模式,设置文件名字
appendonly yes
appendfilename "appendonly.aof"

同步磁盘方式

# appendfsyn always #每个命令实时写入数据到磁盘
appendfsyn everysec #每秒执行一次,最多可能丢失1s数据
# appendfsyn no #no表示交给操作系统来决定,默认30s

rewrite

重新生成当前时间的aof文件,覆盖压缩前的aof文件,因为appendonly.aof日志文件中记录的数据太详细了,这样会占用大量内存空间,所以通过rewrite来压缩内存,重写数据将无效的指令压缩

自动触发重写:在redis.conf中配置自动触发

# 当目前的aof文件大小超过上次重写aof文件大小的百分之多少时触发重写
auto-aof-rewrite-percentage 100
# 当目前的aof文件大小小于64m时不需要触发重写
auto-aof-rewrite-min-size 64mb

手动触发重写:通过bgrewriteaof命令来触发重写


Redis高可用(High Availability)

  • 主从复制(Master-Slave)
  • 哨兵机制(实现master选举)
  • 集群机制

主从复制

slave节点请求主节点,保存了主节点的数据副本,当主节点宕机的时候,从节点可以代替主节点的位置,主从复制是基于RDB文件来完成。

  1. 一主多从:所有事务操作(修改、删除)访问主节点,从节点只支持读操作;这样可以实现读写分离,还可以避免出现数据不一致问题;但是如果slave节点过多,需要不停从主节点同步数据到从节点,会影响master的性能
  2. 级联复制:master节点同步数据给一个slave节点,这个slave节点负责同步数据给其他slave节点;这样可以避免同步给master带来的性能影响,但是会延迟同步
  3. 主主复制:双机热备,两个节点都是运行状态,但是只有一个master负责工作,另一个mater是backup;如果要实现高可用,需要通过keepalived来实现主从切换,keepalived不停的发送心跳监测,当发现mater宕机,会把backup做为新的master
  4. 多主一从:用于数据统一,数据汇总,把多个库的表汇总到一个slave节点来进行清洗或汇总处理

环境准备

  • Centos7(准备三个节点)

        192.168.221.128 6379
        192.168.221.129 6379
        192.168.221.130 6379

  •  关闭防火墙(测试可以这样做),或开放指定端口

        systemctl stop firewalld
        firewall-cmd --zone=public --add-port=6379/TCP --permanent

  • 三个节点都安装好redis
  • redis6需要安装gcc5.3以上版本

配置过程

192.168.221.128作为master节点,192.168.221.129和192.168.221.130作为slave节点

在slave节点的redis.conf中配置,配置好之后就会自动完成主从同步

replicaof 192.168.221.128 6379

可以通过info replication命令查看主从配置信息

同步原理

增量:除了第一次其他都是增量同步,支持断点续传(通过offset来保证可靠性)

全量:新加入的节点初始化时一定是全量同步

在redis.conf中可以配置同步策略

# 需要至少3个slave节点连接到master时才会去写入
min-replicas-to-write 3
# master允许slave节点最长失连时间10s,否则认为slave节点断开
min-replicas-max-lag 10

无磁盘复制

主从复制是基于RDB文件,Redis 2.8之后提供了无磁盘复制,不需要将RDB文件先同步到磁盘再去发送,无磁盘复制可以在redis.conf中配置打开

repl-diskless-sync yes

但是如果master节点挂了,怎么处理?

  • 通过外部组件keepalived来实现主从切换
  • 哨兵机制

哨兵机制

如果master节点挂了,需要重新选举master,这时候需要依赖“哨兵机制”,但是哨兵sentinel也可能挂,所以哨兵也可以配置集群,保证高可用;但是sentinel是非中心化节点,没有主从节点之分,所以通过投票来决定redis master节点是否真的挂了;每个哨兵都通过发送心跳包来监听着master的健康状况,一旦多个哨兵都认为master挂了,就会从slave节点中重新选举一个master;客户端访问不再直接访问master,而是先访问哨兵sentinel,哨兵告诉客户端哪个是master,然后客户端再去请求对应的master

连接哨兵地址:192.168.221.128 26379、192.168.221.129 26379、192.168.221.130 26379

哨兵机制配置

redis自带哨兵机制,在redis安装后可以将源码包中的sentinel.conf复制

在sentinel.conf中配置哨兵需要监听的master节点

# mymaster是监听的master节点名称,192.168.211.128 6379是监听的master节点IP和端口号
# 2表示至少2个哨兵投票认为master节点离线,才被认为真的离线,从而选举新的master
sentinel monitor mymaster 192.168.211.128 6379 2

# 如果sentinel发送心跳包,master节点5s没有响应,则认为master节点挂了,默认30s
sentinel down-after-milliseconds mymaster 5000

# 如果master节点15s后仍然没有恢复,则启动failover,从slave中选举一个master
sentinel failover-timeout mymaster 15000

在redis/bin目录下通过./redis-sentinel ../sentinel.conf启动哨兵

可以查看redis/logs/sentinels.log日志文件发现哨兵已经监听了redis节点

master选举

如何决定哪个slave节点作为新的master节点?有以下四种判断方式:

  1. 和哨兵断开连接时长:断开时间越长,就越没有选举权
  2. 优先级排序:在redis.conf中通过属性会对每个redis节点设置优先级,数值越小优先级越高
    replica-priority 100
  3. 复制偏移量越大,数据越完整,那么竞争力就越大
  4. 进程id越小,竞争力越大

Raft数据一致性算法

Raft演示:http://thesecretlivesofdata.com/raft/

作用

  • 集群节点的master选举
  • 集群节点的数据一致性投票

Raft是一个实现分布式一致性的协议。在Redis中,Raft算法协助sentinel选举master节点;Redis哨兵机制去选举master节点,但是redis哨兵集群中sentinel没有主从之分,所以需要通过raft去决定哪个sentinel起决策作用

Raft核心思想 :通过投票决策,少数服从多数

每个节点都有三个状态:Follower、Candidate、Leader。每个节点开始默认都是Follower状态,然后开始选举Leader。

Leader选举

如果一个节点没有收到一个来自Leader的心跳通信,那么自己就变成Candidate状态,并向其他节点发送投票请求;如果这个Candidate收到了来自于大部分节点的投票,那么当前节点就类似于民心所向、众望所归,就成为了真正的Leader,其他Candidate再次变成Follower。但是有可能每个节点都选择自己,那么这个时候如何才能决定最终哪个才是Leader节点呢?所以引入了几个参数按照规则判断:

超时时间:每个节点都有个随机的过期时间,最早发启投票的节点就可能成为Leader。选举timeout时间介于150ms与300ms之间。

轮数Term:如果第一轮没有选出Leader,那么Term++进入下一轮,每次只有所有节点的轮数保持一致,票数才有效;比如Node1和Node2轮数是2,而Node3轮数是1,即使Node3得到了最多票数,这时票数也是无效的,因为其他节点已经进入到下一轮投票了。

心跳检测

当Leader节点选择出来后,其他Candidate节点再次恢复成Follower。Leader节点会持续的向其他节点发送心跳包,如果超过了心跳超时时间,Follower节点没有收到来自Leader节点的心跳包,那么就认为Leader节点故障,当前Follower节点就会变成Candidate状态,再次发起投票进行Leader选举。

数据同步

客户端更新数据到服务器时,需要先经过Leader节点,然后Leader把数据更新操作伴随着下一次心跳发送给Follower节点,当收到过半节点同步成功确认后,才会给客户端更新成功的确认回复。

脑裂

原因:如果集群中有多个节点,因为网络波动或其他网络异常造成网络分区,导致部分节点脱离了集群,产生了一个新的小集群,并选举出一个新的Leader节点。当网络恢复正常后,集群中就会存在两个Leader节点,此时不知道应该以哪个Leader为准,因此形成脑裂现象。

解决脑裂:当客户端请求更新数据时,两个Leader都会收到更新操作,当两个Leader收到的更新的数据不一致时,这个时候会以更大的选举轮数以及数据持久Id来决定以哪个Leader为准,最终以新数据和更大的选举轮数的节点为Leader节点。

其他选举算法:paxos,zab


Redis-Cluster机制(分片)

master-slave这种主从复制模式仅仅实现了数据副本机制,但是没有提供高性能方案;master负责事务操作,slave负责读操作,仅仅只能在读多写少的情况对slave进行水平扩容;当数据量过大,或请求量很多的情况下都会对主从复制模式造成很大的压力。所以Redis 3.0之后提供了这种分片机制,如果一个master节点数据量是8G,那么可以对数据进行分片储存,假设分成4片,每片存储2G。

数据分片

一个Redis-Cluster集群至少由6个节点组成,一个master至少对应一个slave形成主从复制模式,这样可以保证高可用性,一个master节点宕机,可以选择slave节点作为新的master节点;如果一个master节点对应有多个slave节点更好,master节点宕机,从slave节点中选举一个master节点。在redis-cluster集群中不需要哨兵机制来实现选举,已经默认实现了选举。

可以从图中看出有多个master节点,是多主多从,但是不需要考虑master之间的数据同步问题,因为这多个master是数据分片得到的,每个master节点上的数据是不一样的,所以不需要考虑master之间的数据同步问题。

redis-cluster集群中应用了gossip协议,目的是保证每个节点之间都彼此可见,每个节点都知道另一个节点是master还是slave,都知道另一个节点保存的数据区间,一旦有某个节点重新进行master选举或者数据区间发生变化,需要通过gossip协议来散播告知所有节点。

数据分片划分

每个节点都有个数据分片的区间,这个区间是预先分配好的,集群搭建前,每个节点的分片区间已经确定好了。数据槽的容量是16384,每个节点被分配到一个区间,节点之间的数据不存在重复。

当客户端去更新值到集群时,首先通过crc算法对key进行运算,得到一个值,然后再和16384取模,得到具体的一个槽的索引位置,那么就把值存在这个位置。

如果需要增删节点,提供了一个数据迁移的工具,会对数据区间重新划分,并把数据重新调整。

Redis-Cluster配置

在redis目录下创建多个redis.conf配置文件,可以根据端口进行命名(如redis_7000.conf)

修改redis_7000.conf配置文件去配置开启redis-cluster集群

# 开启redis-cluster集群
cluster-enabled yes
# 设置集群的配置文件
cluster-config-file nodes-7000.conf
# 集群节点超时时间,单位ms,心跳检测超时时间
cluster-node-timeout 15000

在任意一个节点上执行下面命令,则会在每一个机器上随机分配一个master节点和一个slave节点,从而创建一个三主三从的集群

./redis-cli --cluster create 192.168.211.128:7000 192.168.211.128:7001 192.168.211.129:7002 192.168.211.129:7003 192.168.211.130:7004 192.168.211.130:7005 --cluster-replicas 1

可以通过cluster nodes命令查看集群中所有节点的信息,并可以看到master节点上的数据槽位slot区间

如果此时在130节点上对另一个节点上的key赋值,那么会报错提示我们应该到另一个节点上:

如果想要把同一个对象的属性set在同一个数据分片上,那么可以使用hashtag,redis-cluster会将相同hashtag的key放在同一个数据分片上。

set user{hashtag-user}address Xi'an
set user{hashtag-user}age 18
set user{hashtag-user}country China
set user{hashtag-user}name Lucifer

Redisson Cluster配置

更多详情可参照:https://github.com/redisson/redisson/wiki/2.-Configuration#24-cluster-mode

方式一:yaml配置,修改redisson.yaml

clusterServersConfig:
    nodeAddresses:
        - "redis://192.168.211.129:7002"
        - "redis://192.168.211.129:7003"
        - "redis://192.168.211.130:7004"

方式二:java code配置

Config config = new Config();
config.useClusterServers()
    .setScanInterval(2000) // cluster state scan interval in milliseconds
    // use "rediss://" for SSL connection
    .addNodeAddress("redis://127.0.0.1:7000", "redis://127.0.0.1:7001")
    .addNodeAddress("redis://127.0.0.1:7002");

RedissonClient redisson = Redisson.create(config);

Gossip协议

采用病毒传播算法,一个节点传给相邻的未传播的节点,然后一个传播一个

特点

  • 是一个周期性的散播协议,周期是1s
  • 会随机选择相邻的节点去散播
  • 一个节点最多散播三个节点
  • 每次散播都会选择尚未接收新消息的节点

消息类型

ping:每个节点会给其他节点频繁的发送ping,包含自己的状态和自己维护的集群数据,让其他节点知道

pong:返回ping的回执,同样返回自己的状态和其他数据信息

fail:某个节点判断另外一个节点故障了,就会发送fail给其他节点,通知这个节点出现故障了

meet:


Codis

Redis3.0之前没有Redis-Cluster,需要依赖Codis进行数据分片。Codis是通过服务端代理机制实现数据分片,Redis客户端发送请求,不再直接请求Redis,而是请求Codis-Proxy,类似于请求Redis Server,codis-proxy实现了redis协议,客户端发送指令给codis-proxy,codis-proxy会将指令转发给redis server。图中的codis-redis-group是redis分组,每一个分组就是redis的一个数据分片。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: Redis持久化机制是指将Redis中的数据保存到磁盘上,以防止数据丢失。Redis有两种持久化机制,分别是RDB持久化和AOF持久化。RDB持久化是在某个时间点对Redis中的数据进行全量备份,生成当前时刻的数据快照。触发RDB持久化可以通过save命令或bgsave命令来手动触发,也可以通过自动化触发来定期执行。save命令会阻塞Redis服务器,期间无法处理其他命令,因此在线上环境中不建议使用。而bgsave命令会通过fork一个子进程来完成RDB的过程,阻塞时间很短。另外,AOF持久化是将Redis执行的每次写命令记录到单独的日志文件中,当Redis重启时,会重新将持久化的日志文件恢复数据。当两种持久化方式同时开启时,Redis会优先选择AOF恢复数据。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* [Redis持久化机制](https://blog.csdn.net/weixin_37672801/article/details/127476772)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【面试常问】Redis持久化机制是什么?各自的优缺点?](https://blog.csdn.net/weixin_42601136/article/details/122759402)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值