From af2662cdd0b578da6a70be558f338ba410e970a9 Mon Sep 17 00:00:00 2001 From: Taishi Kasuga Date: Thu, 5 Sep 2024 16:15:36 +0900 Subject: [PATCH 1/4] docs: fix readme about MGET, MSET and DEL commands --- README.md | 67 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 53790e0f..1494ca95 100644 --- a/README.md +++ b/README.md @@ -138,41 +138,66 @@ The `#pubsub` method supports sharded subscriptions. Every interface handles redirections and resharding states internally. ## Multiple keys and CROSSSLOT error -A subset of commands can be passed multiple keys. But it has a constraint the keys are in the same hash slot. -The following error occurs because keys must be in the same hash slot and not just the same node. +A subset of commands can be passed multiple keys. +In cluster mode, these commands have a constraint that passed keys should belong to the same slot +and not just the same node. +Therefore, The following error occurs: -```ruby -cli = RedisClient.cluster.new_client +``` +$ redis-cli mget key1 key2 key3 +(error) CROSSSLOT Keys in request don't hash to the same slot + +$ redis-cli cluster keyslot key1 +(integer) 9189 -cli.call('MGET', 'key1', 'key2', 'key3') -#=> CROSSSLOT Keys in request don't hash to the same slot (RedisClient::CommandError) +$ redis-cli cluster keyslot key2 +(integer) 4998 -cli.call('CLUSTER', 'KEYSLOT', 'key1') -#=> 9189 +$ redis-cli cluster keyslot key3 +(integer) 935 +``` -cli.call('CLUSTER', 'KEYSLOT', 'key2') -#=> 4998 +For the constraint, Redis cluster provides a feature to be able to bias keys to the same slot with a hash tag. -cli.call('CLUSTER', 'KEYSLOT', 'key3') -#=> 935 ``` +$ redis-cli mget {key}1 {key}2 {key}3 +1) (nil) +2) (nil) +3) (nil) -Also, you can use the hash tag to bias keys to the same slot. +$ redis-cli cluster keyslot {key}1 +(integer) 12539 -```ruby -cli.call('CLUSTER', 'KEYSLOT', '{key}1') -#=> 12539 +$ redis-cli cluster keyslot {key}2 +(integer) 12539 -cli.call('CLUSTER', 'KEYSLOT', '{key}2') -#=> 12539 +$ redis-cli cluster keyslot {key}3 +(integer) 12539 +``` -cli.call('CLUSTER', 'KEYSLOT', '{key}3') -#=> 12539 +In addition, this gem works multiple keys without a hash tag in MGET, MSET and DEL commands +using pipelining internally automatically. +If the first key includes a hash tag, this gem sends the command to the node as is. +If the first key doesn't have a hash tag, this gem converts the command into a single-key command +and sends them to nodes with pipelining, then gathering replies and returning them. -cli.call('MGET', '{key}1', '{key}2', '{key}3') +```ruby +r = RedisClient.cluster.new_client +#=> # + +r.call('mget', 'key1', 'key2', 'key3') +#=> [nil, nil, nil] + +r.call('mget', '{key}1', '{key}2', '{key}3') #=> [nil, nil, nil] ``` +This behavior is for upper libraries to be able to keep a compatibility with a standalone client. +You can exploit this behavior for migrating from a standalone server to a cluster. +Although multiple calles with single-key comamnds are slower than pipelining, +the performance of the pipelined commands are slower than a single-slot query with multiple keys. +We recommend to use a hash tag in this use cases for the performance. + ## Transactions This gem supports [Redis transactions](https://redis.io/topics/transactions), including atomicity with `MULTI`/`EXEC`, and conditional execution with `WATCH`. Redis does not support cross-node transactions, so all keys used within a From f20d34cb142e245f3a190cf5552d17c57a6e5905 Mon Sep 17 00:00:00 2001 From: Taishi Kasuga Date: Thu, 5 Sep 2024 16:26:43 +0900 Subject: [PATCH 2/4] fix --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1494ca95..bb0d757b 100644 --- a/README.md +++ b/README.md @@ -144,34 +144,34 @@ and not just the same node. Therefore, The following error occurs: ``` -$ redis-cli mget key1 key2 key3 +$ redis-cli -c mget key1 key2 key3 (error) CROSSSLOT Keys in request don't hash to the same slot -$ redis-cli cluster keyslot key1 +$ redis-cli -c cluster keyslot key1 (integer) 9189 -$ redis-cli cluster keyslot key2 +$ redis-cli -c cluster keyslot key2 (integer) 4998 -$ redis-cli cluster keyslot key3 +$ redis-cli -c cluster keyslot key3 (integer) 935 ``` For the constraint, Redis cluster provides a feature to be able to bias keys to the same slot with a hash tag. ``` -$ redis-cli mget {key}1 {key}2 {key}3 +$ redis-cli -c mget {key}1 {key}2 {key}3 1) (nil) 2) (nil) 3) (nil) -$ redis-cli cluster keyslot {key}1 +$ redis-cli -c cluster keyslot {key}1 (integer) 12539 -$ redis-cli cluster keyslot {key}2 +$ redis-cli -c cluster keyslot {key}2 (integer) 12539 -$ redis-cli cluster keyslot {key}3 +$ redis-cli -c cluster keyslot {key}3 (integer) 12539 ``` From 248bed03fe720ceaeb4e8200ee427fb89b18cbf6 Mon Sep 17 00:00:00 2001 From: Taishi Kasuga Date: Thu, 5 Sep 2024 16:41:20 +0900 Subject: [PATCH 3/4] fix --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb0d757b..d15ce8ca 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ $ redis-cli -c cluster keyslot {key}3 In addition, this gem works multiple keys without a hash tag in MGET, MSET and DEL commands using pipelining internally automatically. If the first key includes a hash tag, this gem sends the command to the node as is. -If the first key doesn't have a hash tag, this gem converts the command into a single-key command +If the first key doesn't have a hash tag, this gem converts the command into single-key commands and sends them to nodes with pipelining, then gathering replies and returning them. ```ruby @@ -194,9 +194,9 @@ r.call('mget', '{key}1', '{key}2', '{key}3') This behavior is for upper libraries to be able to keep a compatibility with a standalone client. You can exploit this behavior for migrating from a standalone server to a cluster. -Although multiple calles with single-key comamnds are slower than pipelining, -the performance of the pipelined commands are slower than a single-slot query with multiple keys. -We recommend to use a hash tag in this use cases for the performance. +Although multiple times queries with single-key commands are slower than pipelining, +that pipelining queries are slower than a single-slot query with multiple keys. +Hence, we recommend to use a hash tag in this use case for the better performance. ## Transactions This gem supports [Redis transactions](https://redis.io/topics/transactions), including atomicity with `MULTI`/`EXEC`, From 5565fc3a349ad41e81a4683bf03560f1ebff2a88 Mon Sep 17 00:00:00 2001 From: Taishi Kasuga Date: Thu, 5 Sep 2024 16:45:22 +0900 Subject: [PATCH 4/4] fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d15ce8ca..c87a8cad 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ r.call('mget', '{key}1', '{key}2', '{key}3') This behavior is for upper libraries to be able to keep a compatibility with a standalone client. You can exploit this behavior for migrating from a standalone server to a cluster. Although multiple times queries with single-key commands are slower than pipelining, -that pipelining queries are slower than a single-slot query with multiple keys. +that pipelined queries are slower than a single-slot query with multiple keys. Hence, we recommend to use a hash tag in this use case for the better performance. ## Transactions