go-redis里,sentinel只用来获取master和从节点的ip地址,在获取master和replica节点ip时,如果sentinel不可用,那么会换其他的sentinel重试,并将可用的sentinel换到第一个
1. 用于获取master节点
-
先通过读锁获取c.sentinel,使用c.sentinel获取主节点信息
-
如果上面sentinel为空或者出错未获取到主节点,那么可能在此中间有地方重新设置了c.sentinel,继续用读写锁,使用c.sentinel获取主节点信息
-
- 分读锁和读写锁这两步的原因是,提高并发性能
-
如果以上两步的sentinel都有问题,那么遍历所有的sentinelAddr,创建sentinel进行处理
-
最后如果所有的sentinel都不可用,则报错
1.1. 核心高可用代码
1.2. 方法内所有处理逻辑
func (c *sentinelFailover) replicaAddrs(ctx context.Context, useDisconnected bool) ([]string, error) {
// 1. 先通过读锁获取c.sentinel,使用c.sentinel获取主节点信息
c.mu.RLock()
sentinel := c.sentinel
c.mu.RUnlock()
if sentinel != nil {
// 通过哨兵查询从节点
addrs, err := c.getReplicaAddrs(ctx, sentinel)
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return nil, err
}
// Continue on other errors
internal.Logger.Printf(ctx, "sentinel: Replicas name=%q failed: %s",
c.opt.MasterName, err)
} else if len(addrs) > 0 {
return addrs, nil
}
}
// 2. 如果上面sentinel为空或者出错未获取到主节点,那么可能在此中间有地方重新设置了c.sentinel,继续用读写锁,使用c.sentinel获取主节点信息
// 分读锁和读写锁这两步的原因是,提高并发性能
c.mu.Lock()
defer c.mu.Unlock()
if c.sentinel != nil {
addrs, err := c.getReplicaAddrs(ctx, c.sentinel)