Skip to content

Commit bb586d6

Browse files
authored
fix: race condition while updating shards storage (#3888)
fix: race condition while updating shards storage Writing the array, while reading created sometimes a panic with data race in tests. Use atomic to swap the fields and load to get get the value safely. ``` % go test -race . -run TestConcurrentKubernetesClusterStateAccessValkey -count 20 ok github.com/zalando/skipper 170.118s ``` Signed-off-by: Sandor Szücs <sandor.szuecs@zalando.de>
1 parent 8b65d61 commit bb586d6

1 file changed

Lines changed: 4 additions & 4 deletions

File tree

net/valkey.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"math"
77
"strings"
88
"sync"
9+
"sync/atomic"
910
"time"
1011

1112
xxhash "github.com/cespare/xxhash/v2"
@@ -117,7 +118,7 @@ type valkeyRing struct {
117118

118119
// maps int to client for sharding, trades memory for concurrent access
119120
// most operations only have to use this lock-free structure
120-
shards [ringSize]valkey.Client
121+
shards [ringSize]atomic.Pointer[valkey.Client]
121122
activeShards int
122123

123124
// clientMap is used for Ping operations and to simplify update shards
@@ -155,7 +156,6 @@ func (vr *valkeyRing) updateShards(addr []string) {
155156
cur := -1
156157
shardSize := computeShardSize(len(addr))
157158
clients := make([]valkey.Client, 0, len(addr))
158-
159159
for _, cl := range vr.clientMap {
160160
clients = append(clients, cl)
161161
}
@@ -164,7 +164,7 @@ func (vr *valkeyRing) updateShards(addr []string) {
164164
if i%shardSize == 0 {
165165
cur++
166166
}
167-
vr.shards[i] = clients[cur]
167+
vr.shards[i].Store(&clients[cur])
168168
}
169169
vr.activeShards = cur + 1
170170
}
@@ -223,7 +223,7 @@ func (vr *valkeyRing) SetAddr(addr []string) error {
223223

224224
// shardForKey does the lookup for valkey most operations to find the valkey ring shard
225225
func (vr *valkeyRing) shardForKey(key string) valkey.Client {
226-
return vr.shards[xxhash.Sum64String(key)%ringSize]
226+
return *vr.shards[xxhash.Sum64String(key)%ringSize].Load()
227227
}
228228

229229
// PingAll pings all known shards

0 commit comments

Comments
 (0)