持久化

RDB

在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。

可通过修改redis.conf中的配置dbfilename dump.rdb去修改快照保存文件名。

可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。

save 60 1000

还可以手动执行命令生成RDB快照,进入redis客户端执行命令save或bgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。
save是同步命令,bgsave是异步命令,bgsave会从redis主进程fork(fork()是linux函数)出一个子进程专门用来生成rdb快照文件。
配置自动生成rdb文件后台使用的是bgsave方式。

AOF

将修改的每一条指令记录进文件appendonly.aof中。

开启AOF模式:

appendonly yes

# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"

可以配置 Redis 多久才将数据 fsync 到磁盘一次,有三种可配置的策略。

  • appendfsync always:每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非
    常安全。
  • appendfsync everysec:每秒 fsync 一次,足够快(和使用 RDB 持久化差不多),并且在
    故障时只会丢失 1 秒钟的数据。默认策略为everysec,可以兼顾速度和安全性。
  • appendfsync no:从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择。
AOF重写优化

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件

127.0.0.1:6379> incr readcount
(integer) 1
127.0.0.1:6379> incr readcount
(integer) 2
127.0.0.1:6379> incr readcount
(integer) 3
127.0.0.1:6379> incr readcount
(integer) 4
127.0.0.1:6379> incr readcount
(integer) 5

如上述命令,在AOF重写时,只会将最后一条指令写入到AOF文件中。

配置AOF自动重写频率
# auto-aof-rewrite-min-size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本
来就很快,重写的意义不大
# auto-aof-rewrite-percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重
写

进入redis客户端执行命令bgrewriteaof可手动执行AOF重写。

混合模式

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。
通过如下配置可以开启混合持久化:

# aof-use-rdb-preamble yes

redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一点。

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,原子的覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重启效率大幅得到提升。

主从架构

Redis主从工作原理

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

master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标offset开始。
如果master进程id变化了,或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。
从2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据

哨兵架构

sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。

哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点(由sentinel选举而出,并修改相应的配置文件:哨兵配置文件以及主从节点配置文件)通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)

Spring Boot整合Redis

spring 封装了 RedisTemplate 对象来进行对redis的各种操作,它支持所有的 redis 原生的 api。

RedisTemplate中提供了几个常用的接口方法的使用,分别是:

  1. private ValueOperations<K, V> valueOps;
  2. private HashOperations<K, V> hashOps;
  3. private ListOperations<K, V> listOps;
  4. private SetOperations<K, V> setOps;
  5. private ZSetOperations<K, V> zSetOps;

RedisTemplate中定义了对5种数据结构操作

  1. redisTemplate.opsForValue();//操作字符串
  2. redisTemplate.opsForHash();//操作hash
  3. redisTemplate.opsForList();//操作list
  4. redisTemplate.opsForSet();//操作set
  5. redisTemplate.opsForZSet();//操作有序set

StringRedisTemplate继承自RedisTemplate,也一样拥有上面这些操作。

StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。