Redis设计与实现笔记--多机数据库(三)

1.复制

旧版复制功能实现

同步

①从服务器向主服务器发送SYNC命令

②主服务器收到SYNC后开始执行BGSAVE命令,生成RDB文件,在此期间用缓冲区记录执行的写命令

③把RDB文件发给从服务器,并载入

④把缓冲区的写命令发送给从服务器,从服务器执行,更新至主服务器当前状态

命令传播

主服务器所有写命令都会传播给从服务器

旧版本缺陷

SYNC命令是非常耗费资源的,在初次复制时能很好地完成,但在中途下线后又上线,

缺失的只是一部分信息,不需要所有资源同步,再次执行SYNC就显得低效

新版复制功能实现

2.8版本开始用PSYNC来代替SYNC

该命令有两种模式:

完整重同步,跟SYNC命令基本相同

部分重同步,处理断线后重复制情况,把断线期间没收到的命令同步

部分重同步实现

复制偏移量,重连后发送PSYNC命令,上报当前偏移量

复制积压缓冲区,固定长度先进先出的队列,默认大小为1MB

当字符需要进入满的队列时,队头的元素将弹出

当进行命令传播时,主服务器还会将写命令入队到复制积压缓冲区

如果offset+1开始的数据在复制积压缓冲区中,将进行部分重同步

复制积压缓冲区大小= 2 * 重连平均时间(s) * 每秒产生写的大小。 来保证大部分情况都能部分重同步

服务器运行ID,初次同步时,从服务器会保存主服务器的ID,重连时会发送ID给主服务器

如果ID相同,则尝试部分重同步,不相同则直接完整重同步

PSYNC命令流程

复制步骤

①发送slaveof命令后,设置主服务器的地址和端口

②建立套接字连接,从服务器是主服务器的客户端

③发送PING命令,检查套接字的读写状态是否正常,

④身份验证

⑤发送端口信息

⑥同步

⑦命令传播

 

心跳检测

从服务器默认每隔一秒向主服务器发送命令

REPLCONF ACK <replication_offset>

replication_offset是从服务器当前的复制偏移量

作用

①检测主从服务器的网络连接状态

如果超过1秒没有收到命令,说明连接出现问题

②辅助实现min-slaves配置选项

防止主服务器在不安全的情况下执行写命令

③检测命令丢失

根据偏移量检查有无丢失,后序操作跟部分重同步类似

 

2.Sentinel

 

创建与主服务器的网络连接

一个是命令连接,用于发送接收命令

另一个是订阅连接,专门用于订阅主服务器的__sentinel__:hello频道

当客户端断线为了不丢失hello频道的任何信息,就必须专门订阅该频道

创建与从服务器网络连接

默认每十秒发送一次INFO命令,获取主服务器信息

根据此信息创建与从服务器的连接

创建与其他Sentinel的命令连接

通过频道信息发现新的Sentinel,然后建立命令连接

 

检测主观下线

Sentinel默认每秒对创建了命令连接的实例发送PING命令

在down-after-milliseconds毫秒内没有收到有效信息,Sentinel会修改对应实例结构中flags属性打开

SRI_S_DOWN标识

不同Sentinel配置可能不同,对于判断主观下线时长不一样

检查客观下线

当将一个主服务器判断主观下线后,会对其他Sentinel询问,当赞成的数量超过quorum值时,

会认为已经进入客观下线状态。

不同Sentinel判断客观下线的条件可能不同,由于配置的quorum值

选举领头Sentinel

当一个主服务器判断为客观下线时,监视这个主服务器的各个Sentinel会选举出领头

选举领头规则和方法:

每个发现主服务器进入客观下线的Sentinel都会要求其他Sentinel将自己设置为局部头领

设置局部头领是先到先得,最先向目标Sentinel发送命令 将会得到目标的支持。

当目标Sentinel已经有了支持的,其他发送过来的命令会被拒绝

超过半数的Sentinel支持,则会被选举为头领Sentinel

如果在限定时间内没有选举出,在一段时间后会再次选举,直到选出为止

故障转移操作

①Sentinel系统挑选server1属下的一个从服务器,升级成主服务器

会剔除下线,断开超时,5秒内没有回复过领头Sentinel的INFO命令的从服务器

然后在剩下的从服务器中,先按服务器优先级,再按偏移量,最后按ID

为了保证保存着数据最新

②对其他server1属下的从服务器发送复制命令,称为新主服务器的从服务器

所有从服务器开始复制新的主服务器时,故障转移完毕。

③继续监视server1,上线后把它设置为新主服务器的从服务器

 

3.集群<有关分布式,比较重要>

节点

节点与节点之间建立联系

节点A会将节点B的信息通过Gossip协议传播给集群中的其他节点,与B进行握手

 

槽指派

集群通过分片来保存数据库中的键值对,分为16384(2^14)个槽,每个节点能处理0-16384个槽

所有槽都有节点在处理时,集群才处于上线状态

clusterNode中slots信息

slots数组长度为16384/8=2048个字节,包含16384个二进制位,图中表示该节点负责0-7槽

clusterState.slots数组记录了集群中所有槽的指派信息,获取槽被指派给哪个节点为O(1)

clusterNode.slots数组记录了clusterNode结构所代表的节点的槽指派信息,节点被指派的节点见图17-9

在集群中执行命令

计算键属于哪个槽

CRC(key) & 16383

CRC用于计算CRC-16校验和

判断槽是否由当前节点负责处理

如果clusterState.slots[i]等于clusterState.myself说明是当前节点负责

否则返回MOVED错误,指引去clusterState.slots[i]指向的节点

节点数据库实现

用跳跃表来保存槽和键之间的关系,用槽的编号来表示节点的score

 

重新分片

ASK错误

跟MOVED错误类似,但这个是发生在槽迁移时

客户端收到ASK错误后,会向指引的节点先发送一个ASKING命令,然后重新发送想要执行的命令

如果直接发送会被拒绝执行返回MOVED错误

ASK错误和MOVED错误区别

ASK错误只是临时转向,只限于当前发送ASK错误的命令

而MOVED错误是直接转向。

 

复制与故障转移

当半数以上负责槽处理的主节点发现某一主节点疑似下线,就会正式标为下线状态

故障转移

①下线的主节点中的所有从节点里面选出一个,跟选举领头Sentinel类似

②选出的从节点执行SLAVEOF no one,称为主节点

③把下线的主节点槽指派都指派给自己

④广播PONG消息,通知其他节点

⑤新的主节点开始接收处理跟自己负责槽相关的命令请求

 

消息

MEET消息,请求加入集群

PING消息,默认每隔一秒向已知节点中随机选出5个发送消息,检测是否在线,

长时间没有被选中也会发送PING消息,防止信息更新滞后

PONG消息,确认消息收到

FAIL消息,某节点已经下线的消息

PUBLISH消息,节点会执行这个命令,并向集群广播

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值