mirror of
https://github.com/redis/go-redis.git
synced 2025-07-28 06:42:00 +03:00
fix: fixes ring.SetAddrs and rebalance race (#2283)
* fix: fixes ring.SetAddrs and rebalance race
The change ensures atomic update of `c.hash` and `c.shards`.
`BenchmarkRingRebalanceLocked` shows rebalance latency:
```
go test . -run=NONE -bench=BenchmarkRingRebalanceLocked -v -count=10 | benchstat /dev/stdin
name time/op
RingRebalanceLocked-8 8.50µs ±14%
```
(Note: it essentially reverts a46b053aa6
)
This commit is contained in:
committed by
GitHub
parent
bbff4dd5dc
commit
d83436b321
34
ring.go
34
ring.go
@ -254,9 +254,9 @@ func (c *ringSharding) SetAddrs(addrs map[string]string) {
|
||||
|
||||
shards, cleanup := c.newRingShards(addrs, c.shards)
|
||||
c.shards = shards
|
||||
c.rebalanceLocked()
|
||||
c.mu.Unlock()
|
||||
|
||||
c.rebalance()
|
||||
cleanup()
|
||||
}
|
||||
|
||||
@ -388,7 +388,9 @@ func (c *ringSharding) Heartbeat(ctx context.Context, frequency time.Duration) {
|
||||
}
|
||||
|
||||
if rebalance {
|
||||
c.rebalance()
|
||||
c.mu.Lock()
|
||||
c.rebalanceLocked()
|
||||
c.mu.Unlock()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
@ -396,32 +398,26 @@ func (c *ringSharding) Heartbeat(ctx context.Context, frequency time.Duration) {
|
||||
}
|
||||
}
|
||||
|
||||
// rebalance removes dead shards from the Ring.
|
||||
func (c *ringSharding) rebalance() {
|
||||
c.mu.RLock()
|
||||
shards := c.shards
|
||||
c.mu.RUnlock()
|
||||
|
||||
if shards == nil {
|
||||
// rebalanceLocked removes dead shards from the Ring.
|
||||
// Requires c.mu locked.
|
||||
func (c *ringSharding) rebalanceLocked() {
|
||||
if c.closed {
|
||||
return
|
||||
}
|
||||
if c.shards == nil {
|
||||
return
|
||||
}
|
||||
|
||||
liveShards := make([]string, 0, len(shards.m))
|
||||
liveShards := make([]string, 0, len(c.shards.m))
|
||||
|
||||
for name, shard := range shards.m {
|
||||
for name, shard := range c.shards.m {
|
||||
if shard.IsUp() {
|
||||
liveShards = append(liveShards, name)
|
||||
}
|
||||
}
|
||||
|
||||
hash := c.opt.NewConsistentHash(liveShards)
|
||||
|
||||
c.mu.Lock()
|
||||
if !c.closed {
|
||||
c.hash = hash
|
||||
c.numShard = len(liveShards)
|
||||
}
|
||||
c.mu.Unlock()
|
||||
c.hash = c.opt.NewConsistentHash(liveShards)
|
||||
c.numShard = len(liveShards)
|
||||
}
|
||||
|
||||
func (c *ringSharding) Len() int {
|
||||
|
Reference in New Issue
Block a user