当前位置: 首页 > 科技观察

说说Redis集群Gosisp协议和节点通信

时间:2023-03-18 14:41:15 科技观察

1.数据分片和分布算法为了应对流量并发瓶颈,方便数据迁移和扩容,数据分片是一种常见的解决方案。Kafka的分区(partition)、RocketMQ的队列(Queue)、Elasticsearch的主分片/副本(shard)、数据库分库分表等,都是采用数据分片的思想来应对高并发流量。Redis的集群模式也不例外,使用虚拟槽来实现数据分片。Redis的槽位范围是0~16383,一共16384个槽位。RedisCluster中的每个节点负责一部分slot的数量,分配算法:slot=CRC16(key)&16383。slot分配和选择示意图如下:2.Gosisp协议类型和格式1.Gosisp协议类型节点通信使用Gosisp协议。消息类型包括:ping消息、pong消息、meet消息和fail消息。MEET消息:用于新节点加入时的握手。PING消息:节点定期发送Ping消息并交换状态。PONG消息:接收meet和ping消息的响应,封装自己的状态消息。FAIL消息:当一个节点下线时,集群广播一个fail消息,其他节点收到后会更新该节点的状态。通信端口=节点端口+10000。每个节点周期性的选择几个节点发送ping报文。2、消息头格式消息头的结构在clusterMsg中,具体属性如下:fielddescriptionbriefdescriptioncharsig[4]Signature"RCmb"(RedisClustermessagebus)。signalsignatureuint32_t这条消息的总长度messagelengthuint16_tverProtocolversion,当前设置为1协议版本uint16_tportTCPbaseportnumberportinformationuint16_ttypeMessagetype消息类型,ping,meet,pong等uint16_tcount只用于某种消息消息体中包含的节点数uint64_tcurrentEpoch发送节点对应的epochepoch配置uint64_tconfigEpoch如果是master则配置epoch,如果是slave主从节点则为master最后发布的epochconfigurationuint64_toffsetMaster复制偏移量,如果节点是master,如果节点是slave,则复制偏移量copyoffsetcharsender[CLUSTER_NAMELEN]发送方节点的名称nodeId发送方节点的信息unsignedcharmyslots[CLUSTER_SLOTS/8]myslotsinfo的插槽信息发送节点charslaveof[CLUSTER_NAMELEN]从节点的nodeId信息charmyip[NET_IP_STR_LEN]发件人IP,如果不是全部清零发件人IPuint16_textensionsNumberofextensionssentalongwiththispacketextensioninformationcharnotused1[30]30字节保留供将来使用30字节保留供将来使用uint16_tpportSenderTCP明文端口,如果基本端口是TLS如果基本端口是TLS,TCP明文端口uint16_tcportSenderTCP集群总线端口发送方TCP集群总线端口uint16_tflagsSendernodeflagsSendernodeflags区分master和slave是否下线unsignedcharstateClusterstatefromthePOVofthesender从sender角度看集群状态unsignedcharmflags[3]Messageflags:CLUSTERMSG_FLAG[012]_...消息标识unionclusterMsgDatadata消息正文3.消息体格式消息体clusterMsgData结构如下:unionclusterMsgData{/*PING,MEETandPONG*/struct{/*N个clusterMsgDataGossip结构数组*/clusterMsgDataGossipgossip[1];/*可以选择为ping/meet/pong*消息发送的扩展数据。我们不能在这里明确定义它们,因为*八卦数组不是八卦数据的实际长度。*/}平;/*FAIL*/struct{clusterMsgDataFail关于;}失败;/*发布*/struct{clusterMsgDataPublishmsg;}发布左右;/*更新*/struct{clusterMsgDataUpdatenodecfg;}更新;/*MODULE*/struct{clusterMsgModulemsg;}模块;};注:clusterMsgDataGossip:PING、MEET、PONG使用的消息结构,具体如下typedefstruct{charnodename[CLUSTER_NAMELEN];uint32_tping_sent;uint32_tpong_received;字符IP[NET_IP_STR_LEN];/*上次看到的IP地址*/uint16_tport;/*上次看到的基端口*/uint16_tcport;/*上次看到的集群端口*/uint16_tflags;/*node->flagscopy*/uint16_tpport;/*纯文本端口,当基本端口为TLS时*/uint16_tnotused1;}clusterMsgDataGossip;节点发送ping报文的时间pong_received:节点收到最后一条pong报文的时间ip/port/cport/flags/pport:IP端口和节点标识三、节点选择和通信过程1、节点通信过程两个节点发送MEET/PING消息,回复PONG消息的过程如下。2、通信节点选择Gosisp协议PING/PONG通信时,应该选择哪个节点发起通信?每秒从本地实例列表中选择5个节点,从这5个节点中选择最长时间未通信的实例,向该实例发送PING报文。为避免某些实例节点始终无法被选中,会有计划任务扫描的备份措施。集群以每秒10次的固定频率扫描本地缓存节点列表,即每100ms扫描一次。如果节点:PONG更新时间>(cluster-node-timeout/2)立即向该节点发送PING消息。cluster-node-timeout为判断实例故障的心跳超时时间,默认为15秒。