@@ -21,6 +21,10 @@ import (
21
21
"github.com/redis/go-redis/v9/internal/rand"
22
22
)
23
23
24
+ const (
25
+ minLatencyMeasurementInterval = 10 * time .Second
26
+ )
27
+
24
28
var errClusterNoNodes = fmt .Errorf ("redis: cluster has no nodes" )
25
29
26
30
// ClusterOptions are used to configure a cluster client and should be
@@ -316,6 +320,10 @@ type clusterNode struct {
316
320
latency uint32 // atomic
317
321
generation uint32 // atomic
318
322
failing uint32 // atomic
323
+
324
+ // last time the latency measurement was performed for the node, stored in nanoseconds
325
+ // from epoch
326
+ lastLatencyMeasurement int64 // atomic
319
327
}
320
328
321
329
func newClusterNode (clOpt * ClusterOptions , addr string ) * clusterNode {
@@ -368,6 +376,7 @@ func (n *clusterNode) updateLatency() {
368
376
latency = float64 (dur ) / float64 (successes )
369
377
}
370
378
atomic .StoreUint32 (& n .latency , uint32 (latency + 0.5 ))
379
+ n .SetLastLatencyMeasurement (time .Now ())
371
380
}
372
381
373
382
func (n * clusterNode ) Latency () time.Duration {
@@ -397,6 +406,10 @@ func (n *clusterNode) Generation() uint32 {
397
406
return atomic .LoadUint32 (& n .generation )
398
407
}
399
408
409
+ func (n * clusterNode ) LastLatencyMeasurement () int64 {
410
+ return atomic .LoadInt64 (& n .lastLatencyMeasurement )
411
+ }
412
+
400
413
func (n * clusterNode ) SetGeneration (gen uint32 ) {
401
414
for {
402
415
v := atomic .LoadUint32 (& n .generation )
@@ -406,6 +419,15 @@ func (n *clusterNode) SetGeneration(gen uint32) {
406
419
}
407
420
}
408
421
422
+ func (n * clusterNode ) SetLastLatencyMeasurement (t time.Time ) {
423
+ for {
424
+ v := atomic .LoadInt64 (& n .lastLatencyMeasurement )
425
+ if t .UnixNano () < v || atomic .CompareAndSwapInt64 (& n .lastLatencyMeasurement , v , t .UnixNano ()) {
426
+ break
427
+ }
428
+ }
429
+ }
430
+
409
431
//------------------------------------------------------------------------------
410
432
411
433
type clusterNodes struct {
@@ -493,10 +515,11 @@ func (c *clusterNodes) GC(generation uint32) {
493
515
c .mu .Lock ()
494
516
495
517
c .activeAddrs = c .activeAddrs [:0 ]
518
+ now := time .Now ()
496
519
for addr , node := range c .nodes {
497
520
if node .Generation () >= generation {
498
521
c .activeAddrs = append (c .activeAddrs , addr )
499
- if c .opt .RouteByLatency {
522
+ if c .opt .RouteByLatency && node . LastLatencyMeasurement () < now . Add ( - minLatencyMeasurementInterval ). UnixNano () {
500
523
go node .updateLatency ()
501
524
}
502
525
continue
0 commit comments