当前位置:首页 > 问答 > 正文

Redis集群里怎么直接拿到某个节点的数据,简单点说就是这样用的办法

在Redis集群里,你想直接拿到某个特定节点的数据,这个想法很直接,就是不想让集群自动帮你做路由,而是你自己指定说“我就要这个节点上的这个数据”,办法是有的,而且不止一种,但核心思想都一样:你得先找到那个节点,然后直接跟它“对话”。

第一种最常用的办法:用哈希标签(Hash Tag)

Redis集群是怎么决定一个键存在哪个节点上的呢?它是用CRC16算法给键算出一个哈希值,然后用这个哈希值对16384(也就是16K)个哈希槽取模,最后根据槽的分布找到对应的节点,默认情况下,它会对整个键名进行计算,比如你有两个键,user:10001user:10001:profile,虽然它们看起来很相关,但可能会被算到两个不同的哈希槽里,从而存到两个不同的节点上。

哈希标签就是为了解决这个问题而生的,它的用法很简单,就是在键名里用一对大括号把一部分包起来,集群在计算哈希槽的时候,只会看大括号里面的那部分内容,而忽略大括号外面的部分。

举个例子你就明白了,假设你想把所有和用户10001相关的数据都放在同一个节点上,你可以这样设计键名:

  • user:{10001}
  • user:{10001}:profile
  • order:{10001}:list

你看,这三个键的大括号里的内容都是10001,那么集群在计算时,只会对10001这个字符串进行CRC16计算和取模,因为计算源一模一样,所以算出来的哈希槽号也肯定是一样的,这意味着这三个键百分之百会存储在集群的同一个节点上。

Redis集群里怎么直接拿到某个节点的数据,简单点说就是这样用的办法

这样一来,你就不用关心集群到底有多少个节点,哪个节点具体负责哪个槽,你只需要知道,只要你用同样的哈希标签,这些相关的数据就肯定在同一个地方,当你想获取这些数据时,你甚至可以想办法先连上这个节点(下面会讲怎么连),然后就可以像操作单个Redis一样,用mget命令一次性获取user:{10001}user:{10001}:profile,因为它们在同一个节点上,这个操作是支持的,如果没有用哈希标签,这两个键可能在不同节点,你就不能用mget这种跨键操作了。

哈希标签是间接实现“直接拿到某个节点数据”的基石,它让你能逻辑上把数据分组,确保它们落在你期望的同一个目标节点上。

第二种办法:直接连接目标节点,并把它当单机Redis用

知道了数据在哪个节点上(无论是通过哈希标签逻辑分组,还是你通过CLUSTER KEYSLOTCLUSTER NODES命令查出来的),下一步就是直接连接它。

Redis集群的每个节点,其实都运行着两个端口,一个是客户端连接用的,比如6379;另一个是用于节点间通信的,通常是10000+6379=16379,你要连接的是客户端端口。

Redis集群里怎么直接拿到某个节点的数据,简单点说就是这样用的办法

当你用一个普通的Redis客户端(比如命令行工具redis-cli)直接连接上集群的某个节点时,默认情况下,这个节点仍然是一个“集群模式”的节点,它会检查你操作的键是不是由它自己负责的,如果不是,它就会给你返回一个-MOVED错误,告诉你这个键实际上在哪个节点上,让你去那边操作。

这显然不是我们想要的“直接拿数据”,我们想要的是,让这个节点“闭嘴”,别管集群那一套,我让你干嘛你就干嘛。

这时候就需要一个特殊的参数:-c,不对,说错了,-c参数是让redis-cli开启集群模式,自动跟随-MOVED重定向,我们需要的恰恰是它的反面,也就是不用-c参数,或者更明确地说,使用单机模式连接。

具体操作如下:

  1. 找出目标节点的地址:你需要知道你要连接的那个节点的IP和端口,你可以通过连接集群任意一个节点,执行CLUSTER NODES命令来获取完整的节点列表和信息,从中找到你要的那个。

    Redis集群里怎么直接拿到某个节点的数据,简单点说就是这样用的办法

  2. 直接连接:使用redis-cli,但不要加-c 参数。

    # 错误的做法(这会进入集群模式,会重定向):
    # redis-cli -c -h 192.168.1.10 -p 6379
    # 正确的做法(直接连接,单机模式):
    redis-cli -h 192.168.1.10 -p 6379
  3. 执行命令:你在这个命令行里,就可以像操作一个单机Redis一样操作这个节点了,你可以直接get keyset key value,但这里有个非常重要的前提:你只能操作那些恰好在这个节点上的键,如果你尝试操作一个不属于这个节点的键,这个节点不会像在集群模式下那样告诉你该去哪里,而是会直接报错,比如(error) MOVED 1234 192.168.1.11:6379,它虽然报错了,但不会帮你跳转,因为你用的是单机模式。

这种方法的精髓就是“精准打击”,你必须非常清楚你要的数据就在这个节点上,然后直连过去,把它当成一个独立的数据库来用,这在一些运维场景或者数据迁移的时候特别有用。

总结一下

想直接拿到Redis集群里某个节点的数据,两步走: 第一,最好通过哈希标签来规划你的键,让一类数据稳定地落在同一个节点上,这样你好找。 第二,使用单机模式的客户端(比如不加-c参数的redis-cli)去直接连接那个节点的IP和端口,然后就像用单机Redis一样操作,但务必记住,操作前要确认键就在那儿,否则会报错。

这种办法绕过了集群的自动路由,给了你更大的控制权,但同时也要求你对数据的分布了如指掌,否则很容易出错,它不算常规用法,但在特定需求下非常直接有效。