Redis面试

Redis 中的内存淘汰策略,并提供几个常见的策略示例

内存淘汰策略用于在内存限制达到时,决定如何删除数据以释放内存空间。

  • LRU(Least Recently Used,最近最少使用):根据键的最近使用时间进行淘汰,优先淘汰最长时间未被使用的键。

  • LFU(Least Frequently Used,最不经常使用):根据键的使用频率进行淘汰,优先淘汰使用频率最低的键。

  • Random(随机淘汰):随机选择要淘汰的键,没有特定的规则。

  • TTL(Time To Live,生存时间):为键设置过期时间,在键过期后自动淘汰。

  • Maxmemory(最大内存限制):通过设置最大内存限制,当内存超出限制时,根据指定的淘汰策略进行淘汰。

allkeys 还是 volatile(设置了过期时间)

对于 LRU 策略:config set maxmemory-policy lru

对于 LFU 策略:config set maxmemory-policy lfu

对于 Random 策略:config set maxmemory-policy random

对于 TTL 策略:config set maxmemory-policy volatile-lru

Redis 的持久化机制,并说明主要的两种持久化方式

用于将数据写入磁盘以实现数据的持久化存储。

  • RDB(Redis DataBase)

      RDB 持久化是将 Redis 数据库中的数据以二进制快照的形式保存到磁盘上。在指定的时间间隔内,Redis 会将内存中的数据生成一个 RDB 文件。

      优点:

      缺点:

    • 数据恢复速度快,因为 RDB 文件是一个紧凑的二进制文件,可以快速加载到内存中。

    • 适合大规模数据的备份和恢复。

    • 可以在不同的 Redis 实例之间进行数据迁移。

    • 可能会丢失数据,因为 RDB 是在一定时间间隔内进行的快照,如果在这个时间间隔内发生了数据变更,这些变更可能不会被保存到 RDB 文件中。

    • 对于内存限制较小的系统,可能会因为频繁的快照操作而影响性能。

  • AOF(Append Only File)

      AOF 持久化是将 Redis 执行的所有写命令记录到一个追加式的日志文件中。当 Redis 重启时,可以通过重新执行 AOF 文件中的命令来恢复数据。

      优点:

      缺点:

    • 数据安全性高,因为 AOF 文件记录了所有的写命令,可以最大程度地保证数据不丢失。

    • 可以通过设置不同的 fsync 策略来平衡数据安全性和性能。

    • AOF 文件可能会变得很大,特别是在执行大量写命令的情况下。

    • 数据恢复速度相对较慢,因为需要重新执行 AOF 文件中的所有命令。

RDB 和 AOF 持久化可以同时启用,也可以根据需求选择其中一种。同时启用时,Redis 重启时会优先加载 AOF 文件来恢复数据。

介绍Redis事务

Redis事务,用于将多个命令打包成一个原子操作

  1. MULTI:用于开启一个事务块,表示接下来的命令都属于该事务。

  2. EXEC:用于执行事务块中的所有命令。

  3. DISCARD:用于取消当前事务,放弃事务块中的所有命令。

  4. WATCH:乐观锁,watch某个key,如果在exec前,key的值变化了,则exec失败

保证

  • 事务中的所有命令都按顺序序列化和执行。另一个客户端发送的请求永远不会在Redis事务的执行过程中提供服务。这保证了命令作为单个隔离操作执行。

  • EXEC 命令触发事务中所有命令的执行,如果在调用该命令前客户端与服务器的连接丢失,则所有操作都不会执行,而一旦调用该命令,所有操作都会执行。

可能出现的问题及应对:如果 Redis 服务器崩溃或被系统管理员强制终止,可能只有部分操作被注册,Redis 在重启时会检测到这种情况并报错,可使用 redis-check-aof 工具修复 append-only 文件以移除部分事务,使服务器能重新启动。

Redis分布式事务及其实现方式

在Redis集群中,数据被分成多个片段,在不同的节点上存储,且Redis没有全局事务控制机制。必须采取方法来处理分布式事务。

基本思路:通过协调所有相关节点的操作,实现跨节点的原子性操作。

  1. 两阶段提交(2PC)

    1. 提交请求阶段:协调器触发Transaction和询问所有参与者是否可以提交该Transaction

    2. 提交决定阶段:协调器从参与的所有节点中收集提交意见,并根据他们的反馈决定是否执行该事务。

      1. 如果有任何参与者没有投票,或者协调器收到拒绝的答案,则事务将被取消。

  2. Paxos算法

    1. 客户端向提案者发送请求,提案者将提案发送给所有接受者并等待答复。如果多数接受者认可这个提案,那么提案就可以被批准,

    2. 需要将Redis节点推荐为提案者,并使用其共识机制在集群中选择大部分意见来确定最终结果。

      1. 应用程序向一个Redis节点提出命令。

      2. Redis节点将命令广播给所有节点。

      3. 每个节点都询问其他节点,以确定是否接受该命令。

      4. 如果大多数节点(即超过半数)同意执行该命令,那么命令就被批准。

      5. 每个节点执行批准的命令。

  3. Raft算法(最终一致性)

    1. 是一种复制日志技术,用于管理可扩展的、高度可用的分布式系统。

    2. 每个服务器可以处于三种不同的状态之一:跟随者、候选人或领导者。

      1. 应用程序向Raft服务器发送命令请求。

      2. 服务器将该命令附加到其日志中,并将日志条目复制到所有其他服务器上。

      3. 多数投票的服务器将该日志附加到其日志中。

      4. 收到多数投票后,将修改应用于服务器状态机并返回状态表示成功。

  4. 分布式事务框架:使用专门的分布式事务框架,如 Seata、TCC-Transaction 等。这些框架提供了更高级的分布式事务管理功能,可以简化分布式事务的实现。

避免Redis分布式事务的方法

  1. 使用分布式锁:在执行分布式事务之前,获取一个分布式锁,确保只有一个实例能够执行事务。这样可以避免多个实例同时执行事务导致的数据不一致性。

  2. 消息队列:将事务操作发送到消息队列中,然后由一个单独的进程或线程从队列中取出操作并在 Redis 实例上执行。这样可以确保事务的顺序执行,并避免并发问题。

  3. 数据分片:将数据按照一定的规则分片到不同的 Redis 实例上,每个实例只负责处理自己分片的数据。这样可以减少分布式事务的冲突和复杂性。

实现分布式事务的方法,Redis在其中的作用

  1. 使用分布式事务协调器:可以选择使用专门的分布式事务协调器,如 Apache ZooKeeper、etcd 等。这些协调器提供了分布式锁、分布式共识等功能,可以用于实现分布式事务的原子性和一致性。

  2. 两阶段提交(2PC):在两阶段提交中,涉及到多个参与者(如数据库、服务等)。第一阶段,协调者向所有参与者发送准备请求,并等待它们的响应。如果所有参与者都准备好提交,协调者在第二阶段发送提交请求,否则发送回滚请求。

  3. 补偿事务:补偿事务是一种用于处理分布式事务失败的机制。当分布式事务中的某个操作失败时,可以执行一系列补偿操作来撤销之前的操作,以保证数据的一致性。

  4. 消息队列:可以使用消息队列来实现分布式事务的异步处理。通过将事务操作发送到消息队列中,然后由各个参与者从队列中接收并处理消息,可以实现分布式事务的最终一致性。

Redis单机集群的优缺点

单机

  • 优点

    • 简单易用:Redis单机部署相对简单,只需要启动一个Redis实例即可。

    • 低成本:单机架构不需要额外的硬件和网络资源,适用于小规模项目或者开发环境。

    • 数据一致性:由于只有一个Redis实例,数据的读写操作都在同一个节点上进行,保证了数据的一致性。

  • 缺点

    • 有限容量:单机架构的存储容量受限于单个节点的硬件资源,无法满足大规模数据存储和高并发访问的需求。

    • 单点故障:如果单机架构中的Redis实例发生故障,整个系统将无法提供服务,导致系统不可用。

    • 无法水平扩展:单机架构无法通过简单地增加节点数量来扩展存储容量和处理能力。

集群

  • 优点

    • 高可用性:Redis集群通过主从复制和故障转移机制实现高可用性。当集群中的某个节点发生故障时,其他节点可以接管服务,保证系统的可用性。

    • 扩展性:通过增加Redis集群中的节点数量,可以扩展存储容量和处理能力,满足大规模数据存储和高并发访问的需求。

    • 负载均衡:数据在集群中被分片存储在不同的节点上,实现了负载均衡,提高了系统的吞吐量和响应速度。

  • 缺点

    • 配置复杂:配置Redis集群需要考虑节点数量、数据分片策略、主从复制等因素,相对于单机架构更加复杂。

    • 集群维护:集群架构需要监控和维护多个节点,包括节点的故障检测、故障转移、数据迁移等操作。

Redis分布式锁

使用SETNX命令:Redis的SETNX命令可以将一个键值对设置到Redis中,但只有在键不存在时才会设置成功。

可以利用SETNX命令来实现分布式锁,将锁的名称作为键,将锁的持有者标识作为值。如果SETNX命令返回1,则表示获取锁成功;如果返回0,则表示锁已被其他进程持有。

设置过期时间:为了防止锁被长时间持有而导致死锁,可以为获取到的锁设置一个过期时间。可以使用Redis的EXPIRE命令或设置锁时直接指定过期时间,确保在一定时间后锁会自动释放。

释放锁:释放锁的操作非常重要,可以使用Redis的DEL命令来删除锁。释放锁时需要确保只有锁的持有者才能释放锁,可以使用Lua脚本来保证原子性。

注意事项:

加锁和释放锁的操作需要保证原子性,可以使用Redis的Lua脚本或使用RedLock等分布式锁库来实现。

需要考虑锁的可重入性,即同一个线程可以多次获取同一个锁。

锁的粒度要合理,尽量将锁的范围缩小到最小,避免锁的竞争过大。

考虑锁的可靠性,例如处理锁的异常情况、宕机恢复等。

在高并发场景下,使用分布式锁可能会引起性能问题,需要进行性能测试和优化。

redis的缓存击穿、穿透、雪崩

  1. 缓存击穿:

    1. 问题描述:当热点数据的缓存过期或被删除时,大量的并发请求同时访问该数据,直接绕过缓存访问数据库,导致数据库压力瞬间增大。

    2. 解决方案:

      • 设置热点数据永不过期,或者在缓存过期前提前更新缓存。

      • 使用互斥锁或分布式锁,在并发请求中只有一个请求能够获取锁并查询数据库,其他请求等待锁释放后从缓存中获取数据。

  2. 缓存穿透:

    1. 问题描述:查询一个不存在的数据时,缓存中没有该数据,导致所有请求都直接访问数据库,数据库中也没有该数据,从而导致数据库查询为空。

    2. 解决方案:

      • 对于不存在的数据,可以在缓存中设置一个空对象或默认值,避免每次都查询数据库。

      • 使用布隆过滤器,在查询数据库之前先检查数据是否存在,避免无效的数据库查询。

  3. 缓存雪崩:

    1. 问题描述:当缓存中的大量数据同时过期或失效时,导致大量的请求直接访问数据库,数据库压力瞬间增大,甚至可能导致数据库崩溃。

    2. 解决方案:

      • 合理设置缓存的过期时间,避免大量数据同时过期。

      • 可以采用多级缓存,如本地缓存和分布式缓存,增加缓存的层次和冗余度。

      • 当缓存失效时,可以使用降级策略,返回默认数据或降级页面,避免数据库压力过大。

布隆过滤器的原理

Redis过期策略

Redis是一个高性能的内存数据库,支持多种数据结构和丰富的功能。其中,Redis的过期策略是一个重要的特性,用于自动删除过期的键,释放内存空间。

  • 被动过期(Passive Expiration)

当客户端访问一个键时,Redis会检查该键是否已过期。如果已过期,则删除该键并返回空值。

优点是节省CPU资源,只有在访问键时才进行过期检查。

缺点是可能存在过期键未被及时删除,占用内存空间。

  • 主动过期(Active Expiration)

Redis会定期随机抽取一些键进行过期检查,如果发现过期键则删除。

优点是可以及时删除过期键,释放内存空间。

缺点是会占用一定的CPU资源进行过期检查。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值