返回

golang连接redis集群遇见的坑

后端

背景

我正在使用golang开发一个项目,该项目需要使用redis集群作为缓存。我按照redis集群的官方文档进行了配置,并成功地连接到了集群。但是,当我尝试在集群中执行lua脚本时,却遇到了一个问题。

问题

当我尝试在集群中执行lua脚本时,遇到了以下错误:

ERR Operation against a key holding the wrong kind of value

我检查了redis集群的文档,发现lua脚本只能在string类型的key上执行。但是,我在集群中存储的key都是hash类型的。

解决思路

为了解决这个问题,我需要将hash类型的key转换为string类型。我可以在lua脚本中使用以下命令来实现:

redis.call("SET", key, redis.call("HGETALL", key))

但是,这会导致额外的开销,因为每次执行lua脚本时都需要将hash类型的key转换为string类型。

为了避免额外的开销,我使用了hashTag来解决这个问题。hashTag是一个特殊的字符,可以用来将key分散到不同的node节点上。我可以在key中添加hashTag,然后使用hashTag来确保所有key都落在一个node节点上。

例如,我可以将以下key添加到redis集群中:

user:1000#node1
user:1001#node1
user:1002#node1

这样,当我在集群中执行lua脚本时,所有key都会落在node1节点上。

原理

hashTag是如何工作的呢?

redis集群使用一致性哈希算法来将key分散到不同的node节点上。一致性哈希算法是一种分布式哈希表算法,它可以确保每个key都均匀地分布到不同的node节点上。

当redis集群收到一个key时,它会使用一致性哈希算法来计算出该key应该存储在哪个node节点上。计算方法如下:

  1. 将key转换为一个整数。
  2. 将整数除以redis集群中node节点的数量。
  3. 取余数。

余数就是该key应该存储的node节点的编号。

当我在key中添加hashTag时,hashTag也会被包含在key的整数表示中。因此,当redis集群使用一致性哈希算法来计算key应该存储在哪个node节点上时,hashTag也会被考虑在内。

这样,我就可以确保所有带有相同hashTag的key都存储在同一个node节点上。

总结

在golang中使用redis集群时,我遇到了一个问题,即在集群中执行lua脚本时遇到了错误。这个问题与lua脚本只能在string类型的key上执行有关。为了解决这个问题,我使用了hashTag来确保所有key都落在一个node节点上。