1
0
mirror of https://github.com/redis/go-redis.git synced 2025-07-28 06:42:00 +03:00

feat(ring): add GetShardClients and GetShardClientForKey methods to Ring for shard access (#3388)

* feat: expose shard information in redis.Ring

- Add GetShards() method to retrieve a list of active shard clients.
- Add GetShardByKey(key string) method to get the shard client for a specific key.
- These methods enable users to manage Pub/Sub operations more effectively by accessing shard-specific clients.

* rename GetShardClients and GetShardClientForKey

---------

Co-authored-by: DengY11 <212294929@qq.com>
Co-authored-by: Nedyalko Dyakov <1547186+ndyakov@users.noreply.github.com>
This commit is contained in:
Yi Deng
2025-05-27 23:04:04 +08:00
committed by GitHub
parent 86d418f940
commit cb1968cad6
2 changed files with 102 additions and 0 deletions

View File

@ -782,3 +782,82 @@ var _ = Describe("Ring Tx timeout", func() {
testTimeout()
})
})
var _ = Describe("Ring GetShardClients and GetShardClientForKey", func() {
var ring *redis.Ring
BeforeEach(func() {
ring = redis.NewRing(&redis.RingOptions{
Addrs: map[string]string{
"shard1": ":6379",
"shard2": ":6380",
},
})
})
AfterEach(func() {
Expect(ring.Close()).NotTo(HaveOccurred())
})
It("GetShardClients returns active shard clients", func() {
shards := ring.GetShardClients()
// Note: This test will pass even if Redis servers are not running,
// because GetShardClients only returns clients that are marked as "up",
// and newly created shards start as "up" until the first health check fails.
if len(shards) == 0 {
// Expected if Redis servers are not running
Skip("No active shards found (Redis servers not running)")
} else {
Expect(len(shards)).To(BeNumerically(">", 0))
for _, client := range shards {
Expect(client).NotTo(BeNil())
}
}
})
It("GetShardClientForKey returns correct shard for keys", func() {
testKeys := []string{"key1", "key2", "user:123", "channel:test"}
for _, key := range testKeys {
client, err := ring.GetShardClientForKey(key)
Expect(err).NotTo(HaveOccurred())
Expect(client).NotTo(BeNil())
}
})
It("GetShardClientForKey is consistent for same key", func() {
key := "test:consistency"
// Call GetShardClientForKey multiple times with the same key
// Should always return the same shard
var firstClient *redis.Client
for i := 0; i < 5; i++ {
client, err := ring.GetShardClientForKey(key)
Expect(err).NotTo(HaveOccurred())
Expect(client).NotTo(BeNil())
if i == 0 {
firstClient = client
} else {
Expect(client.String()).To(Equal(firstClient.String()))
}
}
})
It("GetShardClientForKey distributes keys across shards", func() {
testKeys := []string{"key1", "key2", "key3", "key4", "key5"}
shardMap := make(map[string]int)
for _, key := range testKeys {
client, err := ring.GetShardClientForKey(key)
Expect(err).NotTo(HaveOccurred())
shardMap[client.String()]++
}
// Should have at least 1 shard (could be all keys go to same shard due to hashing)
Expect(len(shardMap)).To(BeNumerically(">=", 1))
// But with multiple keys, we expect some distribution
Expect(len(shardMap)).To(BeNumerically("<=", 2)) // At most 2 shards (our setup)
})
})