Redis源码、面试指南(5)多机数据库、复制、哨兵、集群(下)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis源码、面试指南(5)多机数据库、复制、哨兵、集群

Redis源码、面试指南(5)多机数据库、复制、哨兵、集群(上):https://developer.aliyun.com/article/1508247


初始化Sentinel

主要有以下四个步骤:

·初始化服务器:sentinel本身就是一个运行在特殊模式下的Redis服务器

sentinel和普通Redis服务器的区别如下:

·使用sentinel专用代码:将不会使用普通服务器的一些代码;


·初始化sentinel状态,包括监视的主服务器IPport等(读取配置文件);


·创建与监视服务器的网络连接:一个是命令连接,负责跟主服务器进行命令交互;二是订阅连接,获取服务器的_sentinel_:hello频道(心跳检测?);

获取主从服务器信息

在建立连接之后,sentinel会默认10s通过INFO命令获取主/从服务器的返回消息。

注:sentinel一开始连接的是主服务器,当发现其有新的从服务器时,就会创建它的实例(flags为SRI_MASTER)并建立连接并订阅。

·获取主服务器信息:

一方面是关于主服务器本身的信息,包括run_id域记录的服务器运行ID,以及role域记录的服务器角色(主/从);

另一方面是关于主服务器属下所有从服务器的信息,每个从服务器都由一个"slave"字符串开头的行记录,每行的ip=域记录了从服务器的IP地址,而port=域则记录了从服务器的端口号。根据这些IP地址和端口号,Sentinel无须用户提供从服务器的地址信息,就可以自动发现从服务器

sentinel会通过这些信息更新主服务器的实例结构。


·从服务器信息:


从服务器的运行ID run_id。


从服务器的角色role。


主服务器的IP地址master_host,以及主服务器的端口号master_port。主从服务器的连接状态master_link_status。

从服务器的优先级s1ave_priority(跟后续选举有关)

从服务器的复制偏移量slave repl offset.

sentinel会通过这些信息更新主服务器的实例结构。

跟主从服务器交互

sentinel会默认两秒一次通过命令连接向监视的主从服务器发送命令:


PUBLTSHsentinel__:hello"<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,,"


这些命令主要是为了保持两者的连接,并确定信息的正确。

除此之外,sentinel还会通过订阅的sentine_:hello频道向连接的服务器发送信息。

并且这个频道信息是所有sentinel共享的,其他的sentinel会据此来更新自己的实例信息。


检查下线

分为检测主观/客观下线状态。


·主观下线:默认每秒一次向所有实例发送PING,根据服务器返回的回复/或者断线时长来判断是否掉线。


注:多个sentinel的down-after-milliseconds可能不同,只有设置最长间隔的sentinel判断为下线,那才是真正的下线。

·客观下线:这正是上一点提到的:不同的sentinel的设置时长或是判断不一致,因此当某一个sentinel认为某一个服务器下线以后(主观下线),他会不停地询问“该服务器是否已下线”,当接收到足够数量(可配置)的下线判断后,才会将服务器认为真正的客观下线,并对从服务器执行客观转移

注:客观下线是在主观下线的基础上进行的。

故障转移

故障转移主要分为两个步骤:

·选举领头sentinel,当主服务器被判断为客观下线之后,监视这个下线服务器的各个sentinel会进行协商(广播给其他sentinel),选举一个领头sentinel,由它来进行故障转移,这个过程主要有以下规则

(仔细领会)一个配置纪元内最多只能有一个领头sentinel、每个sentinel都有资格、每次进行选举不管结果如何配置纪元(configuration epoch)加一(没有啥用)、同一个配置纪元内所有sentinel都有且仅有一次将**某sentinel设为局部领头的机会、**发现主服务器客观下线的sentinel都会要求同伴将它设为局部领头、要求设为局部领头是先到先得、被大于一半的的sentinel设为局部领头那就是全局领头、给定时限内没选出来那就重来一次。


·故障转移:选出领头的sentienl之后,由领头的进行故障转移,主要包括三个步骤,见下图:

集群

源码参加cluster.c。

集群其实就是运行多个Redis实例,跟分布式不同的是,集群相当于增加硬件资源来使得整个系统性能更好(利用负载均衡),而分布式则是各个部分之间分门别类,各司其职,IPC通信。

Redis启动时都是一个个单机,当使用CLUSTER MEET命令之后,对应的Redis实例就会握手,从而成为一个集群。

指派哈希槽

Redis集群的数据分配是以一种叫做hash槽的方式分派的,具有极大的灵活性,可以自由配置。Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽( slot ),数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽。

当16384个槽都被分配出去的时候,整个集群才是上线状态,否则处于下线(fail)状态。

可以通过CLUSTER ADDSLOTS来进行槽的分配。

每个cluster的槽信息是由clusternode中的slots信息来记录,其实就是一个数组:

集群中的每个节点都会将自己的slots数组通过消息发送给集群中的其他节点,并且每个接收到slots数组的节点都会将数组保存到相应节点的clusterNode结构里面,因此,集群中的每个节点都会知道数据库中的16384个槽分别被指派给了集群中的哪些节点

注:每个集群节点会在clusterstate结构中的slots数组(这里是cluster *slots[],之前节点自身是

unsigned char slots[])中记录16384槽的指派信息(这样就不用去遍历了,而是直达对应的节点),如果为NULL说明未指派,若不为NULL,其中存储了对应的IPport等信息。

集群中如何执行命令

客户端执行命令的关键是计算当前命令应该对应哪个集群节点,见下:

·计算键处于哪个槽:

def slot__number (key):
    return CRC1 6 (key)&16383

·判断该槽在哪个节点

通过clusterstate.slots数组来判断是否是当前节点自身,不是则指明客户端重定向MOVDE错误。

注:集群模式下不会打印出MOVED错误,单机Redis才会,因为它不懂。

注:集群模式下只能使用0号数据库

重新分片

Redis集群可以在线重分片,这是由其集群管理软件redis-trib负责执行的,重分配过程见下:


注:在重新分片期间,有这样一种情形:被迁移槽的一部分键值对在源节点,而另一部分在目标节点中,那么这时如果客户端执行一个命令,该如何处理呢?


注:ASK错误跟MOVED命令一样,集群自动操作并隐藏。两者的区别:


1)MOVED错误代表槽的负责权已经从一个节点转移到了另一个节点:在客户端收到关于槽i的MOVED错误之后,客户端每次遇到关于槽i的命令请求时,都可以直接将命令请求发送至MOVED错误所指向的节点,因为该节点就是目前负责槽i的节点。


2)与此相反,ASK错误只是两个节点在迁移槽的过程中使用的一种临时措施:在客户端收到关于槽i的ASK错误之后,客户端只会在接下来的一次命令请求中将关丁槽i的命令请求发送至ASK错误所指示的节点,但这种转向不会对客户端今后发送关于槽i的命令请求产生任何影响,客户端仍然会将关于槽i的命令请求发送至目前负责处理槽i的节点,除非ASK错误再次出现。

故障转移

集群中的节点分为主节点和从节点,主节点处理槽,从节点复制主节点并在主节点宕机下线后替代该主节点。如以下的这个集群,7004和7005是两个从节点,复制节点7000的数据状态。


若节点7000因错误下线,这时尚在运行的主节点7001、7002、7003就会从7004、7005中选出一个从节点来作为主节点。就算节点7000重新上线,也是作为新主节点的从节点。


集群中的每个节点都会定期地向集群中的**其他节点发送PING消息,**以此来检测对方是否在线,如果接收PING消息的节点没有在规定的时间内,向发送PING消息的节点返回PONG消息,那么发送PING消息的节点就会将接收PING消息的节点标记为疑似下线( probable fail,PFAIL)。


当超过一半的节点都认为某节点疑似下线时,将某节点标记为已下线并向全集群广播。而后开始执行故障转移,主要有以下几个步骤。


1)从下线主节点的所有从节点里面选一个。


2)被选中的从节点会执行SLAVEOF no one命令,成为新的主节点。


3)新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。


4)新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。


5)新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。


从节点的选举是这样的,当从节点接收到自己的主节点FAIL的消息时,它就会向集群广播消息,每一个主节点都可以对其进行投票。在每一个配置纪元中,当某一个从节点的支持者大于N/2时,它即被选中成为新的主节点,进行后续的操作。


3)新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己。


4)新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。


5)新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。


从节点的选举是这样的,当从节点接收到自己的主节点FAIL的消息时,它就会向集群广播消息,每一个主节点都可以对其进行投票。在每一个配置纪元中,当某一个从节点的支持者大于N/2时,它即被选中成为新的主节点,进行后续的操作。


以上的选举过程跟哨兵sentinel的选举很相似,都是基于Raft算法的领头选举方法。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
77 2
|
4天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
1月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
23天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
44 2
|
1月前
|
存储 数据库
快速搭建南大通用GBase 8s数据库SSC共享存储集群
本文介绍如何GBase8s 数据库 在单机环境中快速部署SSC共享存储集群,涵盖准备工作、安装数据库、创建环境变量文件、准备数据存储目录、修改sqlhost、设置onconfig、搭建sds集群及集群检查等步骤,助你轻松完成集群功能验证。
|
29天前
|
Shell 数据库
GBase8a 数据库新集群第一次创建dblink
GBase8a 数据库新集群第一次创建dblink
|
29天前
|
SQL 数据库
GBase8a 数据库集群v953扩容案例问题分享
GBase8a 数据库集群v953扩容案例问题分享
|
1月前
|
存储 缓存 网络安全
南大通用GBase 8s 数据库 RHAC集群基本原理和搭建步骤
南大通用GBase 8s 数据库 RHAC集群基本原理和搭建步骤
|
1月前
|
存储 关系型数据库 数据库
【赵渝强老师】PostgreSQL的数据库集群
PostgreSQL的逻辑存储结构涵盖了数据库集群、数据库、表、索引、视图等对象,每个对象都有唯一的oid标识。数据库集群是由单个PostgreSQL实例管理的所有数据库集合,共享同一配置和资源。集群的数据存储在一个称为数据目录的单一目录中,可通过-D选项或PGDATA环境变量指定。
|
1月前
|
存储 NoSQL 算法
阿里面试:亿级 redis 排行榜,如何设计?
本文由40岁老架构师尼恩撰写,针对近期读者在一线互联网企业面试中遇到的高频面试题进行系统化梳理,如使用ZSET排序统计、亿级用户排行榜设计等。文章详细介绍了Redis的四大统计(基数统计、二值统计、排序统计、聚合统计)原理和应用场景,重点讲解了Redis有序集合(Sorted Set)的使用方法和命令,以及如何设计社交点赞系统和游戏玩家排行榜。此外,还探讨了超高并发下Redis热key分治原理、亿级用户排行榜的范围分片设计、Redis Cluster集群持久化方式等内容。文章最后提供了大量面试真题和解决方案,帮助读者提升技术实力,顺利通过面试。