Redis的优点

应用维度:数据结构应用、缓存应用、集群应用

  1. 数据类型:String(动态字符串)、List(双向链表和压缩列表)、Hash(压缩列表和哈希表)、Set(哈希表和整数数组)、Sorted Set(跳表和压缩列表)。
  2. 缓存:有过期键的淘汰策略(定时删除、定期删除、惰性删除)、有内存不够时处理策略(拒绝新写操作、淘汰旧的键)
  3. 集群:主从集群(维护多个实例之间的数据一致性)和切片集群(将一个大的实例切片成为多个小的实例)

系统维度:高性能、高可靠、高可扩展

  1. 高性能:多种数据结构,比如说压缩列表和整数数组对内存占用的优化。集合类型的
  2. 高可靠:支持AOF和RDB持久化,支持主从集群
  3. 通过切片集群可支持数据扩容

整数数组和压缩列表作为底层数据结构的优势是什么?

节省内存空间,是使用一块连续的内存就不用使用额外的指针串起元素。

Redis 基本 IO 模型中还有哪些潜在的性能瓶颈?

性能瓶颈就对应着主线程是否被阻塞,bigkey、全量返回这些耗时操作都会是性能瓶颈

AOF 重写过程中有没有其他潜在的阻塞风险?

  1. 重写会fork一个子进程,fork是由内核将主线程的PCB拷贝到子进程,是会阻塞主线程的。并且如果redis数据量大,对应的页表也会大。拷贝页表也会阻塞主线程
  2. AOF重写过程中,主线程依旧可以执行写操作。涉及到操作系统的写时复制。就是会申请一个新的内存空间,来保存新写或者修改的数据。如果这个数据过大,则主线程会因为申请大内存面临阻塞风险。

AOF 重写为什么不共享使用 AOF 本身的日志?

  1. 共享的话,重写过程中主线程可以写。而重写子进程也要写。那么就会涉及到竞争。对主线程性能造成影响。
  2. 如果重写过程失败了,可以会对这个唯一aof造成污染,无法用于恢复。

为什么主从库间的复制不使用 AOF?

  1. RDB文件是二进制文件,写磁盘或者网络传输,IO效率都比AOF高
  2. RDB恢复要比AOF快,AOF还需要执行命令

在主从切换过程中,客户端能否正常地进行请求操作呢?

主从集群一般是读写分离,对于读请求,依旧可以由从库执行。对于写操作,客户端无法执行。

:如果想要应用程序不感知服务的中断,还需要哨兵或客户端再做些什么吗?

  1. 缓存客户端的写操作
  2. 哨兵通知新主库给客户端

问题:5 个哨兵实例的集群,quorum 值设为 2。在运行过程中,如果有 3 个哨兵实例
都发生故障了,此时,Redis 主库如果有故障,还能正确地判断主库“客观下线”吗?如
果可以的话,还能进行主从库自动切换吗?

判断客观下线,是大于等于quorum个数,此时正好等于,可以判断下线。主从库自动切换,对于哨兵集群需要选举出leader。超过一半就是超过3个,此时不满足,无法正常切换。

Redis 什么时候做 rehash?

装载因子就是阈值/容量

  1. 当装载因子大于等于1,且被允许rehash的时候。就是可能是哈希表的所有桶都被装满,且此时没有AOF重写和RDB生成。
  2. 阈值大于等于5 也就是冲突很严重了,链上已经挂了很多了。此时马上会rehash

采用渐进式 hash 时,如果实例暂时没有收到新请求,是不是就不做 rehash 了?

不会,还有一个定时的任务,其中会包含rehash操作,并且这个动作会限时,保证不会影响主线程

主线程、子进程和后台线程的联系与区别

进程一般是资源分配的最小单位,拥有自己的堆、栈、虚拟空间(页表)等。而线程则是cpu进行调度的最小单位。

主线程/主进程,一个进程没有第二个线程就可以说是主线程或者主进程。

Redis fork创建的子进程:

  1. 生成RDB会调用fork创建子进程
  2. 无盘复制传输RDB创建子进程 fork
  3. AOF重写创建子进程 fork

Redis pthread_create创建的子线程:
后台线程,异步删除等

写时复制的底层实现机制

  1. 用在哪里:fork子进程 生成RDB文件时主线程依旧可以执行写操作。AOF重写
  2. 原理:子进程复制的是主线程的物理内存对应的页表。主线程执行新写或者修改操作的时候,才写入一个新的物理地址,并修改自己的页表。

replication buffer 和 repl_backlog_buffer 的区别

replication buffer是主从复制时缓存新写命令的缓存区。repl_backlog_buffer则是支持增量复制,是一块环形的缓存区。