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
|
- redis-server
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.4.x
|
|
||||||
- 1.7.x
|
- 1.7.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
|
@ -13,7 +12,6 @@ go:
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- go: 1.4.x
|
|
||||||
- go: tip
|
- go: tip
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
14
cluster.go
14
cluster.go
|
@ -533,16 +533,22 @@ func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
|
||||||
return info
|
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 {
|
func (c *ClusterClient) cmdSlot(cmd Cmder) int {
|
||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
return hashtag.Slot(firstKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
firstKey := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo))
|
slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
slot := hashtag.Slot(firstKey)
|
|
||||||
|
|
||||||
if cmdInfo != nil && cmdInfo.ReadOnly && c.opt.ReadOnly {
|
if cmdInfo != nil && cmdInfo.ReadOnly && c.opt.ReadOnly {
|
||||||
if c.opt.RouteByLatency {
|
if c.opt.RouteByLatency {
|
||||||
|
|
|
@ -536,6 +536,32 @@ var _ = Describe("ClusterClient", func() {
|
||||||
Expect(nodesList).Should(HaveLen(1))
|
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()
|
assertClusterClient()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -82,13 +82,13 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
||||||
if cmd.stringArg(2) != "0" {
|
if cmd.stringArg(2) != "0" {
|
||||||
return 3
|
return 3
|
||||||
} else {
|
} else {
|
||||||
return -1
|
return 0
|
||||||
}
|
}
|
||||||
case "publish":
|
case "publish":
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return -1
|
return 0
|
||||||
}
|
}
|
||||||
return int(info.FirstKeyPos)
|
return int(info.FirstKeyPos)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,13 +55,17 @@ func Key(key string) string {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RandomSlot() int {
|
||||||
|
return rand.Intn(SlotNumber)
|
||||||
|
}
|
||||||
|
|
||||||
// hashSlot returns a consistent slot number between 0 and 16383
|
// hashSlot returns a consistent slot number between 0 and 16383
|
||||||
// for any given string key.
|
// for any given string key.
|
||||||
func Slot(key string) int {
|
func Slot(key string) int {
|
||||||
key = Key(key)
|
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return rand.Intn(SlotNumber)
|
return RandomSlot()
|
||||||
}
|
}
|
||||||
|
key = Key(key)
|
||||||
return int(crc16sum(key)) % SlotNumber
|
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 {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if c.cmdsInfo == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
info := c.cmdsInfo[name]
|
info := c.cmdsInfo[name]
|
||||||
if info == nil {
|
if info == nil {
|
||||||
internal.Logf("info for cmd=%s not found", name)
|
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) {
|
func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) {
|
||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
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)
|
return c.shardByKey(firstKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue