上篇说完了 SpringBoot 整合 Redis,这篇讲述 Redis 的其他功能
目录
redis.windows.conf 详解
单位
配置文件中 units:单位,对大小写不敏感,也就是不区分大小写
包含
就好比 spring 中的 import
网络
bind 127.0.0.1 # 绑定的端口
protected-mode yes # 保护模式
port 6379 # 端口
单位
Windows 中,不支持以守护进程的方式运行 Redis
logfile "" # 日志的文件位置名
databases 16 # 数据库的数量,默认是 16
快照
# 900s内,至少1个 key 进行了修改,进行持久化操作
save 900 1
# 300s内,至少10个 key 进行了修改,进行持久化操作
save 300 10
# 60s内,至少10000个 key 进行了修改,进行持久化操作
save 60 10000
stop-writes-on-bgsave-error yes # 持久化如果出错,是否还需要继续工作
rdbcompression yes # 是否压缩 rdb 文件,需要消耗一些cpu资源
rdbchecksum yes # 保存rdb文件的时候,进行错误的检查校验
dir ./ # rdb 文件保存的目录,Windows 中是当前目录
APPEND ONLY 中 aof 的配置
appendonly no # 默认使用rdb方式持久化,不开启aof模式,在大部分所有的情况下,rdb完全够用
appendfilename "appendonly.aof" # 持久化到文件的名字
# appendfsync always # 每次修改都会加锁,消耗性能
appendfsync everysec # 每秒执行一次加锁,丢失可能会丢失最后 1s 的数据
# appendfsync no # 不执行加锁,这个时候操作系统自己同步数据,速度最快
Redis 持久化
Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,一旦服务器进程退出,服务器中的数据库状态也会消失,所以 Redis 提供了持久化功能。
Rdies 中有两种持久化的方式,一种是 RDB,另一种是 AOF,默认使用的是 RDB 进行持久化,想要使用 AOF 需要进行配置,上面讲到了。
RDB

Redis 会按指定的时间间隔,将内存中的数据集写入磁盘,就是刚刚说的快照,如:save 900 1,产生的文件为 dump.rdb。如果数据被破坏,RDB 的恢复规则是:将快照文件直接读到内存。
Redis 会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何 IO 操作的,这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那么 RDB 方式要比 AOF 方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。通常情况下,我们会将dump.rdb进行备份。
RDB 的触发机制:
1、save 规则满足的情况下,会自动触发 RDB 进行持久化
2、执行 flushall 命令,会触发 RDB 进行持久化
3、退出 Redis,会产生 RDB 文件
数据被破坏后,如何使用 RDB 进行恢复:
只需要将 RDB 文件放在 Redis 的安装目录下就可以,Redis 启动的时候会自动检查 dump.rdb 恢复其中的数据
优点:
1、适合大规模的数据恢复
2、对数据的完整性要不高
缺点:
1、需要一定的时间间隔来操作,如果 redis 意外宕机了,最后一次修改的数据就没有了
2、fork 进程的时候,会占用一定的空间
AOF

AOF 是以日志的形式记录每个写操作,读操作不记录,生成 appendonly.aof 文件,Redis 启动时,会读取该文件并重构建数据。也就是说,重启 Redis 时,Redis 会根据日志文件的内容将写指令从前到后执行一次,以完成数据的恢复工作。
当 appendonly.aof 有错时怎么办:
如果 aof 文件有错,这时候 Redis 是启动不起来的,Redis 给我们提供了一个工具:redis-check-aof,我们可以使用这个工具来恢复 aof 文件,输入命令:redis-check-aof --fix,恢复 aof 文件后,就可以正常启动 Redis 了。
aof 文件是默认无限追加的,文件会越来越大,当 aof 文件大于 64M 是,Redis 会 fork 一个新进程来将我们的文件进行重写。
优点:
1、每一次修改都同步持久化,文件的完整会更加好
2、每秒同步一次,丢失可能只丢失一秒的数据
缺点:
1、相对于数据文件大小来说,aof 远大于 rdb,修复的速度也比 rdb 慢
2、aof 运行的效率也要比 rdb 慢,所以 Redis 默认使用 rdb 进行持久化
Redis 发布订阅
Redis 的发布订阅是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的
关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户
端:
订阅端:
127.0.0.1:6379> SUBSCRIBE mychannel
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "mychannel"
3) (integer) 1
1) "message" # 消息
2) "mychannel" # 消息来自于那个频道
3) "hello,world" # 消息内容,可以是一个对象,也可以是一篇文章
发布端:
127.0.0.1:6379> PUBLISH mychannel "hello,world"
(integer) 1
原理:
redis-server 里维护了一个字典,字典的键就是一个个频道,而字典的值则是一个链表,链表中保存了订阅这个 channel 的所有客户端。SUBSCRIBE 命令的关键,就是将客户端添加到特定 channel 的订阅链表中。
用户通过 PUBLISH 命令向订阅者发送消息时,redis-server 会在该用户的频道下,找出记录了这个频道所有客户端的链表,遍历这个链表,将消息发布给所有订阅者。
Redis 主从复制
主从复制是指将一台 Redis 服务器的数据,复制到其他 Redis 服务器。前者称为主节点(master),后者称为从节点(slave)。Master 以写为主,Slave 以读为主。默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
1、根据上面的描述,我们需要三个服务端来完成主从复制。首先将 Redis 文件夹再复制 2 份
2、更改配置文件参数
打开 6380 文件夹,更改 redis.windows.conf 中的参数
将该客户端的端口改为 6380
设置 6379 为主节点
3、创建 redis 服务
在该目录下打开 cmd 黑窗口,输入命令创建 redis6380 服务
redis-server --service-install redis.windows.conf --loglevel verbose --service-name redis6380
4、打开 6381 文件夹中的 redis.windows.conf,进行更改

在 6381 目录下打开 cmd 黑窗口,输入命令创建 redis6381 服务
redis-server --service-install redis.windows.conf --loglevel verbose --service-name redis6381
5、查看创建的 2 个 redis 服务
win + r 打开 服务管理,输入:services.msc ,查看刚刚创建的两个 redis 服务
开启最原始的没有修改过的 redis,发现在 6379 下,有两个子节点,这是我们刚刚配置的
下面使用 Redis 可视化工具测试
首先打开 Redis 6379 这个客户端,再打开可视化工具,创建三个 Redis连接,注意:每个端口号一定要正确。
打开主节点的控制台,设置键值
打开 6380 的控制台,获取键值,发现可以获取到
打开 6381 的控制台,获取键值,也可以获取到
这样我们就实现了一主二从,主节点写,从节点只能读。
查看 6379 服务端的配置,它是一个主节点,有两个子节点
查看 6380 服务端的配置,是一个从节点,它的主节点是 6379
查看 6381 服务端的配置,也是一个从节点,它的主节点是 6379
Redis 哨兵模式
主从切换技术的方法是:当主服务器宕机后,手动把另一台从服务器设为主服务器,这就需要人工操作,费事费力,还会造成一段时间内服务不可用。
哨兵模式:设置哨兵后,后台实时监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
Redis 的 Windows 版本并没有直接提供开启哨兵模式的可执行文件,所以我们手动实现,现在编写哨兵模式来实时监控 6379 这个端口的 Redis 客户端
1、打开 Redis6379 所在的目录,在目录下创建sentinel.conf文件
sentinel monitor myredis 127.0.0.1 6379 1
2、在该目录下继续创建startup_sentinel.bat文件
title sentinel-6379
redis-server.exe sentinel.conf --sentinel
保证一主二从的情况下,先开启 redis6379 客户端
再双击刚刚创建的startup_sentinel.bat文件,发现,哨兵监控了 6379 这个端口,而 redis6379 下还有两个子节点 6380 和 6381
下面我们来测试哨兵模式,打开 redis 可视化工具,先看看一主二从都正常的情况下
接下来,关闭 redis 可视化工具,它会自动断开 redis6379,这是因为:我们只给 redis6380 和 redis6381 配置了服务,他们两个redis 是一直启动的,redis6379 一旦关闭客户端,服务就停止了
接着,我们重新打开 redis 可视化工具,直接查看 redis6380 的端口情况,发现它还是一个从节点
再看看 redis6381 的端口情况,发现它变成了主节点
哨兵记录了自动转换主节点这一过程
我们再次打开 redis6379 的客户端服务
在 redis 可视化工具中,查看 reids6379 的端口情况,发现它变为了从节点
这说明,主节点一点断开,哨兵重选了主节点后(这里面有一个投票算法),原主节点再次连接,也只能作为从节点
哨兵同样记录了这一过程
优点:
1、哨兵集群,基于主从复制模式,所有的主从配置优点它全有
2、主从可以切换,故障可以转移,系统的可用性就会更好
3、哨兵模式就是主从模式的升级,手动到自动,更加健壮
缺点:
1、Redis 不好在线扩容的,集群容量一旦到达上限,在线扩容十分麻烦
2、实现哨兵模式的配置很麻烦,里面有很多选择
Redis 缓存穿透和雪崩
做了缓存后项目查询数据的过程
缓存穿透(查不到)
缓存穿透的概念很简单,用户想要查询一个数据,发现 redis 内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中时,都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
1、解决方案:布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。

2、缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。
缓存击穿(多次查询同一数据)
缓存击穿,是指一个 key 非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问。由于缓存过期,当这个key 在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,会导使数据库瞬间压力过大。
解决方案:
1、设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点 key 过期后产生的问题。
2、加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此需要等待。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩
缓存雪崩,是指在某一个时间段,缓存集中过期失效,Redis 宕机。
解决方案:
1、redis 高可用
这个思想的含义是,既然 redis 有可能崩掉,那多增设几台 redis,这样一台崩掉之后其他的还可以继续工作,其实就是搭建的集群。
2、限流降级
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
3、数据预热
数据预热的含义就是,在正式部署之前,把可能的数据预先访问一遍,这样部分可能被大量访问的数据就会加载到缓存中。在即将发生大并发访问前,手动触发加载缓存不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
Redis 的相关技术到这里就结束了,各位看官,我们下篇再见…(∩_∩)~