diff --git a/cluster.go b/cluster.go index 05b234aacf..5ec48c5863 100644 --- a/cluster.go +++ b/cluster.go @@ -1407,6 +1407,16 @@ func (c *ClusterClient) cmdsMoved( return nil } +// NewTransation returns a transaction, the related slot is determined by key. +func (c *ClusterClient) NewTransation(ctx context.Context, key string) (*Tx, error) { + slot := hashtag.Slot(key) + node, err := c.slotMasterNode(ctx, slot) + if err != nil { + return nil, err + } + return node.Client.newTx(), nil +} + func (c *ClusterClient) Watch(ctx context.Context, fn func(*Tx) error, keys ...string) error { if len(keys) == 0 { return fmt.Errorf("redis: Watch requires at least one key") diff --git a/go.mod b/go.mod index 927841e0d3..faa9023937 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/go-redis/redis/v9 go 1.17 require ( - github.com/cespare/xxhash/v2 v2.1.2 + github.com/cespare/xxhash/v2 v2.2.0 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.20.0 diff --git a/go.sum b/go.sum index 224bfa9034..e7213528b4 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= diff --git a/redis.go b/redis.go index f558181240..91fc977b2c 100644 --- a/redis.go +++ b/redis.go @@ -9,6 +9,7 @@ import ( "time" "github.com/go-redis/redis/v9/internal" + "github.com/go-redis/redis/v9/internal/hashtag" "github.com/go-redis/redis/v9/internal/pool" "github.com/go-redis/redis/v9/internal/proto" ) @@ -757,3 +758,16 @@ func (c *Conn) TxPipeline() Pipeliner { pipe.init() return &pipe } + +func AreKeysInSameSlot(keys ...string) bool { + if len(keys) == 0 { + return true + } + slot := hashtag.Slot(keys[0]) + for _, key := range keys[1:] { + if hashtag.Slot(key) != slot { + return false + } + } + return true +}