Redis
使用场景
- 缓存
- 穿透,击穿,雪崩
- 双写一致,持久化
- 数据过期,淘汰策略
- 分布式锁
- setnx,redisson
- 计数器
- 保存token:String类型
- 消息队列
- 延迟队列:
- 集群
- 事务
- Redis为啥这么快
常见面试题
缓存-缓存穿透
原因是有人恶意伪造id来获取文章信息。
解决方案:
缓存空数据,查询返回的数据为空,仍把这个空数据进行缓存
优点:简单
缺点:消耗内存,可能存在数据不一致的问题
使用布隆过滤器
优点:内存占用较少,没有多余的key
缺点:实现复杂,存在误判
缓存预热时,预测布隆过滤器
布隆过滤器知识
存在的问题-有缺失率,如下图所示
误判率:数组越小误判率就越大,数组越大误判率就越小,但是同时带来更多的内存消耗。
布隆过滤器实现方案:Redisson,Guava
缓存-击穿
缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮
解决方案
互斥锁:强一致,性能差
逻辑过期:高可用,性能优,不能保证数据绝对一致
缓存雪崩
缓存雪崩是指在同一时间段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。
解决方案:
- 给不同的key的TTL添加随机值
- 利用redis集群提高服务的可用性,哨兵模式,集群模式
- 给缓存业务添加降级限流策略,ngnix
- 给业务添加多级缓存,Guava或者Caffaie
《缓存三兄弟》
- 穿透无中生有key,布隆过滤null隔离。
- 缓存击穿过期key,锁与非期解难题。
- 雪崩大量过期key,过期时间要随机。
- 面试必考三兄弟,可用限流来保底。
双写一致性
前提需求:一致性要求,允许延迟一致性
双写一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致
不管是先删除缓存,还是先修改数据库,都会出现问题。
解决方案:
上面的方案,依旧不高。
阿里给的双写一致性方案
面试题
持久化
在Redis中提供了两种数据持久化的方式:1.RDB
2.AOF
RDB全称Redis Database Backup file (Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。
bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB 文件。
AOF
AOF全称为Append Only File (追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。
AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF
因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。
数据过期策略
加入redis的key过期后,会立即删除吗?
Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除掉。可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略)。
Redis数据删除策略-惰性删除
惰性删除:设置该key过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key
优点∶对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查 缺点∶对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存中,内存永远不会释放
Redis数据删除策略-定期删除
定期删除:
每隔一段时间,我们就对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)。
定期清理有两种模式:
- SLOW模式是定时任务,执行频率默认为10hz,每次不超过25ms,以通过修改配置文件redis.conf的hz选项来调整这个次数
- FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms
优点:可以通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响。另外定期删除,也能有效释放过期键占用的内存。 缺点:难以确定删除操作执行的时长和频率。
数据淘汰策略
缓存过多,内存是有限的,内存被占满的怎么办?
数据的淘汰策略:当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。
面试问题
分布式锁
Redis实现分布式锁主要利用Redis的setnx命令。setnxs set if not exists
实现分布式锁-流程
redisson实现的分布式锁-主从一致性吗?
缺点:实现复杂,性能差,运维繁琐。
面试问题
主从复用
Redis集群有哪些方案,知道吗?
- 主从复制
- 哨兵模式
- 分片集群
主从复制的整体架构
单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。
主从数据同步原理
- 主从全量同步
- 主从增量同步
Replication ld
:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的rep)lid,slave则会继承master节点的replidoffset
:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset.如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。
- 从节点请求主节点同步数据(replication id、 offset )
- 主节点判断是否是第一次请求,是第一次就与从节点同步版本信息(replication id和offset)
- 主节点执行bgsave,生成rdb文件后,发送给从节点去执行
- 在rdb生成执行期间,主节点会以命令的方式记录到缓冲区(一个日志文件)
- 把生成之后的命令日志文件发送给从节点进行同步
- 从节点请求主节点同步数据,主节点判断不是第一次请求,不是第一次就获取从节点的offset值
- 主节点从命令日志中获取offset值之后的数据,发送给从节点进行数据同步
哨兵模式
服务状态监控
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
- 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线
- 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quoru m值最好超过Sentinel实例数量的一半。
哨兵选主规则
- 首先判断主与从节点断开时间长短,如超过指定值就排该从节点
- 然后判断从节点的slave-priority值,越小优先级越高
- 如果slave-prority一样,则判断slave节点的offset值,越大优先级越高。
- 最后是判断slave节点的运行id大小,越小优先级越高。
分片集群
主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:。
- 海量数据存储问题
- 高并发写的问题
使用分片集群可以解决上述问题,分片集群特征
:·
- 集群中有多个master,每个master保存不同数据
- 每个master都可以有多个slave节点
- master之间通过ping监测彼此健康状态
- 客户端请求可以访问集群任意节点,最终都会被转发到正确节点
分片集群结构-数据读写
Redis分片集群引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
面试问题