@@ -566,29 +566,60 @@ func (c *sentinelFailover) MasterAddr(ctx context.Context) (string, error) {
566566 }
567567 }
568568
569- for i , sentinelAddr := range c .sentinelAddrs {
570- sentinel := NewSentinelClient (c .opt .sentinelOptions (sentinelAddr ))
569+ var (
570+ masterAddr string
571+ wg sync.WaitGroup
572+ once sync.Once
573+ errCh = make (chan error , len (c .sentinelAddrs ))
574+ )
571575
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
577- }
578- internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName master=%q failed: %s" ,
579- c .opt .MasterName , err )
580- continue
581- }
576+ ctx , cancel := context .WithCancel (ctx )
577+ defer cancel ()
582578
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 )
579+ for i , sentinelAddr := range c .sentinelAddrs {
580+ wg .Add (1 )
581+ go func (i int , addr string ) {
582+ defer wg .Done ()
583+ sentinelCli := NewSentinelClient (c .opt .sentinelOptions (addr ))
584+ addrVal , err := sentinelCli .GetMasterAddrByName (ctx , c .opt .MasterName ).Result ()
585+ if err != nil {
586+ if errors .Is (err , context .Canceled ) || errors .Is (err , context .DeadlineExceeded ) {
587+ // Report immediately and return
588+ errCh <- err
589+ return
590+ }
591+ internal .Logger .Printf (ctx , "sentinel: GetMasterAddrByName addr=%s, master=%q failed: %s" ,
592+ addr , c .opt .MasterName , err )
593+ _ = sentinelCli .Close ()
594+ return
595+ }
586596
587- addr := net .JoinHostPort (masterAddr [0 ], masterAddr [1 ])
588- return addr , nil
597+ once .Do (func () {
598+ masterAddr = net .JoinHostPort (addrVal [0 ], addrVal [1 ])
599+ // Push working sentinel to the top
600+ c .sentinelAddrs [0 ], c .sentinelAddrs [i ] = c .sentinelAddrs [i ], c .sentinelAddrs [0 ]
601+ c .setSentinel (ctx , sentinelCli )
602+ internal .Logger .Printf (ctx , "sentinel: selected addr=%s masterAddr=%s" , addr , masterAddr )
603+ cancel ()
604+ })
605+ }(i , sentinelAddr )
589606 }
590607
591- return "" , errors .New ("redis: all sentinels specified in configuration are unreachable" )
608+ done := make (chan struct {})
609+ go func () {
610+ wg .Wait ()
611+ close (done )
612+ }()
613+
614+ select {
615+ case <- done :
616+ if masterAddr != "" {
617+ return masterAddr , nil
618+ }
619+ return "" , errors .New ("redis: all sentinels specified in configuration are unreachable" )
620+ case err := <- errCh :
621+ return "" , err
622+ }
592623}
593624
594625func (c * sentinelFailover ) replicaAddrs (ctx context.Context , useDisconnected bool ) ([]string , error ) {
0 commit comments