@@ -540,7 +540,6 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
540
540
if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
541
541
return "" , err
542
542
}
543
- // Continue on other errors
544
543
internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName name=%q failed: %s" ,
545
544
c .opt .MasterName , err )
546
545
} else {
@@ -558,36 +557,59 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
558
557
if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
559
558
return "" , err
560
559
}
561
- // Continue on other errors
562
560
internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName name=%q failed: %s" ,
563
561
c .opt .MasterName , err )
564
562
} else {
565
563
return addr , nil
566
564
}
567
565
}
568
566
567
+ var (
568
+ masterAddr string
569
+ wg sync.WaitGroup
570
+ once sync.Once
571
+ done = make (chan struct {})
572
+ )
573
+
569
574
for i , sentinelAddr := range c .sentinelAddrs {
570
- sentinel := NewSentinelClient (c .opt .sentinelOptions (sentinelAddr ))
575
+ wg .Add (1 )
576
+ go func (i int , addr string ) {
577
+ defer wg .Done ()
578
+ select {
579
+ case <- done :
580
+ return
581
+ default :
582
+ sentinelCli := NewSentinelClient (c .opt .sentinelOptions (addr ))
583
+ addrVal , err := sentinelCli .GetMasterAddrByName (ctx , c .opt .MasterName ).Result ()
584
+ if err != nil {
585
+ internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName addr=%s, master=%q failed: %s" ,
586
+ addr , c .opt .MasterName , err )
587
+ _ = sentinelCli .Close ()
588
+ return
589
+ }
571
590
572
- masterAddr , err := sentinel .GetMasterAddrByName (ctx , c .opt .MasterName ).Result ()
573
- if err != nil {
574
- _ = sentinel .Close ()
575
- if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
576
- return "" , err
591
+ once .Do (func () {
592
+ masterAddr = net .JoinHostPort (addrVal [0 ], addrVal [1 ])
593
+ // Push working sentinel to the top
594
+ c .sentinelAddrs [0 ], c .sentinelAddrs [i ] = c .sentinelAddrs [i ], c .sentinelAddrs [0 ]
595
+ c .setSentinel (ctx , sentinelCli )
596
+ internal .Logger .Printf (ctx , "sentinel: selected addr=%s masterAddr=%s" , addr , masterAddr )
597
+ close (done )
598
+ })
577
599
}
578
- internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName master=%q failed: %s" ,
579
- c .opt .MasterName , err )
580
- continue
581
- }
600
+ }(i , sentinelAddr )
601
+ }
582
602
583
- // Push working sentinel to the top.
584
- c .sentinelAddrs [0 ], c .sentinelAddrs [i ] = c .sentinelAddrs [i ], c .sentinelAddrs [0 ]
585
- c .setSentinel (ctx , sentinel )
603
+ go func () {
604
+ wg .Wait ()
605
+ once .Do (func () { close (done ) })
606
+ }()
586
607
587
- addr := net .JoinHostPort (masterAddr [0 ], masterAddr [1 ])
588
- return addr , nil
589
- }
608
+ <- done
590
609
610
+ if masterAddr != "" {
611
+ return masterAddr , nil
612
+ }
591
613
return "" , errors .New ("redis: all sentinels specified in configuration are unreachable" )
592
614
}
593
615
0 commit comments