mirror of https://github.com/go-redis/redis.git
fix node routing in slotClosestNode (#3043)
* fix node routing when all nodes are failing * fix minlatency zero value
This commit is contained in:
parent
26e0c49acf
commit
9c1f4f0642
|
@ -341,6 +341,8 @@ func (n *clusterNode) Close() error {
|
||||||
return n.Client.Close()
|
return n.Client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maximumNodeLatency = 1 * time.Minute
|
||||||
|
|
||||||
func (n *clusterNode) updateLatency() {
|
func (n *clusterNode) updateLatency() {
|
||||||
const numProbe = 10
|
const numProbe = 10
|
||||||
var dur uint64
|
var dur uint64
|
||||||
|
@ -361,7 +363,7 @@ func (n *clusterNode) updateLatency() {
|
||||||
if successes == 0 {
|
if successes == 0 {
|
||||||
// If none of the pings worked, set latency to some arbitrarily high value so this node gets
|
// If none of the pings worked, set latency to some arbitrarily high value so this node gets
|
||||||
// least priority.
|
// least priority.
|
||||||
latency = float64((1 * time.Minute) / time.Microsecond)
|
latency = float64((maximumNodeLatency) / time.Microsecond)
|
||||||
} else {
|
} else {
|
||||||
latency = float64(dur) / float64(successes)
|
latency = float64(dur) / float64(successes)
|
||||||
}
|
}
|
||||||
|
@ -735,20 +737,40 @@ func (c *clusterState) slotClosestNode(slot int) (*clusterNode, error) {
|
||||||
return c.nodes.Random()
|
return c.nodes.Random()
|
||||||
}
|
}
|
||||||
|
|
||||||
var node *clusterNode
|
var allNodesFailing = true
|
||||||
|
var (
|
||||||
|
closestNonFailingNode *clusterNode
|
||||||
|
closestNode *clusterNode
|
||||||
|
minLatency time.Duration
|
||||||
|
)
|
||||||
|
|
||||||
|
// setting the max possible duration as zerovalue for minlatency
|
||||||
|
minLatency = time.Duration(math.MaxInt64)
|
||||||
|
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
if n.Failing() {
|
if closestNode == nil || n.Latency() < minLatency {
|
||||||
continue
|
closestNode = n
|
||||||
}
|
minLatency = n.Latency()
|
||||||
if node == nil || n.Latency() < node.Latency() {
|
if !n.Failing() {
|
||||||
node = n
|
closestNonFailingNode = n
|
||||||
|
allNodesFailing = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node != nil {
|
|
||||||
return node, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all nodes are failing - return random node
|
// pick the healthly node with the lowest latency
|
||||||
|
if !allNodesFailing && closestNonFailingNode != nil {
|
||||||
|
return closestNonFailingNode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if all nodes are failing, we will pick the temporarily failing node with lowest latency
|
||||||
|
if minLatency < maximumNodeLatency && closestNode != nil {
|
||||||
|
internal.Logger.Printf(context.TODO(), "redis: all nodes are marked as failed, picking the temporarily failing node with lowest latency")
|
||||||
|
return closestNode, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all nodes are having the maximum latency(all pings are failing) - return a random node across the cluster
|
||||||
|
internal.Logger.Printf(context.TODO(), "redis: pings to all nodes are failing, picking a random node across the cluster")
|
||||||
return c.nodes.Random()
|
return c.nodes.Random()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue