redis面试


Redis单机模式、集群模式的区别,说一下哨兵模式

Redis 是一个高性能的键值存储系统,支持多种部署模式,以满足不同的需求。以下是 Redis 单机模式、集群模式的区别,以及哨兵模式的介绍:

1. Redis 单机模式

特点

  • 单节点运行:所有数据都存储在一个 Redis 实例中,读写操作也都在该实例上进行。
  • 简单易用:配置和管理较为简单,适用于小规模或对高可用性要求不高的场景。
  • 数据安全性:如果该节点出现故障,所有数据都可能丢失,除非配备了持久化机制(如 RDB 或 AOF)。
  • 性能瓶颈:当数据量或访问请求增加时,单节点的性能和容量可能成为瓶颈。

适用场景

  • 开发环境、测试环境、小规模的生产环境或对高可用性和数据持久化要求不高的应用。

2. Redis 集群模式

特点

  • 多节点分布:Redis 集群由多个节点组成,数据分片存储在不同的节点上,每个节点只存储数据的一部分。
  • 高可用性:集群模式提供数据的冗余备份,某个节点失效时,其他节点可以继续提供服务。
  • 自动分片:数据通过一致性哈希算法自动分片,分布到集群的各个节点,集群可以动态扩展和缩减节点数量。
  • 支持大规模应用:可以处理较大的数据量和高并发请求,适用于需要高可用和高性能的大规模应用。

适用场景

  • 大型互联网应用、分布式系统、需要高可用性和高吞吐量的数据存储场景。

3. Redis 哨兵模式(Sentinel)

介绍: Redis 哨兵模式是用于实现高可用性的一种模式,它可以监控多个 Redis 实例,并在主节点(Master)发生故障时,自动将某个从节点(Slave)提升为主节点,从而实现故障切换(failover)。

哨兵模式的主要功能

  1. 监控:哨兵会持续监控主节点和从节点的运行状态。如果发现主节点不可用,就会通知管理员并进行故障切换。
  2. 自动故障切换:当主节点发生故障时,哨兵会选择一个从节点提升为新的主节点,并将其他从节点重新配置为复制新的主节点。
  3. 通知:哨兵可以将事件(如故障切换)通知给客户端,客户端可以根据通知调整连接的主节点。
  4. 配置提供者:哨兵还可以作为配置提供者,客户端可以通过哨兵获取当前的主节点信息,以便连接到正确的实例。

工作流程

  • 哨兵以一定频率向 Redis 实例发送 PING 命令来判断其状态。
  • 如果一个哨兵发现某个节点不可达,它会认为该节点“主观下线”(Subjectively Down, SDOWN)。
  • 如果足够多的哨兵(通过配置的quorum参数来控制)认为主节点不可用,则该主节点被标记为“客观下线”(Objectively Down, ODOWN)。
  • 一旦确定主节点 ODOWN,哨兵将会进行故障切换,并推选一个从节点作为新的主节点,完成之后通知其他从节点和客户端。

适用场景

  • 需要高可用性的生产环境,Redis 主从结构下,使用哨兵模式可以自动监控和处理故障,确保系统的稳定性和连续性。

总结

  • 单机模式:简单、适用于小规模应用,但存在单点故障问题。
  • 集群模式:适用于大规模、分布式系统,提供高可用性和可扩展性。
  • 哨兵模式:为主从复制提供高可用性支持,能自动处理主节点故障,实现自动故障切换。

选择哪种模式取决于应用的规模、性能需求、可用性要求等。

Redis的连接池了解过吗

了解过,Redis 连接池是指在应用程序与 Redis 数据库之间维护一个连接池,以便重用已有的连接,而不是在每次需要时都创建新的连接。使用连接池可以提高应用程序的性能,特别是在高并发场景下。

连接池的工作原理

  • 连接复用:连接池中预先创建了一定数量的连接,这些连接可以被多个客户端请求复用。当一个请求完成后,连接不会关闭,而是返回到连接池中等待下一个请求。
  • 最大连接数:连接池通常设有最大连接数限制,避免资源耗尽。当连接池中的所有连接都被占用时,新请求会被阻塞,直到有可用连接释放出来,或者抛出超时异常。
  • 最小连接数:连接池可以配置最小连接数,保持一定数量的连接始终处于可用状态,以减少请求的等待时间。

我们项目里面使用的就是 Lettuce(Java)

Lettuce 默认提供异步、同步和响应式 API,同时也支持连接池。

lettuce:
      pool:
        # 连接池最大连接数
        # 配置连接池中最大的活跃连接数,也就是最多可以同时创建和使用多少个 Redis 连接。
        max-active: 200
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        # 设置连接池最大阻塞等待时间,单位为毫秒。-1ms 表示没有限制,即一直等待,直到有连接可用。
        max-wait: -1ms
        # 这个参数控制着当连接池中空闲连接超过这个数量时,多余的空闲连接将会被释放,避免资源浪费。
        # 连接池中的最大空闲连接
        max-idle: 10
        # 设置连接池中最小空闲连接数,即连接池中至少要保持多少个空闲连接,以确保在需要时有足够的连接可用。
        # 连接池中的最小空闲连接
        min-idle: 0

Spring Redis Template的用法

Spring Redis Template 是 Spring Data Redis 提供的一个用于简化 Redis 操作的类,它封装了对 Redis 数据库的各种常见操作。通过 RedisTemplate,你可以轻松地进行字符串、哈希、列表、集合、有序集合等类型的操作。

使用 RedisTemplate 的一些注意事项

  1. 序列化器的配置RedisTemplate 默认使用 JdkSerializationRedisSerializer 来序列化键和值,如果存储非 Java 序列化对象,可能导致数据无法被其他语言客户端识别。因此,通常会配置 StringRedisSerializerJackson2JsonRedisSerializer 等序列化器。
  2. 线程安全RedisTemplate 是线程安全的,可以被多个线程共享使用。
  3. 事务支持RedisTemplate 支持 Redis 的事务功能,可以通过 redisTemplate.multi()redisTemplate.exec() 来开启和提交事务。
  4. 管道操作:对于批量操作,可以通过管道(pipeline)来提高性能

在我门的项目中

这个配置的目的是通过 RedisTemplate 提供一种方便的方式与 Redis 进行交互,并且通过自定义序列化器来确保 Redis 中的数据以合适的格式存储和读取,特别是使用 JSON 格式来存储对象数据,从而提高了数据的可读性和兼容性。

缓存:常用于将一些频繁访问的数据缓存到 Redis 中,减少对数据库的访问压力。

分布式锁:通过 setnx 操作实现分布式锁,确保在分布式环境中多个进程之间的互斥。

计数器:通过 Redis 的原子递增操作实现分布式计数器。

消息队列:利用 Redis 的列表结构实现简单的消息队列。

public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory  connectionFactory)
这是一个返回 RedisTemplate<String, Object> 类型的 Bean 方法。RedisTemplate 是 Spring 提供的一个用于执行 Redis 操作的模板类。
参数:RedisConnectionFactory 是一个连接工厂接口,用于创建与 Redis 服务器的连接。
用于将 Java 对象序列化为 JSON 字符串,或者将 JSON 字符串反序列化为 Java 对象。
设置 Redis 值(value)的序列化方式为 jackson2JsonRedisSerializer。
JSON 格式存储和读取	
redisTemplate.setConnectionFactory(connectionFactory);
解释:为 RedisTemplate 设置连接工厂,用于创建与 Redis 服务器的连接。
作用:绑定 RedisTemplate 和实际的 Redis 连接,使得 RedisTemplate 能够通过连接工厂与 Redis 服务器进行通信。

Redis连接泄露

Redis连接泄露指的是在使用Redis连接池的环境中,连接在使用后未能正确释放或归还到连接池,导致连接池中的连接数量逐渐减少,最终可能耗尽所有可用连接,导致应用程序无法再获得新的连接来与Redis服务器通信。

连接泄露的成因

  1. 未关闭连接:某些代码在使用完Redis连接后,没有调用 close() 方法归还连接到连接池,导致连接无法被其他请求重用。
  2. 异常处理不当:在连接使用过程中,如果发生异常并且没有正确处理,可能会导致连接无法正确归还。例如,在一个try-catch块中获取了Redis连接,但在catch块中忘记释放连接。
  3. 资源竞争:当多个线程或进程同时获取连接并尝试释放连接时,可能会出现竞争条件,导致连接无法正常归还。

Redis 实现消息队列与 Kafka 的区别

1. 数据结构

  • Redis:Redis 的消息队列通常使用 LIST 数据结构来实现,利用 LPUSHRPOP 操作来添加和消费消息。Redis 也可以利用 PUB/SUB 实现发布/订阅模式,适合实时消息传递。
  • Kafka:Kafka 是一个分布式流处理平台,它使用分区和日志数据结构来实现消息队列。消息以日志形式存储在主题(topic)中,每个主题可以有多个分区,消息在分区中按照时间顺序追加。

2. 消息持久化

  • Redis:Redis 默认将消息存储在内存中,并可以通过持久化机制(RDB 快照、AOF 日志)将数据持久化到磁盘。消息在 Redis 中是易失的,主要用作缓存或实时处理。
  • Kafka:Kafka 主要关注消息的持久化,所有消息都存储在磁盘上,并且可以配置保留策略(例如按时间或空间限制)。消息即使在系统重启后也能保留,适合日志数据存储。

3. 消息处理

  • Redis:Redis 的队列模式支持简单的生产者-消费者模式,使用 LIST 实现的队列支持 FIFO 顺序,且支持阻塞操作(BRPOP)。PUB/SUB 模式的消息会被所有订阅者接收,但没有消息持久化,订阅者在消息发布时需要在线。
  • Kafka:Kafka 支持分布式消费模式,消息被写入到多个分区中,消费者可以并行读取不同的分区。Kafka 支持消费者组(Consumer Groups),每个分区的消息只会被一个消费者组中的一个消费者处理,支持水平扩展和高吞吐量。

4. 性能和扩展性

  • Redis:Redis 是单线程的,通过事件循环机制处理 I/O 操作,具有低延迟和高性能。适用于高频率的数据读取和写入操作,但在消息量很大的场景下,可能会受到内存限制和单线程处理能力的制约。

  • Kafka:Kafka 是分布式的,具有高吞吐量和高可扩展性。可以通过增加分区和消费者实例来扩展处理能力。适用于处理大规模的数据流和日志数据。

    redis是怎么解决key冲突的

    1.覆盖原则

    Redis 是一个键值存储系统,每个键在 Redis 中都是唯一的。当你试图将一个新值存储到已经存在的键上时,Redis 会直接覆盖原有的值。这个过程是原子的,也就是说,在同一个时间点,只能有一个值与该键相关联。

    2.原子操作

    Redis 提供了一些原子操作,确保在多客户端并发访问同一个键时不会产生冲突。比如,INCRDECRSETNX 等命令都是原子的,意味着这些操作在执行时是不可分割的,确保多个客户端并发修改同一个键时不会出现竞争条件。

    3.分布式锁**

    在分布式系统中,Redis 可以通过实现分布式锁来控制对关键资源的访问,避免键冲突。Redis 提供了 SET 命令的扩展参数,如 NXEX,来实现分布式锁。

    1. 自动过期

    Redis 提供了键的自动过期机制。通过设置键的生存时间(TTL),可以确保某些键在过期后自动删除,从而避免了长期存在的冲突风险。

REDIS持久化

RDB和AOF


文章作者: 索冀峰
文章链接: http://suojifeng.xyz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 索冀峰 !
  目录