持久化
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主从工作原理
- 为master配置slave时会发送一个SYNC命令(redis2.8版本之前的命令)给master请求复制数据。
- master收到SYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。
- 当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。
- 当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
中提供了几个常用的接口方法的使用,分别是:
- private ValueOperations<K, V> valueOps;
- private HashOperations<K, V> hashOps;
- private ListOperations<K, V> listOps;
- private SetOperations<K, V> setOps;
- private ZSetOperations<K, V> zSetOps;
RedisTemplate
中定义了对5种数据结构操作
- redisTemplate.opsForValue();//操作字符串
- redisTemplate.opsForHash();//操作hash
- redisTemplate.opsForList();//操作list
- redisTemplate.opsForSet();//操作set
- redisTemplate.opsForZSet();//操作有序set
StringRedisTemplate继承自RedisTemplate,也一样拥有上面这些操作。
StringRedisTemplate
默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
RedisTemplate
默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。