Merge pull request #688 from go-redis/fix/random-node

Pick random node when command does not have keys
This commit is contained in:
Vladimir Mihailenco 2017-12-28 17:12:13 +02:00 committed by GitHub
commit 73b70592cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 11 deletions

View File

@ -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:

View File

@ -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 {

View File

@ -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()
})

View File

@ -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)
}

View File

@ -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
}

View File

@ -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)
}