2-1. 键值保存在哈希表中,哈希表中保存的值具体是键和值的指针。
2-2. Redis 采用了渐进式 rehash。在第二步拷贝数据时,Redis 仍然正常处理客户端请求,每处理一个请求时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝到哈希表 2 中;等处理下一个请求时,再顺带拷贝哈希表 1 中的下一个索引位置的 entries
3-1. 单线程 Redis 为什么那么快,一方面,Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因。另一方面,就是 Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率
3-2. Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,
3-3. Redis 单线程是指它对网络 IO 和数据读写的操作采用了一个线程,而采用单线程的一个核心原因是避免多线程开发的并发控制问题。单线程的 Redis 也能获得高性能,跟多路复用的 IO 模型密切相关,因为这避免了 accept() 和 send()/recv() 潜在的网络 IO 操作阻塞点。
4-1. AOF 是写后日志,“写后”的意思是 Redis 是先执行命令,把数据写入内存
4-2. 为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错
4-3. AOF 还有一个好处:它是在命令执行后才记录日志,所以不会阻塞当前的写操作。AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。这是因为,AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了
4-4. AOF 重写机制就是在重写时,Redis 根据数据库的现状创建一个新的 AOF 文件,也就是说,读取数据库中的所有键值对,然后对每一个键值对用一条SET命令记录它的写入
4-5. 重写AOF 时,吧内存拷贝一份,子线程用拷贝的内存写AOF,期间主线程上的请求记录会被记录到AOF重写缓冲中,最后这部分缓存也会写入新的AOF日志。
5-1. Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。save:在主线程中执行,会导致阻塞;bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。
5-2. 生成RDB时的写时复制:bgsave 子线程在读取内存生成RDB时,如果主线程上来了写请求,会把需要变更的内存复制一份,在副本上修改。
5-3. Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。快照不用很频繁地执行,AOF 日志也只用记录两次快照间的操作
6-1. 主从库间如何进行第一次同步:启动多个实例,使用replicaof建立主从关系,然后数据复制要经过三个阶段,阶段一:各个节点确认主从关系。阶段二,主库bgsave生成rdb文件发给从库,同时把这期间新的写请求写入 replication buffer ,从库接到rdb文件后先删除本地数然后将rdb文件写入内存。阶段三:主库把 replication buffer 中的数据发给从库同步。
6-2. 级联结构,即 主-从-从 模式, 主库的从库可以接续有自己的从库,这样可以分担一部分主库同步数据的压力。
6-3. 主从正常同步过程中维护一个 repl_backlog_buffer 的环形内存空间,主节点记录自己写入未知的偏移量,从节点记录了自己读数据的偏移量。主从断连并恢复连接后,从库发送自己的读数据偏移量,就知道了从哪里开始继续同步。如果断连时间太长,主库已经把缓存写了一圈覆盖掉从库读取的位置了,就要进行全量同步。
7-1. 哨兵其实就是一个运行在特殊模式下的 Redis 进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。
7-2. 通常会采用多实例组成的集群模式进行部署,这也被称为哨兵集群。引入多个哨兵实例一起来判断,就可以避免单个哨兵因为自身网络状况不好,而误判主库下线的情况
7-3. “客观下线”的标准就是,当有 N 个哨兵实例时,最好要有 N/2 + 1 个实例判断主库为“主观下线”,才能最终判定主库为“客观下线
7-4. 选主,先把过去一段时间内常常断连的从库过滤掉,剩下的从空打分,有3轮,按配置的优先级,按同步进度,按id从小到大排。当某一轮选出分数最高唯一实例时,选主结束。
8-1. 哨兵实例之间可以相互发现,要归功于 Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制,哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP 和端口)。同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。然后哨兵之间互相建立连接。
8-2. 除了哨兵实例,我们自己编写的应用程序也可以通过 Redis 进行消息的发布和订阅
8-3. 哨兵给主库发送 INFO 命令,主库接受到这个命令后,就会把从库列表返回给哨兵。接着,哨兵就可以根据从库列表中的连接信息,和每个从库建立连接,并在这个连接上持续地对从库进行监控
8-4. 客户段通过订阅哨兵的频道来得知主从切换到了哪一步以及最终选出的主节点的地址信息。
8-5. 怎么选出由哪个哨兵执行通知主从切换信息的任务? 当一个哨兵判定主节点主管下线后,给其他哨兵发送 is-master-down-by-addr 命令,询问其他哨兵对主节点状态的判断情况,其他哨兵若也判断主管下线则回复Y,否则回复N,如果过回复Y的数量加上自己的一票 的值大于配置文件中配置的quorum 值,则这个哨兵就可以标记主库为“客观下线”了,此时,这个哨兵就可以再给其他哨兵发送命令,表明希望由自己来执行主从切换,并让所有其他哨兵进行投票。在投票过程中,任何一个想成为 Leader 的哨兵,要满足两个条件:第一,拿到半数以上的赞成票;第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值,就可以了。如果投票选举失败则过一段时间后再来一次。
9-1. 在切片集群中,数据需要分布在不同实例上,那么,数据和实例之间如何对应呢?这就和接下来我要讲的 Red