mirror of https://github.com/go-redis/redis.git
Merge pull request #688 from go-redis/fix/random-node
Pick random node when command does not have keys
This commit is contained in:
commit
73b70592cd
|
@ -5,7 +5,6 @@ services:
|
|||
- redis-server
|
||||
|
||||
go:
|
||||
- 1.4.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
|
@ -13,7 +12,6 @@ go:
|
|||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: 1.4.x
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
|
|
14
cluster.go
14
cluster.go
|
@ -533,16 +533,22 @@ func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
|
|||
return info
|
||||
}
|
||||
|
||||
func cmdSlot(cmd Cmder, pos int) int {
|
||||
if pos == 0 {
|
||||
return hashtag.RandomSlot()
|
||||
}
|
||||
firstKey := cmd.stringArg(pos)
|
||||
return hashtag.Slot(firstKey)
|
||||
}
|
||||
|
||||
func (c *ClusterClient) cmdSlot(cmd Cmder) int {
|
||||
cmdInfo := c.cmdInfo(cmd.Name())
|
||||
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||
return hashtag.Slot(firstKey)
|
||||
return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
|
||||
}
|
||||
|
||||
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
||||
cmdInfo := c.cmdInfo(cmd.Name())
|
||||
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||
slot := hashtag.Slot(firstKey)
|
||||
slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
|
||||
|
||||
if cmdInfo != nil && cmdInfo.ReadOnly && c.opt.ReadOnly {
|
||||
if c.opt.RouteByLatency {
|
||||
|
|
|
@ -536,6 +536,32 @@ var _ = Describe("ClusterClient", func() {
|
|||
Expect(nodesList).Should(HaveLen(1))
|
||||
})
|
||||
|
||||
It("should RANDOMKEY", func() {
|
||||
const nkeys = 100
|
||||
|
||||
for i := 0; i < nkeys; i++ {
|
||||
err := client.Set(fmt.Sprintf("key%d", i), "value", 0).Err()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
var keys []string
|
||||
addKey := func(key string) {
|
||||
for _, k := range keys {
|
||||
if k == key {
|
||||
return
|
||||
}
|
||||
}
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
for i := 0; i < nkeys*10; i++ {
|
||||
key := client.RandomKey().Val()
|
||||
addKey(key)
|
||||
}
|
||||
|
||||
Expect(len(keys)).To(BeNumerically("~", nkeys, nkeys/10))
|
||||
})
|
||||
|
||||
assertClusterClient()
|
||||
})
|
||||
|
||||
|
|
|
@ -82,13 +82,13 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
|||
if cmd.stringArg(2) != "0" {
|
||||
return 3
|
||||
} else {
|
||||
return -1
|
||||
return 0
|
||||
}
|
||||
case "publish":
|
||||
return 1
|
||||
}
|
||||
if info == nil {
|
||||
return -1
|
||||
return 0
|
||||
}
|
||||
return int(info.FirstKeyPos)
|
||||
}
|
||||
|
|
|
@ -55,13 +55,17 @@ func Key(key string) string {
|
|||
return key
|
||||
}
|
||||
|
||||
func RandomSlot() int {
|
||||
return rand.Intn(SlotNumber)
|
||||
}
|
||||
|
||||
// hashSlot returns a consistent slot number between 0 and 16383
|
||||
// for any given string key.
|
||||
func Slot(key string) int {
|
||||
key = Key(key)
|
||||
if key == "" {
|
||||
return rand.Intn(SlotNumber)
|
||||
return RandomSlot()
|
||||
}
|
||||
key = Key(key)
|
||||
return int(crc16sum(key)) % SlotNumber
|
||||
}
|
||||
|
||||
|
|
9
ring.go
9
ring.go
|
@ -298,6 +298,9 @@ func (c *Ring) cmdInfo(name string) *CommandInfo {
|
|||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if c.cmdsInfo == nil {
|
||||
return nil
|
||||
}
|
||||
info := c.cmdsInfo[name]
|
||||
if info == nil {
|
||||
internal.Logf("info for cmd=%s not found", name)
|
||||
|
@ -343,7 +346,11 @@ func (c *Ring) shardByName(name string) (*ringShard, error) {
|
|||
|
||||
func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) {
|
||||
cmdInfo := c.cmdInfo(cmd.Name())
|
||||
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||
pos := cmdFirstKeyPos(cmd, cmdInfo)
|
||||
if pos == 0 {
|
||||
return c.randomShard()
|
||||
}
|
||||
firstKey := cmd.stringArg(pos)
|
||||
return c.shardByKey(firstKey)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue