通过调用NewFailoverClient函数可以创建一个能支持redis-server主从切换(sentinel模式下)的client, 基本用法如下:

redis主从节点

  • 主127.0.0.1:6388
  • 从127.0.0.1:6398

假如有3个sentinel实例依次为:127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381;sentinel的配置如下,

sentinel monitor mymaster 127.0.0.1 6388 2
sentinel down-after-milliseconds mymaster 6000
sentinel failover-timeout mymaster 18000
sentinel parallel-syncs mymaster 1

redissentinel.go 

package main

import (
        "fmt"
        "github.com/go-redis/redis"
        "time"
)

func main() {
        client := redis.NewFailoverClient(&redis.FailoverOptions{
                MasterName:    "mymaster",
                SentinelAddrs: []string{"127.0.0.1:26379", "127.0.0.1:26380", "127.0.0.1:26381"},
                Password:      "",
                DB:            0,
        })

        for {
                reply, err := client.Incr("pvcount").Result()
                fmt.Printf("reply=%v err=%v\n", reply, err)
                time.Sleep(1 * time.Second)
        }

}

实验1:redis节点主从切换 

运行redissentinel.go,并在执行过程中,shutdown redis主节点127.0.0.1:6388,可以看到在reply等于93和94之间,客户端监测到了主从切换,并重新连接到新的主节点,这段时间大致等于sentinel配置down-after-milliseconds的时长。

[root@dev example]# go run redissentinel.go
redis: 2020/10/30 00:09:53 sentinel.go:379: sentinel: discovered new sentinel="93db6069e9bde858a99b873048891912eecd45d4" for master="mymaster"
redis: 2020/10/30 00:09:53 sentinel.go:379: sentinel: discovered new sentinel="48ee106539cf267a79a84db621a01ee01b73ca5e" for master="mymaster"
redis: 2020/10/30 00:09:53 sentinel.go:332: sentinel: new master="mymaster" addr="127.0.0.1:6388"
reply=1 err=<nil>
reply=2 err=<nil>
reply=3 err=<nil>
reply=4 err=<nil>
reply=5 err=<nil>
reply=6 err=<nil>
...
reply=83 err=<nil>
reply=84 err=<nil>
reply=85 err=<nil>
reply=86 err=<nil>
reply=87 err=<nil>
reply=88 err=<nil>
reply=89 err=<nil>
reply=90 err=<nil>
reply=91 err=<nil>
reply=92 err=<nil>
reply=93 err=<nil>
reply=0 err=EOF
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
redis: 2020/10/30 00:11:33 sentinel.go:332: sentinel: new master="mymaster" addr="127.0.0.1:6398"
reply=94 err=<nil>
reply=95 err=<nil>
reply=96 err=<nil>
reply=97 err=<nil>
reply=98 err=<nil>
reply=99 err=<nil>
reply=100 err=<nil>

实验2:sentinel实例全部挂掉后,redis的读写操作

如果把3个sentinel实例全部 kill掉,则go-redis会记录一条日志,而对redis的读写操作仍然正常。

reply=233 err=<nil>
reply=234 err=<nil>
reply=235 err=<nil>
reply=236 err=<nil>
reply=237 err=<nil>
redis: 2020/10/30 22:06:45 pubsub.go:159: redis: discarding bad PubSub connection: EOF                                                                                                   
reply=238 err=<nil>
reply=239 err=<nil>
reply=240 err=<nil>

实验3:sentinel实例部分挂掉后(剩余实例数目多于配置的quorum),redis实例的主从切换

如果只kill掉1个sentinel,则剩余两个sentinel还能正常监测redis主从切换。例如下面是kill掉127.0.0.1:26379之后,再kill redis主节点127.0.0.1:6388的实验:

reply=322 err=<nil>
reply=323 err=<nil>
reply=324 err=<nil>
reply=325 err=<nil>
reply=326 err=<nil>
reply=327 err=<nil>
reply=328 err=<nil>
reply=329 err=<nil>
reply=330 err=<nil>
reply=0 err=EOF
redis: 2020/10/30 22:08:19 sentinel.go:313: sentinel: GetMasterAddrByName name="mymaster" failed: EOF
redis: 2020/10/30 22:08:19 sentinel.go:313: sentinel: GetMasterAddrByName name="mymaster" failed: dial tcp 127.0.0.1:26379: connect: connection refused
redis: 2020/10/30 22:08:19 sentinel.go:287: sentinel: GetMasterAddrByName master="mymaster" failed: dial tcp 127.0.0.1:26379: connect: connection refused
redis: 2020/10/30 22:08:19 sentinel.go:379: sentinel: discovered new sentinel="9a023490096f5f87db1c7f445d883f56e75275db" for master="mymaster"
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6388: connect: connection refused
redis: 2020/10/30 22:08:24 sentinel.go:332: sentinel: new master="mymaster" addr="127.0.0.1:6398"
reply=331 err=<nil>
reply=332 err=<nil>
reply=333 err=<nil>
reply=334 err=<nil>

实验4:sentinel实例都正常的情况下,进行redis实例迁移

当3个sentinel都正常运行的情况下,动态增减从节点对客户端没有影响。例如增加一个从节点127.0.0.1:6378再把原从节点127.0.0.1:6388 shutdown,客户端没有影响。进而把主节点127.0.0.1:6398 shutdown,迫使主从切换,结果证明客户端能够切换到新的主节点127.0.0.1:6378上。

reply=525 err=<nil>
reply=526 err=<nil>
reply=527 err=<nil>
reply=528 err=<nil>
reply=529 err=<nil>
reply=530 err=<nil>
reply=531 err=<nil>
reply=0 err=EOF
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
reply=0 err=dial tcp 127.0.0.1:6398: connect: connection refused
redis: 2020/10/30 22:43:19 sentinel.go:332: sentinel: new master="mymaster" addr="127.0.0.1:6378"
reply=532 err=<nil>
reply=533 err=<nil>
reply=534 err=<nil>
reply=535 err=<nil>
reply=536 err=<nil>
reply=537 err=<nil>

小结:

通过上面的实验证明,go-redis的NewFailoverClient对sentinel模式下的redis应用是稳定可靠的。

 

GitHub 加速计划 / sentine / Sentinel
22.25 K
7.98 K
下载
alibaba/Sentinel: Sentinel 是阿里巴巴开源的一款面向分布式服务架构的流量控制、熔断降级组件,提供实时监控、限流、降级和系统保护功能,适用于微服务治理场景。
最近提交(Master分支:3 个月前 )
195150bc * fix issue 2485 which occur oom when using async servlet request. * optimize imports * 1. fix the same issue in the webmvc-v6x 2. improve based on review comments 2 个月前
b78b09d3 2 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐