乐趣区

关于后端:面试题系列一

Redis 有哪些数据结构?其底层是怎么实现的?

[Redis 系列(一):深刻理解 Redis 数据类型和底层数据结构
](https://blog.zysicyj.top/2023/08/12/%E6%8A%80%E6%9C%AF%E6%96%…)

  1. 字符串(String): 用于存储文本或二进制数据。能够执行字符串的基本操作,如设置、获取、减少、缩小等。
  2. 哈希表(Hash): 存储键值对汇合,相似于关联数组。实用于存储对象属性或配置信息。
  3. 列表(List): 应用双向链表实现的有序汇合,容许插入和删除元素。能够用于实现队列、栈等数据结构。
  4. 汇合(Set): 存储不反复的无序元素汇合。反对求交加、并集、差集等操作,实用于数据去重和关联性操作。
  5. 有序汇合(Sorted Set): 相似于汇合,但每个元素都有一个分数(score),并依据分数进行排序。实用于排行榜、优先级队列等场景。
  6. 位图(Bitmap): 应用字符串来示意位的数据结构,反对位操作。实用于标记、计数等场景。
  7. HyperLogLog: 用于预计汇合中惟一元素的个数,占用固定的内存空间,实用于基数统计场景。
  8. 天文空间(GeoSpatial): 存储地理位置信息,反对间隔计算和地位查问。

    什么是缓存击穿?什么起因?如何解决?

    缓存击穿是指在高并发状况下,一个缓存中不存在然而频繁被申请的数据,导致申请间接打到数据库,减少数据库的负载和提早。这通常产生在以下状况下:

  9. 热点数据生效: 当某个热点数据过期或被移除时,大量的并发申请同时拜访该数据,导致申请绕过缓存间接拜访数据库。
  10. 分布式系统中的节点生效: 在分布式缓存环境下,如果一个或多个缓存节点生效,会导致申请无奈命中缓存,从而打到后端数据库。

解决缓存击穿的办法有多种,其中常见的包含:

  1. 设置热点数据永不过期: 对于热点数据,能够设置永不过期,确保数据始终可用。但要留神,这会占用缓存空间,可能导致其余数据的驱赶。
  2. 应用互斥锁(Mutex Lock): 在缓存生效时,应用互斥锁来管制只有一个申请可能从数据库加载数据,其余申请在期待中,防止并发拜访数据库。
  3. 提前异步加载: 在数据行将过期时,启动一个异步工作去加载数据到缓存,防止过期时间接申请数据库。
  4. 应用分布式锁: 在分布式环境下,能够应用分布式锁来爱护缓存数据的加载过程,确保只有一个节点进行加载。
  5. 应用布隆过滤器: 布隆过滤器是一种用于判断元素是否存在于汇合中的数据结构,能够用来判断某个数据是否须要去数据库加载,缩小有效的申请。
  6. 热点数据预加载: 提前在系统启动时加载热点数据到缓存,防止在运行时因为缓存生效而引起的问题。

抉择哪种办法取决于具体的业务场景和需要,通常须要依据零碎的特点和拜访模式来综合思考。

什么是缓存雪崩?什么起因?如何解决?

缓存雪崩是指缓存在某个时间段内大面积生效,导致大量申请间接拜访后端数据库,造成数据库压力激增和零碎性能降落的状况。通常产生在以下状况下:

  1. 大量缓存同时生效: 当多个缓存数据在同一个时间段内同时生效,导致大量申请间接打到后端数据库。
  2. 缓存服务器宕机: 如果缓存服务器宕机,缓存数据不可用,申请会间接拜访后端数据库。
  3. 业务高峰期: 在业务高峰期,访问量剧增,缓存生效导致数据库申请激增。

解决缓存雪崩的办法包含:

  1. 应用多级缓存: 引入多级缓存,将数据同时存储在多个缓存层,升高某个缓存层生效的危险。
  2. 设置随机过期工夫: 对于雷同类型的数据,设置随机的过期工夫,防止大量数据同时生效。
  3. 缓存数据永不过期: 对于热点数据,能够设置永不过期,确保数据始终可用。
  4. 异步加载缓存: 在缓存生效时,启动异步工作去加载数据,防止在缓存生效时间接拜访数据库。
  5. 限流降级: 在高峰期限度申请的并发数,将局部申请降级解决,防止对后端服务造成过大压力。
  6. 熔断策略: 依据零碎负载状况,施行熔断策略,防止零碎解体。
  7. 缓存预热: 在系统启动时,事后加载热点数据到缓存,防止系统启动时的大量申请。
  8. 分布式部署: 将缓存服务器散布在不同的节点上,升高单点故障的危险。

综合思考业务需要和零碎特点,能够采纳上述办法来解决缓存雪崩问题,保障系统的稳定性和性能。

Redis 长久化机制理解吗?

[Redis 系列(二):深刻解读 Redis 的两种长久化形式
](https://blog.zysicyj.top/2023/08/13/%E6%8A%80%E6%9C%AF%E6%96%…)

是的,Redis 具备两种次要的长久化机制:RDB(Redis Database)快照和 AOF(Append-Only File)日志。这些机制用于将内存中的数据长久化到硬盘上,以避免数据失落。

  1. RDB 快照:

    • RDB 长久化通过将内存中的数据快照保留到一个二进制文件(例如dump.rdb)中来实现。
    • 能够手动执行 RDB 快照,也能够通过配置项定期主动执行。
    • 长处是文件小,适宜备份和复原,对性能影响较小。
    • 毛病是数据可能在两次快照之间产生失落,不适宜数据实时性要求较高的场景。
  2. AOF 日志:

    • AOF 长久化记录每个写操作(例如 SET、DEL)到一个追加的日志文件(例如appendonly.aof)中。
    • AOF 文件以文本形式记录,能够随时对其进行追加、更新和重写。
    • 能够通过配置项设置不同的 AOF 策略:always(每次写操作都记录)、everysec(每秒记录一次)、no(不记录)。
    • 长处是能够实现更高的数据实时性,适宜对数据安全性要求较高的场景。
    • 毛病是 AOF 文件绝对较大,复原速度可能较慢。

在理论利用中,能够依据业务需要抉择适合的长久化机制,甚至能够同时应用 RDB 和 AOF,以进步数据的安全性和可靠性。另外,Redis 还提供了混合长久化的形式(默认应用 AOF 来复原数据,而 RDB 用于备份),以充分发挥两种长久化机制的劣势。

Redis 利用场景有哪些?

  1. 缓存: 最常见的用处,将热门数据存储在内存中,以进步访问速度,加重数据库累赘。实用于读取频繁、数据量较大的场景。
  2. 会话存储: 将用户会话数据存储在 Redis 中,实现分布式会话治理,以防止单点故障和状态共享问题。
  3. 计数器和统计: Redis 的原子操作能够实现计数器性能,用于统计页面拜访、点赞、评论等。
  4. 排行榜 / 热门内容: 利用有序汇合(Sorted Set)数据结构,存储并排名用户、文章、商品等,以实现排行榜或展现热门内容。
  5. 公布订阅: Redis 的公布订阅机制容许实时地将音讯公布给订阅者,用于构建实时告诉、聊天室等性能。
  6. 分布式锁: 利用 Redis 的原子操作和过期工夫设置,实现分布式环境下的锁机制,保障资源的互斥拜访。
  7. 限流器: 利用 Redis 的令牌桶或漏桶算法,实现申请的限流管制,避免突发流量影响零碎稳定性。
  8. 缓存穿透防护: 将空值或异样数据存储在缓存中,防止缓存穿透引起的数据库查问压力。
  9. 地理位置服务: 利用 Redis 的地理位置数据类型,存储并查问地理位置信息,用于左近的人、地点等性能。
  10. 工作队列: 利用列表数据结构,实现异步工作队列,解决后台任务、音讯队列等。
  11. 即时数据分析: 将实时产生的数据存储在 Redis 中,供数据分析应用,如实时监控、实时报表等。

这些只是 Redis 利用场景的一部分,实际上,因为 Redis 的高性能、低提早和丰盛的数据结构,它在很多畛域都有宽泛的利用。依据具体的业务需要,能够灵便抉择适合的场景来应用 Redis。

Redis 为什么这么快?

Redis 之所以具备如此高的性能,次要是因为以下几个方面的设计和优化:

  1. 内存存储: Redis 将数据存储在内存中,内存的读写速度远高于磁盘,因而可能实现极低的读写提早。
  2. 单线程模型: Redis 采纳单线程模型解决客户端申请,防止了多线程的锁竞争和上下文切换开销,缩小了性能损耗。
  3. 非阻塞 IO: Redis 应用非阻塞 IO 和事件驱动的形式来解决客户端连贯和网络通信,无效利用了操作系统提供的异步 IO 机制,进步了并发能力。
  4. 数据结构优化: Redis 内置了多种高效的数据结构,如哈希表、有序汇合、跳表等,针对不同的利用场景抉择最合适的数据结构,进步了数据操作的效率。
  5. 长久化策略: Redis 反对多种长久化形式,如 RDB 快照和 AOF 日志,能够依据需要抉择适合的长久化策略,保障数据的可靠性。
  6. 多种网络协议反对: Redis 反对多种网络协议,如 HTTP、RESP(Redis Serialization Protocol)等,不便不同编程语言和应用程序与 Redis 进行交互。
  7. 数据压缩: Redis 在存储数据时进行了压缩,减小了内存占用,进步了数据的存储密度。
  8. 预分配内存: Redis 在启动时事后调配肯定数量的内存,缩小了内存调配的开销,进步了内存应用效率。
  9. 管道技术: Redis 的管道(Pipeline)技术容许客户端发送多个命令,在一个连贯上间断执行,缩小了网络通信的开销。
  10. 高效的排序算法: 在有序汇合(Sorted Set)中,Redis 采纳跳表(Skip List)作为底层数据结构,实现了高效的排序和检索。

Redis 事务如何实现?

Redis 事务是一组命令的汇合,能够在一个原子操作内执行多个命令。Redis 的事务通过 MULTI、EXEC、WATCH、DISCARD 等命令来实现,它提供了相似于传统数据库的事务个性,但与传统数据库的事务有一些不同之处。

以下是 Redis 事务的实现流程:

  1. MULTI 命令: 事务开始时,客户端发送 MULTI 命令,通知 Redis 开始记录后续的命令序列。
  2. 多个命令: 在 MULTI 和 EXEC 之间的命令会被退出到事务队列中,但并不会立刻执行。
  3. EXEC 命令: 当客户端发送 EXEC 命令时,Redis 会顺次执行事务队列中的命令。在执行过程中,Redis 会将事务队列中的命令顺次执行,如果其中的某个命令执行失败,不会影响其余命令的执行。
  4. 事务执行后果: EXEC 命令执行实现后,Redis 会返回事务中所有命令的执行后果,以数组模式返回。如果事务中的某个命令执行失败,对应的后果将是错误信息。
  5. DISCARD 命令: 如果在 MULTI 和 EXEC 之间,客户端发送了 DISCARD 命令,那么事务队列中的所有命令都会被革除,事务被勾销。
  6. WATCH 命令: 为了实现乐观锁的机制,能够应用 WATCH 命令监督一个或多个键。如果在事务执行前,有其余客户端批改了被监督的键,整个事务会被勾销。

Redis 事务的特点:

  • Redis 事务是原子性的:在 EXEC 执行期间,事务中的所有命令要么都被执行,要么都不被执行。
  • Redis 事务是隔离的:事务的执行过程不会受到其余客户端的影响。
  • Redis 事务是不反对回滚的:即便其中某个命令执行失败,不会回滚后面曾经执行的命令。

须要留神的是,尽管 Redis 事务提供了一种封装多个命令的形式,然而因为 Redis 的单线程模型,事务中的某些命令可能会因为特定的状况(如阻塞操作)导致整个事务执行的工夫较长。因而,在应用 Redis 事务时,须要思考事务执行期间可能的性能影响。

Redis 过期键删除策略?

在 Redis 中,有两种次要的过期键删除策略,别离是惰性删除和定期删除,还有一些淘汰策略用于开释内存空间。以下是这些策略的具体阐明:

  1. 惰性删除(Lazy Expiration): 这是 Redis 默认的过期键删除策略。当拜访一个曾经过期的键时,Redis 会立刻删除该键并返回空值。这种策略防止了在拜访时才删除键,节俭了内存和 CPU 资源。
  2. 定期删除(定时工作删除): Redis 会随机抽取一些过期键,并查看它们是否过期。如果过期,就会删除这些键。这种策略通过定期工作进行删除,以防止删除大量过期键对性能造成影响。
  3. 内存淘汰策略(Eviction Policies): 当内存应用达到肯定阈值(由 maxmemory 参数指定)时,Redis 会触发淘汰策略来开释空间。常见的淘汰策略包含:

    • noeviction:当内存不足以包容新写入数据时,写入操作会报错。
    • allkeys-lru:从所有键中抉择最近起码应用的键进行删除。
    • volatile-lru:从设置了过期工夫的键中抉择最近起码应用的键进行删除。
    • allkeys-random:随机抉择一个键进行删除。
    • volatile-random:从设置了过期工夫的键中随机抉择一个键进行删除。
    • volatile-ttl:从设置了过期工夫的键中抉择剩余时间最短的键进行删除。

这些策略能够通过 Redis 的配置参数进行设置,例如:

# 设置过期键删除策略为定期删除
config set maxmemory-policy noeviction

须要依据理论场景和需要来抉择适宜的策略和参数值,以均衡内存应用和性能。

Redis 怎么实现音讯队列?

Redis 能够用作轻量级的音讯队列,实现根本的音讯公布和订阅性能。以下是在 Redis 中如何实现音讯队列的根本步骤:

  1. 公布音讯: 在发布者端,应用 PUBLISH 命令将音讯公布到指定的频道(通道)。

    PUBLISH channel_name message_content
  2. 订阅音讯: 在订阅者端,应用 SUBSCRIBE 命令订阅一个或多个频道,从中接管发布者公布的音讯。

    SUBSCRIBE channel_name
  3. 接管音讯: 订阅者在订阅了频道后,会实时接管到发布者公布的音讯。

通过上述步骤,你能够实现根本的公布 - 订阅模式的音讯队列。然而,须要留神以下几点:

  • Redis 的音讯队列不反对音讯长久化,即如果没有订阅者在线时,音讯会失落。
  • 如果须要反对长久化、多个消费者、音讯确认等高级个性,可能须要思考应用专门的音讯队列中间件,如 RabbitMQ、Apache Kafka 等。

在理论利用中,如果须要更多的音讯队列个性,能够应用 Redis 的 LIST 数据结构来实现简略的队列。将发布者公布的音讯插入到 LIST 中,而后消费者从 LIST 中弹出音讯进行解决。但须要留神的是,Redis 并不是专门为音讯队列设计的,更适宜用于一些简略的音讯公布 - 订阅场景。对于高性能、大规模的音讯队列需要,倡议应用专门的音讯队列中间件。

本文由 mdnice 多平台公布

退出移动版