redis故障转移原理,以及go-redis连接集群的地址数组

目录

go-redis连接集群的配置,尤其看地址数组

redis故障转移原理

前提

一、故障模拟

三、机制解读


 

go-redis连接集群的配置,尤其看地址数组

转自:https://blog.csdn.net/pengpengzhou/article/details/105559884

	client := redis.NewClusterClient(&redis.ClusterOptions{
		//-------------------------------------------------------------------------------------------
		//集群相关的参数
 
		//集群节点地址,理论上只要填一个可用的节点客户端就可以自动获取到集群的所有节点信息。但是最好多填一些节点以增加容灾能力,因为只填一个节点的话,如果这个节点出现了异常情况,则Go应用程序在启动过程中无法获取到集群信息。
		Addrs: []string{"127.0.0.1:7000", "127.0.0.1:7001", "127.0.0.1:7002", "127.0.0.1:7003", "127.0.0.1:7004", "127.0.0.1:7005"},
 
		MaxRedirects: 8, // 当遇到网络错误或者MOVED/ASK重定向命令时,最多重试几次,默认8
 
		//只含读操作的命令的"节点选择策略"。默认都是false,即只能在主节点上执行。
		ReadOnly: false, // 置为true则允许在从节点上执行只含读操作的命令
		// 默认false。 置为true则ReadOnly自动置为true,表示在处理只读命令时,可以在一个slot对应的主节点和所有从节点中选取Ping()的响应时长最短的一个节点来读数据
		RouteByLatency: false,
		// 默认false。置为true则ReadOnly自动置为true,表示在处理只读命令时,可以在一个slot对应的主节点和所有从节点中随机挑选一个节点来读数据
		RouteRandomly: false,
 
		//用户可定制读取节点信息的函数,比如在非集群模式下可以从zookeeper读取。
		//但如果面向的是redis cluster集群,则客户端自动通过cluster slots命令从集群获取节点信息,不会用到这个函数。
		ClusterSlots: func() ([]ClusterSlot, error) {
 
		},
 
		//钩子函数,当一个新节点创建时调用,传入的参数是新建的redis.Client
		OnNewNode: func(*Client) {
 
		},
 
		//------------------------------------------------------------------------------------------------------
		//ClusterClient管理着一组redis.Client,下面的参数和非集群模式下的redis.Options参数一致,但默认值有差别。
		//初始化时,ClusterClient会把下列参数传递给每一个redis.Client
 
		//钩子函数
		//仅当客户端执行命令需要从连接池获取连接时,如果连接池需要新建连接则会调用此钩子函数
		OnConnect: func(conn *redis.Conn) error {
			fmt.Printf("conn=%v\n", conn)
			return nil
		},
 
		Password: "",
 
		//每一个redis.Client的连接池容量及闲置连接数量,而不是cluterClient总体的连接池大小。实际上没有总的连接池
		//而是由各个redis.Client自行去实现和维护各自的连接池。
		PoolSize:     15, // 连接池最大socket连接数,默认为5倍CPU数, 5 * runtime.NumCPU
		MinIdleConns: 10, //在启动阶段创建指定数量的Idle连接,并长期维持idle状态的连接数不少于指定数量;。
 
		//命令执行失败时的重试策略
		MaxRetries:      0,                      // 命令执行失败时,最多重试多少次,默认为0即不重试
		MinRetryBackoff: 8 * time.Millisecond,   //每次计算重试间隔时间的下限,默认8毫秒,-1表示取消间隔
		MaxRetryBackoff: 512 * time.Millisecond, //每次计算重试间隔时间的上限,默认512毫秒,-1表示取消间隔
 
		//超时
		DialTimeout:  5 * time.Second,     //连接建立超时时间,默认5秒。
		ReadTimeout:  3 * time.Second, //读超时,默认3秒, -1表示取消读超时
		WriteTimeout: 3 * time.Second,     //写超时,默认等于读超时,-1表示取消读超时
		PoolTimeout:  4 * time.Second,     //当所有连接都处在繁忙状态时,客户端等待可用连接的最大等待时长,默认为读超时+1秒。
 
		//闲置连接检查包括IdleTimeout,MaxConnAge
		IdleCheckFrequency: 60 * time.Second, //闲置连接检查的周期,无默认值,由ClusterClient统一对所管理的redis.Client进行闲置连接检查。初始化时传递-1给redis.Client表示redis.Client自己不用做周期性检查,只在客户端获取连接时对闲置连接进行处理。
		IdleTimeout:        5 * time.Minute,  //闲置超时,默认5分钟,-1表示取消闲置超时检查
		MaxConnAge:         0 * time.Second,  //连接存活时长,从创建开始计时,超过指定时长则关闭连接,默认为0,即不关闭存活时长较长的连接
 
	})
	defer client.Close()

尤其是:

集群节点地址,理论上只要填一个可用的节点客户端就可以自动获取到集群的所有节点信息。但是最好多填一些节点以增加容灾能力,因为只填一个节点的话,如果这个节点出现了异常情况,则Go应用程序在启动过程中无法获取到集群信息。

Addrs: []string{"127.0.0.1:7000", "127.0.0.1:7001", "127.0.0.1:7002", "127.0.0.1:7003", "127.0.0.1:7004", "127.0.0.1:7005"},

 

redis故障转移原理

转自:https://blog.csdn.net/tr1912/article/details/81265007

前提

搭建了一个如下图的三主三从的集群。

     

并且集群处于运行中

一、故障模拟

我们首先停止一个主服务,看有什么变化:

我们停止了7002主服务器:

马上会在他的从机7004服务器上看到这些

然后其他主服务器看到这些:

这里表示有一个节点down掉了,然后回收了他的哈希槽,然后选举出了一个新的master

其他从机只是标记了down掉的那台机子为访问失败

随后我们可以在down掉的那个主机器的从机上看到这些:

可以看到这个从机知道了选举的进行,并被选为了主机,至此整个选主就结束了。

然后我们再启动7002这个原主机

在看7004这个主机,发现他先把7002这个主机标记为了可达的状态,然后再和它同步数据。根据数据记录的pid

其他的机器只是把它标记为了可达的状态:

这次我们要把一个主从的两个机器都停止掉,看看是什么情况:

我们先停止7002这个从机:

他的主机:

其他机器:

然后再停止7004这个主机:

其他从机:

其他主机:

这个可以知道了,我们的节点中只要有一个分片的机能完全停止之后,整个集群就处于连接不能的状态。

然后我们先启动7002这个slave节点:

7002一直在扫描主节点

而其他节点就和之前7002恢复的时候一样,给他标记了可用的状态。

这个时候启动7004节点:

可以看到7002连接上了7004,并且同步了一波数据。

其他节点则表示这个节点恢复了连接,然后整个儿集群也都恢复了:

三、机制解读

这个就是redis的cluster的故障转移机制,redis的各个节点通过ping/pong进行消息通信,转播槽的信息和节点状态信息,故障发现也是通过这个动作发现的,他总共分为这么几步:

1.主观下线:某个节点认为另一个节点不可用,变为了下线的状态,这个是第一个实验中,首先断开7002节点的时候,7004就会马上发现7002不可达时候7004的认为的状态。

2.客观下线:指标记一个节点真正下线,集群内多个节点都认为该节点不可用的状态。如第一个实验中过了一会,其他节点都会标记7002为fail的状态。

3.故障恢复:故障节点变为客观下线后,如果下线节点是持有槽的主节点则需要在它的从节点中选出一个替换它,从而保证集群的高可用。下线主节点的所有从节点承担故障恢复的义务,当从节点通过内部定时任务发现自身复制的主节 点进入客观下线时,将会触发故障恢复流程:

1). 资格检查:每个从节点都要检查最后与主节点断线时间,判断是否有资格替换故障 的主节点。如果从节点与主节点断线时间超过cluster-node-time*cluster-slave-validity-factor,则当前从节点不具备故障转移资格。参数cluster-slavevalidity-factor用于从节点的有效因子,默认为10。

2).准备选举时间:当从节点符合故障转移资格后,更新触发故障选举的时间,只有到达该时间后才能执行后续流程。这里之所以采用延迟触发机制,主要是通过对多个从节点使用不同的延迟选举时间来支持优先级问题。复制偏移量越大说明从节点延迟越低,那么它应该具有更高的优先级来替换故障主节点。所有的从节点中复制偏移量最大的将提前触发故障选举流程。

主节点b进入客观下线后,它的三个从节点根据自身复制偏移量设置延 迟选举时间,如复制偏移量最大的节点slave b-1延迟1秒执行,保证复制延迟低的从节点优先发起选举。

3).发起选举

   当从节点定时任务检测到达故障选举时间(failover_auth_time)到达后,发起选举流程如下:

    (1).更新配置纪元:配置纪元是一个只增不减的整数,每个主节点自身维护一个配置纪元 (clusterNode.configEpoch)标示当前主节点的版本,所有主节点的配置纪元都不相等,从节点会复制主节点的配置纪元。整个集群又维护一个全局的配 置纪元(clusterState.current Epoch),用于记录集群内所有主节点配置纪元 的最大版本。执行cluster info命令可以查看配置纪元信息。只要集群发生重要的关键事件,纪元数就会增加,所以在选从的时候需要选择一个纪元数最大的从。

    (2).广播选举消息:在集群内广播选举消息(FAILOVER_AUTH_REQUEST),并记录已发送过消息的状态,保证该从节点在一个配置纪元内只能发起一次选举。消息 内容如同ping消息只是将type类型变为FAILOVER_AUTH_REQUEST。

4).选举投票:只有持有哈希槽的主节点才能参与投票,每个主节点有一票的权利,如集群内有N个主节点,那么只要有一个从节点获得了N/2+1的选票即认为胜出。

   Ps.故障主节点也算在投票数内,假设集群内节点规模是3主3从,其中有2个主节点部署在一台机器上,当这台机器宕机时,由于从节点无法收集到 3/2+1个主节点选票将导致故障转移失败。这个问题也适用于故障发现环 节。因此部署集群时所有主节点最少需要部署在3台物理机上才能避免单点问题。
        投票作废:每个配置纪元代表了一次选举周期,如果在开始投票之后的 cluster-node-timeout*2时间内从节点没有获取足够数量的投票,则本次选举作废。从节点对配置纪元自增并发起下一轮投票,直到选举成功为止。

5).替换主节点

      当从节点收集到足够的选票之后,触发替换主节点操作:

  • 当前从节点取消复制变为主节点。
  • 执行clusterDelSlot操作撤销故障主节点负责的槽,并执行 clusterAddSlot把这些槽委派给自己。
  • 向集群广播自己的pong消息,通知集群内所有的节点当前从节点变为主节点并接管了故障主节点的槽信息。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值