Redis八股文

1.Redis是什么?

Redis 是一个基于 C 语言开发的开源数据库(BSD 许可),与传统数据库不同的是 Redis 的数据是存在内存中的(内存数据库),读写速度非常快,被广泛应用于缓存方向。并且,Redis 存储的是 KV 键值对数据。

2.Redis的优缺点

Redis是一个开源的、内存存储、支持键值对、具有持久性的数据结构存储系统,具有以下优缺点:
优点:

  1. 高性能:Redis将数据全部存储在内存中,并使用单线程模型,这使得Redis的读写速度非常快。
  2. 丰富的数据结构:Redis支持多种数据结构,包括字符串、列表、哈希表、集合和有序集合等,这些数据结构可以满足不同应用场景的需求。
  3. 数据持久化:Redis支持将数据持久化到磁盘中,包括快照和日志文件两种方式,这使得Redis可以在系统宕机后快速恢复数据。
  4. 支持分布式:Redis支持分布式架构,可以将数据分散到多个节点中,提高系统的可扩展性和容错性。
  5. 简单易用:Redis提供了简单易用的命令行接口,同时也支持多种编程语言的客户端,使用起来非常方便。

缺点:

  1. 数据存储受限:由于Redis将所有数据存储在内存中,所以受到内存容量的限制,如果数据量很大,需要更多的内存。
  2. 单线程模型:虽然Redis使用单线程模型来保证读写性能,但是在高并发情况下,单线程模型也可能成为瓶颈。
  3. 不适合存储大文件:由于Redis是将所有数据存储在内存中,因此不适合存储大文件等大型二进制数据。
  4. 数据一致性:Redis支持数据持久化,但是在高并发的情况下,可能会存在数据一致性问题,需要进行额外的配置和处理。
  5. 配置复杂:Redis提供了多种配置选项,需要根据不同的使用场景进行不同的配置,这可能会增加系统配置的复杂度。

3.Redis为什么这么快

  1. 基于内存:Redis 将数据全部存储在内存中,而内存的访问速度是磁盘的上千倍,这使得 Redis 能够快速地读取和写入数据。
  2. 高效的事件处理模型:Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用,这使得 Redis 能够高效地处理大量的并发请求。
  3. 优化过的数据结构实现:Redis 内置了多种优化过后的数据结构实现,如哈希表、有序集合等,这些数据结构能够高效地处理常见的数据操作,如插入、删除、查找等。
  4. 异步非阻塞的网络模型:Redis 使用异步非阻塞的网络模型,这使得 Redis 能够高效地处理大量的并发请求,而不会因为等待 I/O 操作而阻塞线程,从而提高了系统的吞吐量。
  5. 数据持久化:Redis 支持将数据持久化到磁盘中,包括快照和日志文件两种方式,这使得 Redis 可以在系统宕机后快速恢复数据,从而提高了系统的可靠性。

4.Redis为何选择单线程

Redis 选择单线程模型的主要原因是为了避免线程切换带来的开销和竞争条件带来的复杂性,从而提高系统的性能和可靠性。具体来说,单线程模型带来以下几个优点:

  1. 避免线程切换带来的开销:线程切换会带来一定的开销,包括上下文切换和内存开销等,而单线程模型能够避免这些开销,从而提高系统的性能。
  2. 避免竞争条件带来的复杂性:在多线程模型下,多个线程之间会存在竞争条件,需要使用锁等机制来避免竞争条件带来的复杂性,而单线程模型能够避免这些复杂性,从而提高系统的可靠性。
  3. 更容易实现:单线程模型相对于多线程模型更容易实现和维护,因为它不需要考虑线程间的同步和通信等问题。
  4. 更容易进行优化:由于单线程模型不会存在多线程间的竞争条件,因此可以更容易地进行优化,如利用 CPU 缓存等。

需要注意的是,Redis 的单线程模型并不代表它只能处理一个请求,实际上 Redis 通过事件处理模型和异步非阻塞的网络模型,能够同时处理大量的并发请求,从而实现高吞吐量和低延迟。

5.Redis应用场景有哪些

Redis 作为一种高性能、可靠性高的内存数据库,在许多应用场景中得到了广泛的应用。以下是 Redis 的一些常见应用场景:

  1. 缓存:Redis 作为一种高速缓存数据库,可以将热点数据缓存在内存中,从而提高系统的读写性能。
  2. 消息队列:Redis 的发布/订阅模式和 List 数据结构可以实现轻量级的消息队列,从而支持异步消息通信。
  3. 计数器和排行榜:Redis 的原子性操作和 Sorted Set 数据结构可以实现高效的计数器和排行榜功能。
  4. 分布式锁:Redis 的原子性操作和过期时间可以实现高效的分布式锁功能,从而保证多个进程或线程之间的数据访问互斥。
  5. 会话存储:Redis 可以作为会话存储数据库,将用户的会话信息存储在内存中,从而支持高并发的 Web 应用程序。
  6. 地理位置和空间索引:Redis 的 Geo 数据结构可以实现高效的地理位置和空间索引功能,从而支持 LBS 应用程序。
  7. 数据库持久化:Redis 支持将数据持久化到磁盘中,从而支持数据备份和恢复,提高系统的可靠性。

综上所述,Redis 在缓存、消息队列、计数器和排行榜、分布式锁、会话存储、地理位置和空间索引、数据库持久化等多个应用场景中都具有很好的表现。

6.Memcached和Redis的区别

  • Redis 支持更丰富的数据类型(支持更复杂的应用场景)。Redis 不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。Memcached 只支持最简单的 k/v 数据类型。
  • Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而 Memcached 把数据全部存在内存之中。
  • Redis 有灾难恢复机制。 因为可以把缓存中的数据持久化到磁盘上。
  • Redis 在服务器内存使用完之后,可以将不用的数据放到磁盘上。但是,Memcached 在服务器内存使用完之后,就会直接报异常。
  • Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是 Redis 目前是原生支持 cluster 模式的。
  • Memcached 是多线程,非阻塞 IO 复用的网络模型;Redis 使用单线程的多路 IO 复用模型。 (Redis 6.0 引入了多线程 IO )
  • Redis 支持发布订阅模型、Lua 脚本、事务等功能,而 Memcached 不支持。并且,Redis 支持更多的编程语言。
  • Memcached 过期数据的删除策略只用了惰性删除,而 Redis 同时使用了惰性删除与定期删除。

7.Redis 数据类型有哪些

  • 5 种基础数据结构 :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
  • 3 种特殊数据结构 :HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)

8.keys命令存在的问题

  1. 性能问题:keys 命令会遍历整个 Redis 数据库中的所有键值,对于大型 Redis 数据库来说,这个操作可能会耗费大量时间和系统资源,导致 Redis 服务器的性能下降。
  2. 阻塞问题:由于 keys 命令会遍历整个 Redis 数据库,因此在执行 keys 命令期间,Redis 服务器会被阻塞,无法响应其他请求。
  3. 安全问题:keys 命令可以返回 Redis 数据库中的所有键值,包括一些敏感数据,如果在生产环境中误用 keys 命令,可能会导致泄露敏感数据。

9.SortedSet和List异同点

相同点:

  1. 都可以存储多个元素。
  2. 都可以通过索引来访问元素。
  3. 都可以在头部或尾部插入和删除元素。
  4. 都可以进行范围查询,即查询某个范围内的元素。
  5. 都支持阻塞式的弹出和插入操作。
  6. 都可以通过多种命令实现数据结构的基本操作,如增删改查。

不同点:

  1. 数据结构不同:List 是链表结构,SortedSet 是平衡树结构。
  2. 元素的唯一性:List 允许存储重复的元素,而 SortedSet 不允许存储重复的元素,并且元素按照指定的权重进行排序。
  3. 排序方式不同:List 中的元素按照插入顺序排序,而 SortedSet 中的元素按照指定的权重排序。
  4. 操作复杂度不同:List 中的大多数操作的复杂度都是 O(1) 级别的,而 SortedSet 中的大多数操作的复杂度都是 O(log N) 级别的,其中 N 表示元素个数。
  5. 适用场景不同:List 适用于先进先出(FIFO)的场景,如消息队列、任务队列等;SortedSet 适用于有序排列并且需要去重的场景,如排行榜、计数器等。

10.Redis事务

Redis 事务的基本使用方法如下:

  1. 通过 MULTI 命令开启一个事务。
  2. 在事务中执行多个命令,这些命令并不会立即被执行,而是被放入一个队列中。
  3. 通过 EXEC 命令将事务中的所有命令依次执行。
  4. 如果在事务执行过程中发生错误,可以通过 DISCARD 命令取消事务。

下面是一个简单的 Redis 事务示例:

sqlCopy code
MULTI SET key1 value1 SET key2 value2 GET key1 EXEC

在这个示例中,首先通过 MULTI 命令开启一个事务,然后执行了三个命令:SET key1 value1SET key2 value2GET key1。这些命令并不会立即被执行,而是被放入一个队列中。最后通过 EXEC 命令将事务中的所有命令依次执行,如果所有命令都执行成功,则返回结果集;否则返回 nil
Redis 事务还支持一些高级功能,如 WATCH 命令、CAS 命令等,可以用来实现乐观锁、原子操作等功能。
需要注意的是,在 Redis 中事务并不是严格意义上的 ACID 事务,因为 Redis 事务并不能保证所有命令的原子性,即使其中一个命令执行失败也不会回滚已执行的命令。因此,在使用 Redis 事务时需要格外小心,避免出现意外情况。

11.持久化机制

RDB方式
Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。
快照持久化是 Redis 默认采用的持久化方式,在 redis.conf 配置文件中默认有此下配置:

save 900 1           #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发bgsave命令创建快照。

save 300 10          #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发bgsave命令创建快照。

save 60 10000        #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发bgsave命令创建快照。

Redis 提供了两个命令来生成 RDB 快照文件:

  • save : 同步保存操作,会阻塞 Redis 主线程;
  • bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。

AOF方式
与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:

appendonly yes 

开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到内存缓存 server.aof_buf 中,然后再根据 appendfsync 配置来决定何时将其同步到硬盘中的 AOF 文件。
AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof。
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:

appendfsync always    #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec  #每秒钟同步一次,显式地将多个写命令同步到硬盘
appendfsync no        #让操作系统决定何时进行同步

为了兼顾数据和写入性能,用户可以考虑 appendfsync everysec 选项 ,让 Redis 每秒同步一次 AOF 文件,Redis 性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis 还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。

12.AOF 重写了解吗?

当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。
Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。

13.RDB和AOF如何选择?

RDB 比 AOF 优秀的地方

  • RDB 文件存储的内容是经过压缩的二进制数据, 保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。AOF 文件存储的是每一次写命令,类似于 MySQL 的 binlog 日志,通常会必 RDB 文件大很多。当 AOF 变得太大时,Redis 能够在后台自动重写 AOF。新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。不过, Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。
  • 使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。而 AOF 则需要依次执行每个写命令,速度非常慢。也就是说,与 AOF 相比,恢复大数据集的时候,RDB 速度更快。

AOF 比 RDB 优秀的地方

  • RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。生成 RDB 文件的过程是比较繁重的, 虽然 BGSAVE 子进程写入 RDB 文件的工作不会阻塞主线程,但会对机器的 CPU 资源和内存资源产生影响,严重的情况下甚至会直接把 Redis 服务干宕机。AOF 支持秒级数据丢失(取决 fsync 策略,如果是 everysec,最多丢失 1 秒的数据),仅仅是追加命令到 AOF 文件,操作轻量。
  • RDB 文件是以特定的二进制格式保存的,并且在 Redis 版本演进中有多个版本的 RDB,所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。
  • AOF 以一种易于理解和解析的格式包含所有操作的日志。你可以轻松地导出 AOF 文件进行分析,你也可以直接操作 AOF 文件来解决一些问题。比如,如果执行FLUSHALL命令意外地刷新了所有内容后,只要 AOF 文件没有被重写,删除最新命令并重启即可恢复之前的状态。

14.Redis常见的部署方式有哪些

  1. 单机部署

单机部署是指将Redis部署在单个服务器上,通过监听特定端口提供服务。这种方式简单易用,适用于小规模应用场景,但是容易出现单点故障,无法满足高可用性要求。

  1. 主从复制部署

主从复制部署是指在主节点上写入数据,在从节点上进行复制。通过多个从节点来实现读写分离,提高读取性能,并且从节点可以作为主节点的备份,保证高可用性。

  1. 集群部署

集群部署是将Redis实例分布在多个物理节点上,通过集群管理器对实例进行管理和调度,实现高可用性和横向扩展。集群部署相对于主从复制部署,能够提供更高的性能和更好的可扩展性,但是需要考虑数据分片和节点之间的网络通信问题。

  1. 哨兵部署

哨兵部署是在主从复制基础上增加了哨兵节点来监控主节点状态,当主节点宕机时,哨兵节点会自动切换从节点为新的主节点。哨兵部署可以提供较高的可用性,并且相对于集群部署来说,管理和维护成本更低,但是对于大规模数据和高并发场景来说,性能和可扩展性不如集群部署。

15.主从复制

Redis主从复制是一种数据同步机制,其中一个Redis实例作为主节点(Master),而其他Redis实例则作为从节点(Slave)来复制主节点的数据。
主节点接收客户端的写操作,并将这些写操作的结果通过网络发送给从节点,从节点接收这些结果并更新本地数据。这样,即使主节点宕机,从节点也可以继续提供服务并保持数据的完整性。
在配置Redis主从复制时,需要指定主节点的IP地址和端口号,并将从节点的配置文件中的slaveof选项设置为主节点的IP地址和端口号。一旦从节点成功连接到主节点,它将开始接收主节点的数据,并将其存储在本地内存中。
主从复制可以用于多种场景,例如:

  1. 数据备份:从节点可以用作主节点数据的备份,以避免数据丢失。
  2. 负载均衡:从节点可以用于分担主节点的负载,提高系统的性能和稳定性。
  3. 读写分离:主节点可以专注于处理写操作,而从节点可以处理读操作,以提高系统的并发性能。

需要注意的是,主从复制并不是高可用性的解决方案,因为当主节点宕机时,需要手动切换从节点成为主节点来维护服务的可用性。如果需要高可用性,可以使用Redis Sentinel或Redis Cluster。

16.哨兵Sentinel

https://pdai.tech/md/db/nosql-redis/db-redis-x-sentinel.html
https://juejin.cn/post/6998564627525140494#heading-13
作用

  1. 监控:监控所有 Redis 节点的状态。
  2. 故障转移:当哨兵发现主节点下线时,会在所有从节点中选择一个作为新的主节点,并将所有其他节点的 Master 指向新的主节点。同时已下线的原主节点也会被降级为从节点,并修改配置将 Master 指向新的主节点,等到它重新上线时就会自动以从节点进行工作。
  3. 通知:当哨兵选举了新的主节点之后,可以通过 API 向客户端进行通知。

哨兵的原理
从库发现
对于哨兵的配置,我们只需要配置主库的信息,哨兵在连接主库之后,会调用 INFO 命令获取主库的信息,再从中解析出连接主库的从库信息,再以此和其他从库建立连接进行监控。
发布/订阅机制
哨兵们在连接同一个主库之后,是通过发布/订阅(pub/sub)模式来发现彼此的存在的。
监控
哨兵在对 Redis 节点建立 TCP 连接之后,会周期性地发送 PING 命令给节点(默认是 1s),以此判断节点是否正常。如果在 down-after-millisenconds 时间内没有收到节点的响应,它就认为这个节点掉线了。
主观下线
当哨兵发现与自己连接的其他节点断开连接,它就会将该节点标记为主观下线(+sdown),包括主节点、从节点或者其他哨兵都可以标记为 sdown 状态。
客观下线
哨兵确认主节点是否真的宕机这一步成为客观下线确认,如果主节点真的宕机了,哨兵就会将主节点标记为客观下线(+odown)状态。
客观下线投票过程

  1. 当哨兵发现主节点下线,标记主节点为 sdown 状态。
  2. 哨兵向其他哨兵发送 SENTINEL is-master-down-by-addr 命令,询问其他哨兵该主节点是否已下线。
  3. 其他哨兵在收到投票请求之后,会检查本地主缓存中主节点的状态并进行回复(1 表示下线,0 表示正常)。
  4. 发起的询问的哨兵在接收到回复之后,会累加“下线”的得票数。
  5. 当下线的票数大于一半哨兵数量并且不小于 quorum 时,就会将主节点标记为 odown 状态。并开始准备故障转移
  6. 发起投票的哨兵有一个投票倒计时,倒计时结束如果票数仍然不够的话,则放弃本次客观线下投票。并尝试继续与主节点建立连接。

17.Redis cluster

Redis Cluster 是 Redis 的分布式实现,允许您将 Redis 在多个节点之间水平扩展,提供高可用性和自动数据分片。Redis Cluster 自动将数据分配到多个节点上,这有助于分配负载并增加应用程序的吞吐量。
Redis Cluster 使用一种称为哈希槽的分片算法,它允许将每个键分配给集群中的特定节点。这确保每个节点仅存储数据的一个子集,从而更容易扩展和管理 Redis 数据库。
Redis Cluster 支持主从复制模型,其中每个主节点有一个或多个从节点。主节点负责处理读写操作,而从节点复制主节点的数据并作为热备份,在主节点故障时可以立即接替主节点的功能。
Redis Cluster 还提供自动故障转移,当主节点失败时,将自动替换为其中一个从节点。这有助于确保高可用性并在节点故障时防止数据丢失。

18.哈希分区算法有哪些

  1. CRC16算法:Redis cluster默认的哈希分区算法是CRC16算法,它是一种快速的哈希算法,具有良好的分布性和低碰撞率。在Redis cluster中,每个键都会被CRC16算法映射到一个16位整数上,然后根据这个整数对节点数取模得到该键所在的节点。
  2. CRC32算法:Redis cluster也支持CRC32算法作为哈希分区算法,它是一种更为复杂的哈希算法,具有更好的随机性和更低的碰撞率。在Redis cluster中,使用CRC32算法需要手动设置。
  3. MD5算法:Redis cluster还支持MD5算法作为哈希分区算法,它是一种更为安全的哈希算法,具有很高的随机性和很低的碰撞率。在Redis cluster中,使用MD5算法需要手动设置。

不同的哈希分区算法适用于不同的场景,CRC16算法在性能和效果上都有良好的表现,因此是Redis cluster默认的哈希分区算法。如果需要更高的哈希分布性和更低的碰撞率,可以考虑使用CRC32算法或MD5算法。

19.过期键的删除策略

常用的过期数据的删除策略就两个(重要!自己造缓存轮子的时候需要格外考虑的东西):

  1. 惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。
  2. 定期删除 : 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。

定期删除对内存更加友好,惰性删除对 CPU 更加友好。两者各有千秋,所以 Redis 采用的是 定期删除+惰性/懒汉式删除。但是,仅仅通过给 key 设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉了很多过期 key 的情况。这样就导致大量过期 key 堆积在内存里,然后就 Out of memory 了。
怎么解决这个问题呢?答案就是:Redis 内存淘汰机制。

20.内存淘汰策略有哪些

Redis 提供 6 种数据淘汰策略:

  1. volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
  2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  4. allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  6. no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!

4.0 版本后增加以下两种:

  1. volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
  2. allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key。

21.如何保证缓存与数据库双写时的数据一致性

https://juejin.cn/post/6850418121754050567#comment

22.缓存穿透

缓存穿透说简单点就是大量请求的 key 是不合理的,根本不存在于缓存中,也不存在于数据库中 。这就导致这些请求直接到了数据库上,根本没有经过缓存这一层,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。
解决办法
最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。

23.缓存雪崩

缓存在同一时间大面积的失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力。 这就好比雪崩一样,摧枯拉朽之势,数据库的压力可想而知,可能直接就被这么多请求弄宕机了。
针对 Redis 服务不可用的情况:

  1. 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
  2. 限流,避免同时处理大量的请求。

针对热点缓存失效的情况:

  1. 设置不同的失效时间比如随机设置缓存的失效时间。
  2. 缓存永不失效(不太推荐,实用性太差)。
  3. 设置二级缓存。

缓存雪崩和缓存击穿有什么区别?

缓存雪崩和缓存击穿比较像,但缓存雪崩导致的原因是缓存中的大量或者所有数据失效,缓存击穿导致的原因主要是某个热点数据不存在与缓存中(通常是因为缓存中的那份数据已经过期)

24.缓存击穿

缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。这就可能会导致瞬时大量的请求直接打到了数据库上,对数据库造成了巨大的压力,可能直接就被这么多请求弄宕机了。

有哪些解决办法?

  • 设置热点数据永不过期或者过期时间比较长。
  • 针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
  • 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。

缓存穿透和缓存击穿有什么区别?

缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。
缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期)

25.Redis 怎么实现消息队列?

(1)List 结构;(2)Pub/Sub 模式;(3)Stream 结构
https://mp.weixin.qq.com/s/_q0bI62iFrG8h-gZ-bCvNQ

26.pipeline的作用

Redis Pipeline是一种优化Redis批量查询的技术。它允许客户端将多个Redis命令一次性发送给Redis服务器,而不需要等待每个命令的响应。这样可以减少客户端与服务器之间的往返通信,从而提高Redis的性能。
具体来说,Redis Pipeline的工作原理如下:

  1. 客户端将多个Redis命令打包成一个请求。
  2. 客户端将打包后的请求发送给Redis服务器。
  3. Redis服务器收到请求后,不立即执行,而是将请求缓存起来。
  4. Redis服务器按照请求的顺序逐一执行请求,并将执行结果保存在缓存中。
  5. 客户端最终一次性接收所有命令的执行结果。

相比于单独发送每个Redis命令,使用Pipeline可以极大地减少通信延迟和网络带宽,从而提高Redis的吞吐量。在一些需要批量查询Redis的场景下,使用Pipeline可以显著提高应用程序的性能。

27.LUA脚本

  • 减少网络开销,在 Lua脚本 中可以把多个命令放在同一个脚本中运行
  • 原子操作,Redis 会将整个脚本作为一个整体执行,中间不会被其他命令插入(编写脚本过程中无需担心会出现竞态条件)
  • 复用性,客户端发送的脚本会永远存储在 Redis中,意味着其他客户端可以复用这一脚本。

28.什么时候使用pipeline,什么时候使用lua

  • 当多个redis命令之间没有依赖、顺序关系(例如第二条命令依赖第一条命令的结果)时,建议使用pipline;
  • 如果命令之间有依赖或顺序关系时,pipline就无法使用,此时可以考虑才用lua脚本的方式来使用。

28.什么是RedLock?

在RedLock中,多个客户端通过竞争获取一个分布式锁,只有获得锁的客户端才能够执行对共享资源的访问。为了防止分布式环境中出现单点故障,RedLock采用了多个Redis实例来存储锁信息,并且在获取锁时需要占用大多数Redis实例的锁才能成功获取锁,从而保证了分布式锁的可靠性和高可用性。

29.Redis单线程理解

RedLock是基于redis实现的分布式锁,它能够保证以下特性:

  • 互斥性:在任何时候,只能有一个客户端能够持有锁;避免死锁:
  • 当客户端拿到锁后,即使发生了网络分区或者客户端宕机,也不会发生死锁;(利用key的存活时间)
  • 容错性:只要多数节点的redis实例正常运行,就能够对外提供服务,加锁或者释放锁;

RedLock算法思想,意思是不能只在一个redis实例上创建锁,应该是在多个redis实例上创建锁,n / 2 + 1,必须在大多数redis节点上都成功创建锁,才能算这个整体的RedLock加锁成功,避免说仅仅在一个redis实例上加锁而带来的问题。

30.lO多路复用

Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。
其实 Redis 是利用上Linux 中的 IO 多路复用机制, Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流。
简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。
内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。

猜你喜欢

转载自blog.csdn.net/weixin_56640241/article/details/129838680