【1. Redis概述】
1. Redis是什么?优缺点是什么?
Redis本质上一个key-vlaue类型的内存型数据库,Redis将整个数据库加载在内存当中操作,定期通过异步操作吧数据库中的数据flush到磁盘上进行保存。
优点:
1)读写性能极高,实现系统的高并发操作;
2)支持数据持久化,支持RDB和AOF两种持久化方式;
3)支持事务操作,Redis的所有操作都是原子性的,多个操作通过MULTI和EXEC指令包装起来也支持事务,即原子性;
4)数据结构丰富,支持string hash list set zset 等数据结构;
5)支持主从、哨兵、集群等模式,读写分离,实现系统高可用;
缺点:
1)数据库容量受到物理内存的限制,不能用作海量数据的高性能读写;
2)主机宕机,宕机前可能会有部分数据未能及时同步到从机;
2. Redis为什么这么快?
1)内存存储:Redis是基于内存存储的,没有磁盘IO的开销;
2)单线程实现:使用单线程处理请求,避免了线程切换和锁资源争用的开销;(Redis6.0以前)
3)非阻塞IO:使用多路复用IO技术,使用epoll作为IO多路复用技术的实现;
4)虚拟内存机制:Redis使用自己构建的VM虚拟内存机制,将不经常访问的数据(冷数据)从内存交换到磁盘,可以腾出多余的内存空间存储经常访问的数据(热数据);
5)优化的数据结构:Redis可以直接应用优化的数据结构;
3. 为什么使用Redis作为缓存?
1)从高并发角度而言:直接操作缓存能够承受的请求远远大于直接访问数据库,Redis作为内存数据库,读写性能极高,支持高并发访问;
2)从高性能角度而言:Redis采用内存存储,单线程实现,且非阻塞IO实现数据库操作,读写性能极高;
3)从高可用角度而言:Redis支持主从、哨兵、集群等多种模式,实现读写分离;
4. Redis相比Memcached有哪些优势?
1)数据类型:Redis支持更为丰富的数据类型;
2)性能对比:Redis的速度比Memcached快的多;
3)持久化:Redis支持数据持久化存储,Memcached不支持数据持久化存储;
4)集群模式:Redis提供主从、哨兵、集群等部署方式,而Memcached没有原生的集群模式;
5)网络IO模式:Redis使用单线程的多路复用IO模型,而Memcached支持多线程的非阻塞IO;
5. Redis的常用场景?
1)缓存:Redis提供灵活的键过期删除策略和内存淘汰策略,合理使用缓存可以提高网站访问速度,同时可降低数据库的访问压力;
2)排行榜:京东的销售榜单、微博的热搜榜等;
3)社交网络:社交网站的共同好友、最新回复等;
4)消息系统:Redis提供发布订阅消息队列功能,实现简单的消息队列系统;
6. Redis的数据结构有哪些?
1)string:最常用的一种能够数据类型,应用场景:key-value缓存应用;
2)hash:hash是一个键值对集合,常用于存储对象;
3)list:list是一个有序可重复的集合,底层是双向链表实现的,常用于社交网络的最新回复功能等
4)set:set是一个无序的天然去重的集合,即key-set,常用于求共同好友、共同关注等;
5)sortedset:是set的排序版本,常用于排行榜和带权重的消息队列等场景;
【2. Redis持久化】
1. Redis持久化机制
Redis数据库的数据是存储在内存中的,若需要重用数据,就需要将内存数据写入到磁盘中,即Redis持久化;
Redis提供了两种持久化方式:快照RDB、只追加文件AOF
RDB:在指定的时间间隔内将内存中的数据快照写入磁盘,数据恢复时将快照文件直接读到内存。
优势:适合大规模的数据恢复,对数据完整性和一致性要求不高。
劣势:每隔一段时间进行数据备份,如果Redis数据库在该期间内宕机后,会丢失数据。
AOF:以日志的形式记录每个写操作,只许追加文件但不可以改写文件,Redis启动后加载该日志文件就可重现构建数据。
优势:每修改同步,同步持久化,每次数据发生修改就就保存日志,数据完整性较好但系统性能较差;每秒同步方式,异步持久化,每秒记录,且每秒同步策略效率较好。
劣势:相同数据集的数据,AOF文件远大于RDB文件,且恢复速度比RDB慢。
2. 如何选择合适的持久化方式?
若用做内存数据库,且需要Redis持久化,建议RDB和AOF都开启。
3. Redis 4.0持久化优化
Redis4.0 添加了混合持久化方式,即:新的AOF文件前半段是RDB格式的全量数据,后半段是AOF格式的增量数据。
优势:混合持久化结合了RDB持久化和AOF持久化的优点;
劣势:兼容性差,4.0之前版本无法识别该AOF文件;
【3. 过期键的删除策略 淘汰策略】
1. Redis的过期键删除策略
过期删除策略就是:惰性删除和定期删除两种策略配合使用
定期删除: 每隔一段时间,对key进行检查,删除里面过期的key。
优点:限制定时删除方式频繁检查key是否过期对CPU带来的影响,同时,定期删除key,释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。
惰性删除:给key设置过期时间后,不去管他,而是当需要该key时,再检查是否过期,如果过期,删除它,反之返回该key
优点:对CPU友好,不用浪费时间进行过期检查;
缺点:对内存不友好,不经常使用的key,一直占用内存,该内存无法得到释放;
2. Redis内存淘汰策略
当Redis内存超过最大允许的内存后,会触发内存淘汰策略,删除不常用的数据。
LRU(Least Recently Used)算法:
以双向链表存放被访问的key,每次被访问到的就会放入表头,表尾就是最少被访问的。LRU算法需要一个双向链表来记录数据的最近被访问顺序,但是出于节省内存的考虑,Redis的LRU算法并非完整的实现。
Redis的LRU并不维护队列,它会提供一个待淘汰候选key的pool,里面默认有16个key,按照空闲时间排好序。触发淘汰机制时从Redis键空间随机选择N个key,分别计算它们的空闲时间idle,key的空闲时间大于pool里最小的时,才会进入pool,然后从pool中选择空闲时间最大的key淘汰掉。
LFU(Least Frequently Used)算法:
在LFU算法中,可以为每个key维护一个计数器。每次key被访问的时候,计数器增大。计数器越大,可以约等于访问越频繁。
【4. 缓存异常】
缓存异常有四种类型,分别是缓存与数据库的数据不一致,缓存穿透,缓存击穿,缓存雪崩。
1. 如何保证缓存与数据库双写时的数据一致性?
先删除缓存,后更新数据库
异步串行化:先删除缓存,再去更新数据库,但还没有更新完成时,此时一个读请求过来,读到空的缓存,将缓存更新请求发送到队列中,排在刚才更新库的操作之后,然后同步等待缓存更新完成后,再读缓存数据返回给读请求。
先更新数据库,后删除缓存
在更新完数据库后,使用MySQL数据库的binlog日志对缓存进行删除操作。
2. 缓存穿透
用户请求的数据在缓存中不存在,同时在数据库中也不存在,导致用户每次请求数据都要去数据库查询一遍,若是恶意用户不断请求系统中不存在的数据,就对导致短时间大量的请求落在数据库上,造成数据库压力过大而宕机。
解决方法:
1)将无效的key存放到Redis中,适用于无效key有限的情况;
2)使用布隆过滤器,使用于无效的key随机大量的情况;
3. 缓存击穿
缓存击穿是某个热点的key失效,大并发数据集中对其进行请求,造成大量数据读缓存没读到数据,导致短时间内大量的请求打在数据库上,造成数据库压力过大而宕机。
解决方法:
1)热点数据缓存永不过期;
2)缓存失效后,通过互斥锁控制读数据写缓存的线程数量,降低打在数据库上的请求数量,但此时系统的吞吐量会下降;
4. 缓存雪崩
缓存雪崩是指在某一时刻大规模的key失效,导致大量的请求打在数据集上,造成数据库压力过大而宕机。
解决方法:
事前:
1)均匀过期:设置不同的过期时间;
2)分级缓存:设置多级缓存,每一层缓存的过期时间都不同;
3)热点时间缓存永不失效;
4)使用主从、哨兵、集群等方式,保证Redis数据库的高可用;
事中:
1)互斥锁:缓存失效后,通过互斥锁控制读数据写缓存的线程数量,降低打在数据库上的请求数量,但此时系统的吞吐量会下降;
2)使用熔断机制,限流降级;
事后:
开启Redis持久化机制,在系统重启后,尽快恢复缓存数据;