1 Redis单线程为什么这么快?
- 纯内存操作
- 基于非阻塞的IO多路复用机制
- 单线程避免多线程频繁上下文切换带来的性能问题
2 Redis持久化机制?
2.1 RDB
Redis DataBase将某个时刻的内存快照,以二进制的方式写入磁盘。
手动触发
- save命令,使redis处于阻塞状态,知道RDB持久化完成,才会响应客户端发出的命令。
- bgsave命令,fork出一个子进程进行RDB持久化操作。主线程可以正常向颖客户端的请求。
自动触发
- save m n:在m秒内,如果有n个键发生变化,自动通过bgsave触发持久化。
- flushall:清除redis所有的数据,并生成一个dump.rdb
- 主从同步:全量同步时会自动触发bgsave命令,生成RDB文件发送到从节点。
优点
- 只有一个RDB文件,方便持久化
- 容灾性好,方便备份
- 性能最大化
- 数据集大,备份效率快
缺点
- 数据安全性低,因为RDB是隔时间持久化,如果在节点之间宕机了,导致部分数据丢失。
- RDB通过fork子进程持久化,数据集大时,会导致整个服务宕机几百毫秒,会占用cpu
2.2 AOF
Append Of File以日志的形式记录服务器每一个增删改操作,查询不记录。
2.2.1 所有的写命令都会追加到AOF缓冲区。
2.2.2 AOF缓冲区根据对应的策略向硬盘进行同步操作
2.2.3 AOF越来越大,需要定时对AOF进行重写,达到压缩的目的。
2.2.4 当Redis重启时,可以加载AOF进行数据恢复。
优点
- 数据安全
- 通过append模式写文件,即使中途宕机也不会破坏已存在的内容。
- AOF机制的rewrite模式,定期对AOF文件进行重写,达到压缩的目的。
缺点
- AOF文件大
- 数据集大,启动效率慢
- 运行效率低。
区别
- AOF更新频率高,优先使用AOF更新
- AOF更安全更大
- RDB效率高
- 优先加载AOF
3 布隆过滤器
位图:初始化,每一个bit都是0
添加数据:计算数据的hash值,转换成对应的bit位,并把0改成1
查询数据:计算数据的hash值,对应的bit中,如果存在一个0,证明数据不存在bit中,如果都为1,则可能在bit中
优点:
- 占用内存小
- 增加和查询元素的时间复杂度为0(K)
- 哈希函数相互之间没有关系
- 布隆过滤器不需要存储元素本身,具备保密性
- 数据量很大时,布隆过滤器可以显示全集
- 使用同一组散列函数的布隆过滤器进行交,并,差运算
缺点:
- 误判率,不能准确判断元素是否在集合中
- 不能获取元素本身
- 一般情况下不能从布隆过滤器删除元素
4 缓存过期都有哪些策略
- 定时删除:定时清除过期的数据。清除大量的数据会占用CPU资源,降低响应速度和吞吐量。
- 惰性删除:当访问一个key时,才判断对应的数据是否过期,过期则删掉。占用大量内存。
- 定期随机删除:。定时清除一部分过期数据(随机)。使CPU和内存资源在较好的情况。
5 缓存雪崩,缓存穿透,缓存击穿
- 缓存雪崩:同一时间缓存大面积失效,大量请求到数据库端,导致宕机。(强调的是同一时间大量缓存失效)
解决方案:
- 缓存数据过期时间设置随机,防止同一时间失效。
- 监控缓存数据是否失效,如果失效,即使更新。
- 缓存预热。提前把缓存数据加载好。
- 互斥锁。缓存排队。
多级缓存,缓存互斥,合理设置缓存过期时间,缓存预热,限流控制
- 缓存穿透:缓存和数据库都没有数据,短时间内,数据库承受大量请求而崩掉。
解决方案:
- 接口层增加校验
- 缓存和数据库没有数据,缓存key-value设置key-null,有效时间设置短点,30秒。
- 采用布隆过滤器,将所有可能存在的数据哈希到bitmap中,一定不存在的数据会被拦截掉,避免对底层存储系统的查询压力。
布隆过滤器,缓存null对象
- 缓存击穿:缓存中没有数据,数据库有数据。跟缓存雪崩不同,缓存雪崩是很多数据失效,缓存击穿是一个数据失效。
- 设置热点数据永不过期
- 加互斥锁,缓存排队,CAS,自旋锁。
热点数据永不过期,
缓存穿透、缓存雪崩和缓存击穿都是与缓存相关的问题,但它们之间有一些不同点。
缓存穿透
缓存穿透是指恶意用户发送请求到系统,这些请求所请求的数据在缓存中不存在,也不存在于后端数据库中,导致大量无效查询打到后端数据库上,从而引起数据库性能下降。缓存穿透通常可以通过使用布隆过滤器等技术来解决。
缓存击穿
缓存击穿是指一个存在于缓存中的key突然失效或被删除,并且在此期间恰好有大量的请求访问该key对应的数据,此时这些请求会直接访问后端数据库,而造成数据库短时间内承受巨大压力。缓存击穿通常可以通过使用互斥锁、缓存预热等技术来解决。
缓存雪崩
缓存雪崩是指当缓存系统中的某些key在同一个时间段过期失效,而这些key所对应的数据在同一时间又全部被请求,此时会发生大量的缓存命中失败,从而导致请求全部转发至后端数据库,最终产生连锁反应,导致数据库也崩溃的现象。缓存雪崩通常可以通过使用缓存预热、多级缓存等技术来解决。
综上所述,缓存穿透、缓存击穿和缓存雪崩都是与缓存相关的问题,但是它们所针对的对象不同,解决方案也不同。缓存穿透需要使用布隆过滤器等技术进行防护,缓存击穿通常可以使用互斥锁、缓存预热等技术进行解决,缓存雪崩则需要采用多级缓存、缓存预热等策略来保证缓存的高可用性。
#####6 Redis分布式锁
1. setnx保证如果key不存在,才获取锁,如果key存在,则获取不到锁。
2. lua脚本保证多个redis操作的原子性
3. 锁过期,定时任务判断锁是否需要续约
4. redis节点挂掉的情况,需采用红锁的方式向N/2+1节点申请锁,都申请了才能证明获取锁成功,这样就算redis挂了,锁也不能被其他客户端获取。
#####7 Redis9大结构
1. String 字符串
2. List 列表
3. Hash 哈希表
4. Set 无序集合
5. SortedSet 有序集合
6. BitMap 布隆过滤器
7. GeoHash 坐标
8. HyperLogLog
9. Streams
#####8 Redis集群方案
3种策略:
- 主从模式:
主库宕机,需手动修改ip,较难扩容,整个集群存储数据量收到某一台机器的内存容量的影响。
- 哨兵模式:
主库节点宕机,会在从库中选择一个作为主库。哨兵也可以是集群。不能很好扩容
- cluster模式:
常用,支持多主多从,根据key进行槽位的分配,可以使得不同的key分散到不同的节点上,可以使整个集群环境支持更大的数据容量。每一个主节点有自己的从节点。
数据量小-哨兵模式,数据量大,需支持扩容-cluster模式
1. 哨兵模式+主从模式
解决高可用问题,无法解决数据量大。
- 集群监控:负责监控各个节点是否正常。
- 消息通知:如果某一个redis实例故障,那么哨兵负责发预警消息给管理员。
- 故障转移: 如果master节点宕机,会自动转移到slave节点。
- 配置中心:如果故障转移发生了,通知客户端新的master节点。
2. Redis Cluster:是一种服务端sharing技术,采用slot槽的概念,一共分成16384个。将请求发送到任意节点,接受到请求的节点会将查询请求发送到正确的节点上执行。
实现原理:
- 通过哈希将数据分片,每一个节点根据内存配置一定的哈希槽区间的数据。
- 每一个数据分片,都会存储到互为主从的多节点上。
- 数据先写入主节点,再同步到从节点。
- 同一分片多节点间数据不包吃一致性。
- 读取数据时,当前客户端操作的key没有分配到该节点,会返回指令,自从正确的节点查询数据。
- 扩容时需要把旧节点的数据迁移一部分到新节点上。
#####9 Redis如何保持消息的一致性?
1. 先更新MySQL,再更新Redis。如果Redis更新失败,可能仍然不一致。
2. 先删除Redis缓存数据,再更新MySQL。可能在删除数据后,再查询数据库,把旧数据更新到缓存里。
3. 延时双删,删完缓存,MySQL数据后,过几百毫秒,再删除缓存数据。
#####10 简述Redis事务实现
1. 事务开始
Multi命令的执行,标志着一个事务的开始。Multi命令将客户端状态的flags属性中打开Redis_multi标识来完成。
2. 命令入队
当一个客户端切换到事务状态后,服务器会根据这个客户端发送过来的命令执行不同的操作。
2.1 如果客户端发送的命令使exec,discard,watch,multi其中之一,那么服务器会立即执行命令
2.2 否则,把正确的命令放进事务队列中(FIFO),向客户端返回queued回复。
3. 事务执行
客户端发送EXEC命令,执行队列中的命令。
#####11 Redis主从复制的底层实现方式?
1. 全量复制
1.1 bgsave命令fork子进程进行RDB持久化,该过程非常消耗CPU,内存(页表复制),硬盘IO
1.2 RDB文件通过网络传输,消耗带宽。
1.3 从节点需要先清除老数据,再重新载入RDB文件,该过程是阻塞的,无法响应客户端的命令。
2. 部分复制
2.1 复制偏移量
2.2 复制积压缓冲区,若主从节点的偏移量>缓冲区长度,将无法执行部分复制,只能全量复制
2.3 服务器运行id:
从节点断开重连,根据运行id判断同步的进度。若判断主id不同,则主节点也换了,需要全量复制。
#####12 什么是Redis?它的特点是什么?
redis是一种高性能的基于内存的键值存储数据库。
有以下特点:
1. 非常快速:基于内存读写
2. 持久化:数据持久化到磁盘,不会丢失。
3. 多种数据结构
4. 发布订阅
5. 高可用:主从复制
6. 轻量级数据库
#####13 Redis的应用场景有哪些?
1. 缓存:把数据缓存在内存中,提高查询效率,降低数据库压力
2. 分布式锁:redis支持原子操作,分布式锁,避免多个服务同时操作同一个资源。
3. 计算器:redis的incr命令实现计数器。统计文章阅读数,网站访问量。
4. 消息队列:订阅发布模式
5. 实时排名:有序的集合
6. 用户列表:无序的集合
#####14 Redis如何保证数据的持久化?默认使用哪种?
快照:RDB
日志:AOF
默认RDB。因为快照简单,易于理解,保证较高的性能和可靠性。适用于大部分场景。
在要求数据准确性和可靠性更高的场景下,用AOF
#####15 Redis支持哪些数据淘汰策略?
1. no eviction 不回收,添加新数据报错
2. allkeys-lru:回收最少使用的
3. volatile-lru:在设置了过期时间的空间中,回收最少使用的值
4. volatile-ttl:在设置了过期时间的空间中,回收最快过期的值
#####16 Redis的主从复制是什么?如何配置主从复制?
redis的主从复制是一种高可用性的解决方案,将一个redis服务器配置成主服务器,而将其他redis服务器配置成从服务器。数据从主拷贝到从,实现数据的冗余备份和读写分离。在主从复制的模式下,主负责所有的写操作以及部分读操作,而从只负责读操作。当主宕机,从服务器会自动选举一个成为主服务器,以保证高可用。
通过给主从服务的配置文件设置主服务的id+端口实现。
- 注意:
主从复制,只有一个主服务处理所有的写操作,可能出现单点故障 的情况,以及出现数据同步延迟的问题。
#####17 Redis的并发竞争问题如何解决?
1.原子性操作,INCRBY,DECRBY
2.乐观锁,更新数据后比较版本号,时间戳等字段。
3.分布式锁,
4.事务,多个命令放到一个队列中执行,不会被其他并发操作打断。
5.pipeLine,将客户端多个命令打包成单个请求,并发送到服务器。
#####18 Redis如何实现分布式锁?
SETNX lock_key myrandom_value 获取锁。
DEL lock_key 释放锁
- 如何防止锁过期时间过短?设置锁时,指定过期时间。
- 如何保证锁定的可靠性和安全性?使用Redis的事务特性保证锁的不会被意外的过期或释放。
- 如何表面锁竞争导致的死锁和性能问题?Redis的lua脚本执行多个命令。
#####19 Redis和Memcached的区别是什么?
1.数据类型支持:redis支持多种,字符串,哈希表,链表,集合,有序集合等,memcached只支持简单的键值对。
2.存储方式:redis持久化到磁盘,即使服务重启也不会丢失数据。而memcached只能将数据存储到内存中,并不能保证数据的持久性。
3.性能表现:读取大量数据,redis性能比memcached好
4.扩展性:redis支持主从复制,哨兵模式等高可用性,以及cluster集群模式方便扩展和可用性。而memcached扩展性差。
5.应用场景:支持更为复杂的数据结构和算法。如排行榜,阅读量,实时消息传递等。而memcached只使用简单的读写缓存场景。
#####20 Redis的主要优点是什么?
1.高性能,读写很快
2.可扩展性,主从复制,哨兵模式,cluster集群模式
3.多种数据结构
4.持久化,RDB,AOF
5.多语言支持,java,python,php,C#
6.发布/订阅
#####21 Redis有哪些常见的性能问题?
1.内存消耗高。解决方案:LRU自动清除过期或者不常用的数据。redis集群模式进行水平扩展。
2.阻塞操作。redis单线程,阻塞可能导致其他请求被阻塞。导致系统吞吐量下降。
3.慢查询。如果查询非常慢,会导致性能下降。(优化避免慢查询)
4.数据结构不当。推荐:频繁更新-哈希表,排序和范围查询-有序集合。
5.过期设置不当。大量数据同时过期,可能导致雪崩。
#####22 Redis如何实现发布/订阅模式?
1.客户端通过subscribe命令向服务器发送订阅请求,服务器将该请求保存到对应的频道或模式的订阅列表。
2.当其他客户端向已订阅发布消息时,服务器会将消息推送给所有订阅该频道或模式的客户端。
3.服务器收到publish命令时,遍历该频道的订阅列表,将消息发送给所有已经订阅该频道的客户端。
4.处理订阅和发布消息时,redis使用内部数据结构pubsub_channels和pubsub_patterns。
pubsub_channels是以一个字典类型的数据结构,用于保存所有的频道及其对应的订阅客户端。
pubsub_patterns是一个链表类型的数据结构,用于保存所有的模式及其对应的订阅客户端。
5.redis还是用了c语言中时间驱动机制(epoll)
#####23 Redis如何实现持久化的优化?
1.RDB优化
增量备份,命令lastsave获取最后一次成功执行bgsave的时间戳,并在此基础上做差异备份。
2.AOF优化
- 避免aof文件过大,压缩。
- 设置适当的同步频率,保证数据的安全性和尽少减少数据丢失
3.内存优化
- 高效的数据结构
- 通过info memory查看内存使用情况,对高占比内存进行优化。
4.网络优化
提高网络传输的稳定性和效率。
#####24 20道经典面试题?
https://blog.csdn.net/github_36665118/article/details/128845139