Redis篇
一、缓存穿透
发生场景:查询一个不存在的数据,mysql中查询不到数据也不会写入缓存,导致每次都会直接查询数据库
解决方案一:把查到的数据仍然放入redis,value为null。优点:很简单,缺点:消耗内存。
解决方案二:增加布隆过滤器。优点:内存占用少,没有多余key,缺点:实现复杂,存在误判。
二、缓存击穿
发生场景:给某一个key设置了过期时间,当key过期时,恰好这个时间点对这个key有大量的并发请求过来,这些并发的请求可能把数据库压垮
解决方案一:互斥锁 。优点:强一致,缺点:性能差,适用于金额场景
解决方案二:逻辑过期 。优点:高可用,性能好,缺点:不是强一致
三、缓存雪崩
发生场景:缓存雪崩是指在同一时间段大量的key同时失效或者redis宕机,导致大量请求到达数据库。
解决方案一:给不同的key是指不同的过期时间
解决方案二:使用集群提高可用性
解决方案三:给缓存业务添加降级限流策略(穿透,击穿,雪崩都可以使用)
解决方案四:给业务添加多级缓存
四:双写一致性
发生场景:如何保证数据库和缓存数据一致0
保证强一致性:用到redisson提供的读写锁或者使用延时双删
不需要保证强一致性:使用异步操作,使用mq进行通知操作或者使用canal,通过读取binlog日志进行一致性操作
五:Redis持久化
RDB
全称Redis Database Backup file ,也叫Redis数据快照,把数据库中所有数据都记录到磁盘中,当Redis故障重启后,从磁盘读取文件,恢复数据
RDB两个操作:save和bgsave
save:由Redis主进程来执行RDB,会阻塞所有命令
bgsave:开启子进程执行RDB,避免主进程受到影响
RDB操作在Redis的redis.conf中也有,例如:save 900 1 save 300 10 在多少秒内有多少个key被更改就会执行RDB操作
RDB执行原理:首先任何进程都不可以直接操作物理内存,主进程有一个页表,记录了虚拟地址和物理地址的映射关系,在进行RDB操作时,主进程会复制一个紫禁城,页表也会复制过去,子进程会读取到内存数据,写入磁盘中。
注意:在RDB过程中,主进程修改数据会产生一些问题,解决方案:fork采用的是copy-on-write技术,主进程只是读的操作,就会访问共享内存,当主进程执行写的操作时,会拷贝一份数据,执行写的操作
AOF
全称Append Only File,Redis处理的每一个写命令都会记录在AOF文件中,需要配置开启。
可以通过执行bgrewriteaof命令,用最少的命令达到相同效果
六、Redis过期策略
惰性删除
设置key过期时间后,不去管他,当需要该key时,再检查是否过期,如果过期,就进行删除,反之则返回该key。
优点:对CPU友好,只有使用该key时才会进行过期检查,对于很多用不到的key不会浪费时间进行检查
缺点:对内存不友好,一直未使用,key就会一直存在内存中。
定期删除
每隔一段时间,对一些key进行检查,删除里面过期的key,有两种模式,分别是SLOW和FAST模式,Redis的过期删除策略是两种配合使用。
优点:可以通过限制删除操作执行的市场和频率来减少删除操作对cpu的影响,定期删除可以有效释放过期占用的内存。
缺点:难以确定删除操作执行的时长和频率。
七、数据淘汰策略
当redis中的内存不够用时,此时向redis中添加新的key,那么redis就会按照某一种规则将内存中的数据删除,这种数据的删除规则被称之为内存的淘汰策略。
有8种淘汰策略,默认是noeviction,不淘汰任何key,但是内存满了不允许写入新的数据
重点:LRU,最近最少使用,用当前时间减去最后一次访问时间,值越大有限淘汰。
LFU,最少频率使用,统计每个key的访问频率,值越小优先级越高。
八、redis分布式锁
Redis实现分布式锁主要利用Redis的setnx命令。
九、Redis集群
1.主从复制
单节点Redis的并发能力是有上限的,要提高并发能力,需要搭建集群,主节点负责写数据,从节点负责读数据。
主从同步流程:
全量同步:从节点请求主节点同步数据,主节点判断是否是第一次请求,第一次请求就和从节点同步版本信息,主节点执行bgsave,生成RDB文件后,交给从节点执行,在执行RDB期间,主节点的操作会以命令的方式记录到缓冲区,最后把生成的命令日志文件发给从节点进行同步。
增量同步:从节点请求主节点同步数据,主节点判断不是第一次请求,获取从节点上的offset值,主节点从命令日志中获取offset值之后的数据,发给从节点进行数据同步。
2.哨兵集群
Redis提供了哨兵机制来实现主从集群的自动故障恢复。哨兵的结构和作用如下
监控:哨兵会不断检查主节点和从节点是否按预期工作。
自动故障恢复:如果主节点故障,哨兵会选择一个从节点当主节点,当故障实例恢复后也以新的主节点为主
通知:哨兵充当Redis客户端的服务发现来源,当集群发生故障时,会将消息发给Redis客户端。
Redis集群脑裂问题
集群脑裂时由于主节点和从节点的哨兵处于不同的网络分区,导致哨兵没有能够心跳感知到主节点,所以推选新的从节点为主节点,这样就会存在两个主节点,就像大脑分裂一样,这样客户端还在老的主节点那里写入数据,新节点无法同步数据,当网络恢复后,哨兵会将老的主节点降为从节点,这样再从新的主节点同步数据,就会导致数据丢失。
解决:设置最少的从节点数量或者缩短主从同步的延迟时间,可以避免大量数据丢失。
3.分片集群
分片集群解决的问题:高并发下的写问题,海量数据存储问题
如何实现:集群中有多个主节点,每个主节点保存不同的数据,每个主节点都可以有多个不同的从节点,主节点之间互相检测健康状态
如何实现存储和读取:引入了哈希槽的概念,集群有16384个哈希槽,将哈希槽分配到不同的实例,根据key的有效部分计算哈希值,对16384取余,最终确定存储。
有些地方写的不够详细,可以说出来不理解的地方改正。