Skip to content

Commit

Permalink
Add ReplicaOnly support for cluster client
Browse files Browse the repository at this point in the history
  • Loading branch information
NeoHuang committed Aug 25, 2023
1 parent 92d534f commit dd8642a
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 2 deletions.
20 changes: 19 additions & 1 deletion cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package rueidis
import (
"context"
"errors"
"math/rand"
"net"
"runtime"
"strconv"
Expand Down Expand Up @@ -176,7 +177,6 @@ func (c *clusterClient) _refresh() (err error) {

groups := parseSlots(reply, addr)

// TODO support read from replicas
conns := make(map[string]conn, len(groups))
for _, g := range groups {
for _, addr := range g.nodes {
Expand Down Expand Up @@ -205,6 +205,15 @@ func (c *clusterClient) _refresh() (err error) {
slots := [16384]conn{}
for master, g := range groups {
cc := conns[master]
if c.opt.ReplicaOnly {
if replicaAddr := g.pickReplica(); replicaAddr != "" {
cc = conns[replicaAddr]
result := cc.Do(context.Background(), cmds.ReadOnlyCmd)
if result.Error() != nil {
return err
}
}
}
for _, slot := range g.slots {
for i := slot[0]; i <= slot[1]; i++ {
slots[i] = cc
Expand Down Expand Up @@ -1069,6 +1078,15 @@ func (r *connretrycache) ResetLen(n int) {
}
}

func (g group) pickReplica() string {
// no replica exists
if len(g.nodes) <= 1 {
return ""
}

return g.nodes[1+rand.Intn(len(g.nodes)-1)]
}

var connretrycachep = util.NewPool(func(capacity int) *connretrycache {
return &connretrycache{m: make(map[conn]*retrycache, capacity), n: capacity}
})
4 changes: 4 additions & 0 deletions internal/cmds/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ var (
PingCmd = Completed{
cs: newCommandSlice([]string{"PING"}),
}
// ReadOnly is predefined READONLY
ReadOnlyCmd = Completed{
cs: newCommandSlice([]string{"READONLY"}),
}
// SlotCmd is predefined CLUSTER SLOTS
SlotCmd = Completed{
cs: newCommandSlice([]string{"CLUSTER", "SLOTS"}),
Expand Down
1 change: 0 additions & 1 deletion rueidis.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ type ClientOption struct {
ForceSingleClient bool

// ReplicaOnly indicates that this client will only try to connect to readonly replicas of redis setup.
// currently, it is only implemented for sentinel client
ReplicaOnly bool

// ClientNoEvict sets the client eviction mode for the current connection.
Expand Down

0 comments on commit dd8642a

Please sign in to comment.