Redis

Redis 是一个开源、基于内存、使用 C 语言编写的 key-value 数据库,并提供了多种语言的 API。它的数据结构十分丰富,基础数据类型包括:string(字符串)、list(列表,双向链表)、hash(散列,键值对集合)、set(集合,不重复)和 sorted set(有序集合)。主要可以用于数据库、缓存、分布式锁、消息队列等…

核心内容

单线程

首先要明确的是 Redis 单线程指的是网络 IO键值对读写是由一个线程来完成的,但 Redis 持久化、集群数据等是由额外的线程执行的。

IO 多路复用机制:使其在网络 IO 操作中能并发处理大量的客户端请求从而实现高吞吐率

Redis 是基于内存的,绝大部分请求都是内存操作,十分的迅速;

Redis 具有高效的底层数据结构,为优化内存,对每种类型基本都有两种底层实现方式;

主要执行过程是单线程,避免了不必要的上下文切换和资源竞争,不存在多线程导致的 CPU 切换和锁的问题;

哨兵

哨兵会按照在线状态、网络状态,筛选过滤掉一部分不符合要求的从库,然后,依次按照优先级、复制进度、ID 号大小再对剩余的从库进行打分,只要有得分最高的从库出现,就把它选为新主库。

哨兵之间使用 pub/sub 交换信息. __sentinel__:hello

保证所有哨兵实例的配置是一致的 (达成共识的必要条件), down-after-miliseconds

MISC

  • 当使用 String 保存 i64 时,Redis 会把它保存为一个 8 字节的 Long 类型整数 (int 编码方式); 当保存的数据中包含字符串是, 会使用 SDS 结构体.

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

  • Redis 主线程 fork 创建 bgrewriteaof 子进程时, 内核需要创建用于管理子进程的相关数据结构 (PCB). 内核要把主线程的 PCB 拷贝给子进程, 这个创建和拷贝过程由内核执行, 此时会产生阻塞. 在拷贝过程中, 子进程要拷贝父线程的页表, 这个过程的耗时和 Redis 实例的内存大小有关.
  • bgrewriteaof 子进程会和主线程共享内存. 当主线程收到新写或者修改的操作时, 主线程会申请新的内存空间, 用于保存新写或修改的数据, 如果操作的事 bigkey, 主线程可能会因为申请大空间而面临阻塞风险.
    • 操作系统在分配内存空间时, 有查找和锁的开销

使用一个 2 核 CPU、4GB 内存、500GB 磁盘的云主机运行 Redis,Redis 数据库的数据量大小差不多是 2GB。当时 Redis 主要以修改操作为主,写读比例差不多在 8:2 左右,也就是说,如果有 100 个请求,80 个请求执行的是修改操作。在这个场景下,用 RDB 做持久化有什么风险吗

内存不足的风险:Redis fork 一个 bgsave 子进程进行 RDB 写入,如果主线程再接收到写操作,就会采用写时复制。写时复制需要给写操作的数据分配新的内存空间。本问题中写的比例为 80%,那么,在持久化过程中,为了保存 80% 写操作涉及的数据,写时复制机制会在实例内存中,为这些数据再分配新内存空间,分配的内存量相当于整个实例数据量的 80%,大约是 1.6GB,这样一来,整个系统内存的使用量就接近饱和了。此时,如果实例还有大量的新 key 写入或 key 修改,云主机内存很快就会被吃光。如果云主机开启了 Swap 机制,就会有一部分数据被换到磁盘上,当访问磁盘上的这部分数据时,性能会急剧下降。如果云主机没有开启 Swap,会直接触发 OOM,整个 Redis 实例会面临被系统 kill 掉的风险。

主线程和子进程竞争使用 CPU 的风险:生成 RDB 的子进程需要 CPU 核运行,主线程本身也需要 CPU 核运行,而且,如果 Redis 还启用了后台线程,此时,主线程、子进程和后台线程都会竞争 CPU 资源。由于云主机只有 2 核 CPU,这就会影响到主线程处理请求的速度。

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

判定主库“客观下线”的依据是,认为主库“主观下线”的哨兵个数要大于等于 quorum 值,现在还剩 2 个哨兵实例,个数正好等于 quorum 值,所以还能正常判断主库是否处于“客观下线”状态。如果一个哨兵想要执行主从切换,就要获到半数以上的哨兵投票赞成,也就是至少需要 3 个哨兵投票赞成。但是,现在只有 2 个哨兵了,所以就无法进行主从切换了。

References

Get Things Done
Built with Hugo
Theme Stack designed by Jimmy