1. 什么是Redis,具有哪些特点?

    Redis是一个基于内存的数据库,读写速度非常快,通常被用作缓存、消息队列、分布式锁和键值存储数据库。它还支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等,Redis还提供了分布式特性,可以将数据分布在多个节点上,以提高可扩展性和可用性。

  2. Redis的数据类型?有哪些使用场景?

    Redis常见的数据类型有:String(字符串)、Hash(哈希表)、List(列表)、Set(集合)、Zset(有序集合)

    • 字符串:存储字符串数据,也可以存储整数、浮点数,是最基本的数据类型,常用于缓存对象、常规计数、分布式锁、共享Session信息等;
    • 哈希表:存储字段和值的映射,常用于缓存对象、购物车等;
    • 列表:存储有序的字符串元素,常用于消息队列(有两个问题:1. ⽣产者需要自行实现全局唯⼀ ID;2. 不能以消费组形式消费数据);
    • 集合:存储无序不重复的字符串元素,常用于聚合运算场景(并集、交集、差集),如点赞、共同关注、抽奖活动;
    • 有序集合:类似于集合,但是可以根据元素所关联的分数进行排序,常用于排序场景,如排行榜。

    随着Redis版本更新,又更新了这些数据类型:

    • BitMap:存储位的数据结构,可以处理一些位运算操作,比如签到、登录状态等;
    • HyperLogLog:用于基数估算的数据结构,用于统计元素的唯⼀数量,如海量数据基数统计的场景;
    • GEO:存储地理位置信息的数据结构;
    • Stream:专门为消息队列设计的数据类型。
  3. Redis持久化机制有哪些?

    • AOF日志:每次执行一条写操作指令,就把该指令以追加的方式写入到一个文件里;
    • RDB快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
    • 混合持久化方式:集成了前两种的优点。(AOF优点是服务器宕机时丢失数据少,但是数据恢复不够快;RDB的优点是数据恢复快,但是保存快照的频率不好把握,频率高会影响新能,频率低会丢失的数据较多。)
  4. 混合持久化如何实现的?

    混合持久化工作在 AOF 日志重写过程。在 AOF 重写日志时,fork出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件,然后主线程处理的操作命令会被记录在重写缓冲区里,重写缓冲区里的增量命令会以AOF 方式写入到 AOF 文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的AOF 文件。文件的前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据。

    总结:首先将内存的数据以RDB的方式写入到AOF文件,而后续主线程的写操作命令会被记录到重写缓冲区,重写缓冲区里的增量命令会以AOF 方式写入到 AOF 文件,最后前半部分是RDB格式的全量数据、后半部分是AOF格式的增量数据的AOF文件再持久化到磁盘上。

  5. AOF的三种写回策略?

    Always、Everysec和No,这三种策略的可靠性是从高到低,而性能是从低到高。

    Always是每次写操作命令执行完后,同步将AOF日志数据写回磁盘;Always每次写操作命令执行完后,先将命令写入到AOF文件的内核缓冲区,然后每隔一秒将缓冲区的内容写回磁盘;No就是不控制写回磁盘的时机。每次写操作命令执行完后,先将写操作命令写入到AOF文件的内核缓冲区,再由操作系统决定何时将缓冲区的内容写回磁盘。

  6. Redis集群模式有哪些/Redis有哪些部署方案?哨兵模式的功能?

    • 主从复制:将一个Redis实例的数据复制到其他实例,其中一个是主节点(master),其余是从节点(slave)。主节点将写操作传播到所有从节点。
    • 哨兵(Sentinel):监控Redis实例的状态,发现主节点故障时,自动进行故障转移。
    • 切片集群(Cluster):将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖。

    Redis哨兵用于监控Redis实例的状态,发现主节点的故障并自动进行故障转移。

    • 监控:监控Redis主服务器和从服务器的状态,包括连接状态、是否能够执行命令、是否有持久性问题等。
    • 故障转移:当哨兵(sentinel)发现主服务器不可用时(例如宕机),它会通过一定的选举机制选择一个从服务器升级为新的主服务器。
    • 通知:哨兵(sentinel)在选举完新的主服务器后,通知其他从服务器将其切换到新的主服务器。
  7. 哨兵的工作原理?

    • 判断节点是否存活:每个哨兵定期向Redis服务器发送PING命令,以检测服务器是否处于活跃状态。若哨兵在连续一定次数未收到服务器的响应,就认为该服务器主观下线。然后哨兵就会从从节点中选择一个作为主节点。

    • 选出新主节点:在发现主服务器下线后,哨兵们会协调选举一个新的主服务器。这个过程中,哨兵会考虑每个可用的从服务器,选择个作为新的主服务器,并将其他从服务器配置为复制新的主服务器。

      具体过程:

      • 选择候选从服务器:哨兵会从可用的从服务器中选择一组候选服务器,通常选择复制偏移量 (replicationoffset) 最大的从服务器。
      • 计算投票:每个哨兵为每个候选从服务器投票。投票的考量因素包括从服务器的复制偏移量、连接质量、优先级等。
      • 达成共识:哨兵们根据投票结果达成共识,选择一个从服务器作为新的主服务器。这通常需要获得多数哨兵的同意。
    • 更新配置信息:一旦新的主服务器被选出,哨兵会更新 Redis 集群的配置信息,包括将新的主服务器的地址和端口通知给其他哨兵和客户端。

    • 通知客户端:哨兵会向客户端发送通知,告知客户端新的主服务器的位置,以便客户端能够重新连接。

  8. Redis过期删除策略有哪些?

    • 定时删除:设置key的过期时间,当时间到达时,自动执行key的删除操作。
    • 惰性删除:每次从数据库访问 key 时,都检测 key 是否过期,如果过期则删除该 key。
    • 定期删除:每隔一段时间随机] 从数据库中取出一定数量的 key 进行检查,并删除其中的过期key。

    Redis选择 惰性删除 + 定期删除 这两种策略配合使用。

  9. 缓存雪崩、击穿、穿透和解决办法

    image-20240326095110638

  10. 如何保证数据库和缓存的一致性?

    Cache Aside

    • 原理: 先从缓存中读取数据,如果没有就再去数据库里面读数据,然后把数据放回缓存中,如果缓存中可以找到数据就直接返回数据,更新数据的时候先把数据持久化到数据库,然后再让缓存失效。

    • 问题: 假如有两个操作一个更新一个查询,第一个操作先更新数据库,还没来及删除数据库,查询操作可能拿到的就是旧的数据,更新操作马上让缓存失效了,所以后续的查询可以保证数据的一致性;还有的问题就是有一个是读操作没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,也会造成脏数据。

    • 可行性: 出现上述问题的概率其实非常低,需要同时达成读缓存时缓存失效并且有并发写的操作。数据库读写要比缓存慢得多,所以读操作在写操作之前进入数据库,并目在写操作之后更新,概率比较低。

    Read/Write Through

    • 原理: Read/Write Through原理是把更新数据库(Repository) 的操作由缓存代理,应用认为后端是一个单一的存储,而存储自己维护自己的缓存。

    • Read Through: 就是在查询操作中更新缓存,也就是说,当缓存失效的时候,Cache Aside策略是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对调用方是透明的。

    • Write Through: 当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由缓存自己更新数据库 (这是一个同步操作)

    Write Behind

    • 原理: 在更新数据的时候,只更新缓存,不更新数据库,而缓存会异步地批量更新数据库。这个设计的好处就是让数据的I/O操作非常快,带来的问题是,数据不是强一致性的,而且可能会丢。

    • 第二步失效问题: 这种可能性极小,缓存删除只是标记一下无效的软删除,可以看作不耗时间。如果会出问题,一般程序在写数据库那里就没有完成: 故意在写完数据库后,休眠很长时间再来删除缓存。