【.com原稿】上一篇我们讲解了Redissentry的工作原理。主要是针对单节点容量、并发问题、线性可扩展性的解决方案。图片来自Pexels。在这篇文章中,我将讲解Redis集群的工作原理。文末有你要搭建的SSH后台!本文主要围绕以下几个方面介绍集群:集群介绍集群功能配置集群手动和自动故障转移故障转移的原理本文实现环境:CentOS7.3Redis4.0Redis工作目录/usr/local/redis所有操作均模拟在虚拟机集群介绍集群是为了解决主从复制中单机内存上限和并发的问题,假设你当前的云服务内存是256GB,当达到这个内存的时候,Redis就不能再提供服务了。同时,如果数据量能达到这个点,那么写入的数据量也会很大,容易造成缓冲区溢出,导致slave节点进行无限制的全量复制,导致master失效和奴隶正常工作。那么我们需要将单机的主从模式改为多对多,所有的主节点都会连接起来相互通信。这种方式既可以共享单机内存,又可以分发请求,提高系统的可用性。如下图:当有大量请求写入时,不再向一个master节点发送单条指令,而是将指令分发给各个master节点共享内存,避免大量请求.那么指令是如何分发和存储的呢?我们需要在集群存储结构中找出来。集群功能集群的功能如下:分配单机的存储容量,同时可以方便地进行扩展。分散单机的访问请求。提高系统可用性。如何理解提高系统可用性这句话,我们看下图。当master1宕机时,对系统的影响不会那么大,仍然可以提供正常的服务。这时候有人会问了,master1宕机了,此时集群是怎么工作的呢?这个问题会在下面的failover中得到解答,这个问题会在原理章节详细解释。集群存储结构存储结构单机存储是在用户发起请求时,直接将key存储在自己的内存中。集群的存储结构并不是那么简单。首先,当用户发起按键命令时,需要做的事情如下:通过CRC16(key)计算出一个值。将这个值对16384取模将得到一个值,我们最初认为它是28。此值28是保存密钥的空间位置。那么现在的问题是,这个key应该存放在哪个Redis存储空间呢?实际上Redis在集群启动后已经将存储空间分成了16384份,每台主机保存一份。这里需要注意的是,我给每个Redis存储空间的编号相当于一个小的存储空间(技术术语“哈希槽”)。你可以把它理解为建筑物中的数字。一个建筑物就是Redis的整个存储空间。每个房子的数量相当于一个存储空间。这个存储空间会有一定的区域存放对应的key,不是上图取模后的位置。箭头所指的28表示这个区域会存放28个,而这个房子可能会存放29、30、31等。此时,问题来了,增减一台机器怎么办?看图说话,尽量不要用文字用图解释。添加新机器后,将从其他三个存储空间中分配某个插槽给新机器。在这里您可以设置要在新机器中放置多少个插槽。同理,减少一台机器后,移除的slot会重新分配给其他已有的机器,就像增加新的节点一样,可以指定接收slot的节点。所谓增加节点或移除节点,就是改变存储槽的位置。了解了集群的存储结构之后,我们还需要解释另外一个问题。集群如何设计内部通信?当一个值来的时候,获取一个key,从哪里获取数据呢?按照这个问题,我们将看到以下内容。通信设计集群中的每个节点都会在一定时间内向其他节点发送ping报文,其他节点会返回pong作为响应。一段时间后,所有节点都会知道集群中所有节点的slot信息。如果下图中有3个节点,那么16384个hashslot就会被分成三份。分别是:0-55005501-1100011001-16384当用户发起密钥请求时,集群如何处理该请求?上图中的黑框代表了集群中所有节点的slot信息,里面还有很多其他的信息。如图所示,用户发起一个key请求,Redis收到key后会计算出key的slot位置,然后根据slot位置找到对应的节点。如果访问的slot在节点本身,那么直接返回key对应的数据。否则返回移动重定向错误,将正确的节点返回给客户端。然后重新发送key命令,如下图:配置集群①修改配置文件,如下图所示:只需要注意圆圈中的配置信息即可:cluster-enabledyes:开启集群模式。cluster-config-filenodes-6379.conf:集群配置文件。clustre-node-timeout10000:节点超时时间,这里为了测试方便设置为10s。②构建6个节点的配置文件并全部启动,为你提供一个方便替换文件的命令:sed's/6379/6380/g'6379-redis.conf>6380-redis.conf这样创建6个节点的配置文件不同端口的:随便打开一个配置文件查看,检查是否替换成功:为了方便查看日志信息,全部使用前台启动。并检查服务是否正常启动。执行命令:ps-ef|grepredis,可以看到启动后多了一个集群标识,代表都是集群的一个节点。所有节点都已经启动,集群启动说明需要基于Ruby(我用的是Redis4.0版本),然后一起安装。③安装Ruby,执行命令:wgethttps://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.gz解压(根据你下载的版本解压):tar-xvzfruby-2.7.1.tar.gz安装:./configure|make|makeinstall这三个命令一气呵成,查看ruby和gem版本:ruby-v。④启动集群集群的执行命令在/usr/local/redis/src/redis-trib.rb。注意,如果需要直接使用redis-trib.rb命令,需要ln到bin目录下,否则必须使用./redis-trib.rb方式。如果按照步骤操作的话,这里会报错,如下图:执行geminstallredis,不幸的是这里也会报错:然后需要安装yuminstallzlib-devel和yuminstallopenssl-devel.安装完成后,分别在/ruby-2.7.1/ext/openssl和/ruby-2.7.1/ext/zlib中执行rubyextconf.rb,执行make|进行安装。然后执行geminstallredis就OK了:然后回去执行:./redis-trib.rbcreate--replicas1127.0.0.1:6379127.0.0.1:6380127.0.0.1:6381127.0.0.1:6382127.0.0.1:6383127.0.0.1:6384信息解读:创建集群并为6个节点分配哈希槽,并将后三个节点配置为前三个节点的从节点。显示每个节点的哈希槽信息和节点ID。最后一步需要输入yes:进入data目录查看配置文件的变化。配置文件的主要信息是分配给每个master节点的slot:查看host节点的运行日志:这里给出的主要信息是clusterstatuschanged:ok集群状态正常。⑤集群设置和数据获取直接设置数据会报错,namekey转换后的slot位置为5798,并给出ip地址和端口号。您需要使用命令redis-cli-c。设置值时,会提示重定向到5798的slot。接下来,获取数据,自动切换节点:Failover①集群从节点下线。根据上面的集群启动信息,我们知道6383端口是6379的从节点,接下来让6383下线查看6379的日志信息,6379会报6383连接丢失,会被标记为失败,表示它不可用。此时集群还在正常工作。总结:从节点下线对集群没有影响。当6383端口在线时,所有节点都会清除fail标记,如下图:②集群主节点下线,主节点6379手动下线。查看slave节点6383的日志信息,此时6383节点会继续连接6379,总共10次,为什么是10次?是根据我们配置的参数cluster-node-timeout10来决定的,这里是我们每秒钟连接一次的消息。时间到期后,故障转移开始。此时6383在failover选举中胜任,变身slavesing成为master节点。此时查看集群的节点信息,命令clusternodes。你会发现这里有四个master节点,但是其中一个master节点下线了:6379原来的master节点上线了:6379上线后,所有节点也会清除fail信息。而节点信息也会发生变化,此时6379变为6383的从节点。③为新的master节点添加两个新的端口6385和6386:执行新命令./redis-trib.rbadd-node127.0.0.1:6385127.0.0.1:6379,meetmessage发送到这里。执行add-node命令,第一个参数是新节点的ip+port,第二个参数是现有集群中的节点。根据下图,我们可以看到集群中已经存在新添加的节点。注意:虽然6385成为了集群中的一个节点,但它与其他节点不同。它没有数据,即没有哈希槽。接下来,我们需要将集群中的一些哈希槽分配给这个新节点。分配完成后,该节点将成为真正的主节点。执行命令./redis-trib.rbreshard127.0.0.1:6385,会提示转移多少个哈希槽,填写接收节点的id。最后一步询问是否从所有节点转账:我用all。使用命令:clusternodes查看,6385节点已经有三个范围的哈希槽。已添加主节点。接下来需要为主节点6385配置一个从节点6386,命令如下:./redis-trib.rbadd-node--slave--master-iddcc0ec4d0c932ac5c35ae76af4f9c5d27a422d9f127.0.0.1:6386127.0.0.1:6385master-id是6385的id,第一个参数是新节点的ip+port,第二个是指定master节点的ip+port。④手动故障转移当集群中的主节点要升级时,可以手动故障转移到从节点,避免影响集群的可用性。在从节点上执行命令:clusterfailover。执行过程:查看节点信息,可以看到节点6386已经成为宿主点。向从节点发送集群故障转移命令后,从节点会向主节点发送CLUSTERMSG_TYPE_MFSTART数据包。从节点请求主节点停止访问,从而比较两者之间的数据偏移量以达到一致性。这个时候client就不会连接到我们淘汰的master节点了。同时,主节点将复制偏移量发送给从节点。从节点获得复制偏移量后,故障转移开始,然后通知主节点切换配置。当客户端在旧主节点上解锁后,重新连接到新主节点。故障转移的原理在上面的文章中,我们测试了故障转移。主节点下线后,从节点成为主节点。接下来,我们分析这个过程。①从故障发现到确认,集群中的每个节点都会周期性地向其他节点发送ping报文,接收方回复pong。如果ping报文在cluster-node-timeout时间内一直失败,接收方节点将被标记为pfail状态,即主观下线。这种离线状态是不是很熟悉?是的,这有点类似于哨兵判断主节点是否异常。当哨兵发现主节点出现问题时,它也会客观地将主节点标记为下线(s_down)。突然发现我跑题了,尴尬……再提一下哨兵。当一个sentinel认为master节点异常时,就标记主观下线,但是其他sentinel怎么可能同意呢?你不能说你说的。他们会尝试连接异常的主节点。当超过半数哨兵认为主节点异常时,会直接让主节点客观下线。同样,集群也不会因为某个节点被判断为离线,就判断其状态为离线。节点直接通过Gossip消息传播。集群中的节点会不断收集故障节点的离线反馈,并保存在本地故障节点离线报告中。当超过一半的集群主节点被标记为主观下线时,状态变为客观下线。最后,向集群广播一条故障消息,通知所有节点将故障节点标记为客观离线。例如:节点A向节点B发送ping,在通信异常后将节点B标记为pfail,则节点A会继续向节点C发送ping,并携带节点B的pfail信息,然后节点C将将NodeB的故障保存到离线报告中。当下线报告数量大于拥有哈希槽的主节点数量的一半时,将尝试进行客观的下线尝试。②故障恢复(从节点翻身,从节点唱歌)当一个故障节点被定义为客观下线时,故障节点的所有从节点承担故障恢复的责任。故障恢复是指从节点通过定时任务发现其宿主点客观下线后,将执行故障恢复过程。资格检查:所有从节点将检查与主节点的最后连接时间。如果断开连接时间大于cluster-node-time*cluster-slave-validity-factor,它们将不符合故障转移的条件。筹备选举的时间:我来说说为什么要筹备选举的时间。如果通过资格检查后有多个从节点,则需要使用不同的延迟选举时间来支持优先级。这里的优先级是基于复制偏移量的。偏移量越大,故障主节点之间的延迟越小,更换主节点的机会就越多。主要作用是保证数据一致性最好的节点先发起选举。选举投票:Redis集群的投票机制并没有使用slave节点来进行leader选举,所以切记不要和sentinels混淆。集群的投票机制是持有slot的主机点进行投票。故障节点的从节点会向所有持有slots的主节点广播一个FAILOVER_AUTH_REQUEST包请求投票。当主节点回复FAILOVER_AUTH_ACK投票后,在NODE_TIMEOUT*2期间不能为其他从节点投票。在获得超过半数的节点投票后,故障恢复阶段开始。Failover:成功选出的slave节点取消复制成为master节点,删除失败节点的slot,将失败节点的slot委托给自己,向集群广播自己的pong消息,通知节点的host更改并接管故障节点槽信息。加分:你要的SSH后台是一篇用了两个晚上完成的Redis哨兵文章,但是你的关注点不在文章本身,啊!小编很郁闷。。。为了满足大家的要求,勉强告诉大家怎么设置高亮背景,我用的工具是xsheel。打开工具选择选项:然后看到有窗口透明就可以设置xsheel透明了。这是正确的!没错,这就是桌面背景,准备好开始设置了吗?最后,欢迎各位大神给予技术补充,指正错误。作者:Kaka简介:工作三年,从平淡无奇的生活变成了现在的“单身”生活。当然,这个订单不是单单!虽然技术学习要求极高,但远远不能满足客户千奇百怪的要求。进入朝九晚六的我,虽然躲过了风吹日晒,但还是很享受那些只剩下黑眼圈的日子。坚持学习、博客、分享,是卡卡从业以来一直坚持的信念。希望卡卡在诺大网的文章能给大家带来一点帮助。编辑:陶佳龙征稿:如有意向投稿或寻求报道,请联系editor@51cto.com【原创稿件请注明原作者和出处为.com,合作网站转载】
