likes
comments
collection
share

探索Redis集群:(二)数据操作与节点增减

作者站长头像
站长
· 阅读数 20

前情提要:

计划接下来用两周的时间,搞清楚Redis Cluster的相关内容。既然要深入了解集群,自然就需要解答以下几个基本问题:

  1. 集群中各节点的表现形式是什么?节点的增加和减少是怎样进行的?
  2. 数据在集群中是如何分布的?集群是如何处理读写操作的?在节点增减的时候,如何确保读写操作的正常进行?
  3. 集群是如何发现故障的?一旦发现故障,又是怎样进行处理的?
  4. 这种集群方式有没有什么局限?使用时有什么注意事项?
  5. 实际怎么搭建一个Redis集群?怎么使用?

今天继续讨论:Redis集群 -(二)数据分布与增减节点

也就是分片(sharding)

Redis Cluster通过一种称为 哈希槽(hash slot) 的机制来管理数据的分布以及读写操作的处理。

这个机制允许Redis Cluster实现高性能和高可用性,同时保证了数据的一致性和分布式处理。下面详细解释这些部分的具体做法和原理。

1. 数据在集群中的分布

Redis Cluster将所有的数据分成16384个哈希槽,每个键通过CRC16算法对16384取模的结果决定了它属于哪个哈希槽。 集群中的每个节点负责维护一部分哈希槽及其对应的键值对。 这种方式使得数据被平均分布在所有节点上,实现了数据的分布式存储和负载均衡。

举个例子,下图的Redis集群: 探索Redis集群:(二)数据操作与节点增减

  • 物理节点1中部署分片A的主节点和分片B的从节点
  • 物理节点2中部署分片B的主节点和分片C的从节点
  • 物理节点3中部署分片C的主节点和分片A的从节点
  • 分片A负责[0 - 5500]的槽位
  • 分片B负责[5501 - 11001]的槽位
  • 分片C负责[11001 - 16383]的槽位

2. 集群如何处理读写操作

2.1 写操作

当客户端尝试写入一个键时,Redis客户端库会根据键计算出它所属的哈希槽。 然后将这个写操作发送到负责该哈希槽的节点。 如果客户端连接的不是负责该哈希槽的节点,那么该节点会返回一个重定向信息,告诉客户端应该连接到哪个节点。 客户端接收到重定向后,会连接到正确的节点并重新发送写操作。

也就是下面的过程:

Redis集群
1. 计算CRC16哈希值
2. 返回重定向信息
3. 重定向到正确节点
主节点1
主节点2
主节点3
从节点1
从节点2
从节点3
客户端

2.2 读操作

读操作的处理方式与写操作类似。 客户端会计算键所属的哈希槽,并尝试从负责该哈希槽的节点读取数据。 如果连接的节点不是负责该哈希槽的节点,会发生重定向,客户端根据重定向信息连接到正确的节点进行读取。

3. 节点变化时的读写操作

3.1 新增节点

当向集群中添加新节点时,部分哈希槽会从现有节点迁移到新节点上。 这个过程中,涉及到的键值对也会被迁移到新节点。

在迁移过程中,旧节点会知道这些哈希槽正在迁移到哪个新节点,如果在迁移期间有对这些正在迁移的哈希槽的访问请求,旧节点会重定向客户端到新节点。

3.1.1 怎么增加一个节点

以下操作基于Redis 5.0以上,5.0以上的版本可以使用redis-cli --cluster reshard命令对Redis集群进行重分片操作,在之前的版本需要基于Ruby环境使用redis-trib.rb对Redis集群进行创建、修复、重分片等操作。

a. 启动新的Redis实例

首先,在新的服务器或容器上启动一个Redis实例,并修改Redis的配置文件以使其作为集群模式运行。以下是一些关键的配置选项:

  • cluster-enabled yes:启用集群模式。
  • cluster-config-file nodes.conf:指定集群配置文件的名称,Redis会自动管理这个文件。
  • cluster-node-timeout 5000:设置节点超时时间(毫秒)。
  • appendonly yes:启用AOF持久化。 假设新Redis实例将运行在192.168.1.100上,端口为6379,可以使用以下命令启动Redis实例:
redis-server /path/to/your/redis.conf
b. 将新节点添加到集群

使用redis-cli工具将新节点添加到集群中。需要使用--cluster add-node命令,指定新节点的IP和端口,以及集群中任意一个现有节点的IP和端口:

redis-cli --cluster add-node 192.168.1.100:6379 192.168.1.50:6379

这里,192.168.1.100:6379是新节点的地址,而192.168.1.50:6379是集群中任意一个现有节点的地址。

c. 迁移键到新节点

添加新节点后,集群会自动接受这个节点,但它一开始不会持有任何数据。 可以使用redis-cli--cluster reshard命令来迁移一部分键到新节点,以平衡集群的负载。 这个步骤需要指定要迁移的槽数,新节点的ID,以及一个或多个源节点的ID。

redis-cli --cluster reshard 192.168.1.50:6379

在执行上面的命令时,会进入一个交互式会话,用来引导完成reshard过程。

3.1.2 数据迁移过程中的读写操作

新增节点并进行reshard是比较简单的,根据命令进行操作就可以了。 但是如果reshard过程中,正在迁移槽位的一部分数据迁移到了目标节点,一部分数据还在源节点,这时正好发生的读写操作是怎么处理的呢?

以下数据迁移的过程保障了对正在迁移的key的读写请求也能被正确处理:

a. 迁移标记

当开始迁移一个哈希槽时,源节点(即数据迁出的节点)会标记这个槽为MIGRATING状态,目标节点(即数据迁入的节点)则将这个槽标记为IMPORTING状态。这两个状态表明了哈希槽正在迁移过程中。

b. 数据访问和迁移
  • 读操作:如果客户端尝试读取一个正在迁移的键,而这个键还在源节点上,源节点可以直接返回这个键的值。如果键已经被迁移到目标节点,源节点会返回一个特殊的重定向错误,告诉客户端应该从新的节点(目标节点)读取数据。
  • 写操作:对于写操作,如果目标节点收到了对一个IMPORTING状态槽中键的写请求,它会正常接受这个写操作。如果写操作发生在源节点,并且这个键正好被迁移,源节点会先将这个键迁移到目标节点,然后再执行写操作。
c. 原子迁移

每个键的迁移是原子的,意味着在迁移过程中,任何对这个键的访问要么是在源节点完成,要么在完成迁移后在目标节点上进行。这确保了数据的一致性。

下图描述了在迁移过程中一个key的读写处理过程:

客户端源节点目标节点迁移开始读操作alt[如果key在源节点][如果key已迁移至目标节点]写操作alt[如果key在源节点且未迁移][如果key正在迁移]标记哈希槽为MIGRATING标记哈希槽为IMPORTING请求读取key返回key的值返回重定向错误重新请求读取key返回key的值请求写入key执行写操作将key迁移到目标节点在目标节点执行写操作确认写入成功客户端源节点目标节点

3.2 移除节点

需要注意,这里讨论的移除节点不是移除一个从节点,而是移除一个主节点或者移除一个分片。

当从集群中移除节点时,需要对原节点上的数据进行迁移,迁移过程中发生的读写操作和上面类似。

在数据迁移完成后,就可以移除节点了。

以下是移除主节点的步骤:

a. 迁移哈希槽

首先,需要使用redis-cli --cluster reshard命令将要移除的分片(主节点)上的所有哈希槽迁移到集群中的其他节点:

redis-cli --cluster reshard <target-node-ip>:<port>

b. 迁移主节点的从节点

如果主节点有关联的从节点,需要将这些从节点指向集群中的其他主节点。通过CLUSTER REPLICATE命令来完成:

redis-cli -h <slave-node-ip> -p <port> CLUSTER REPLICATE <new-master-node-id>

c. 从集群配置中移除节点

一旦所有数据都迁移出去,并且从节点都重新指向了其他的主节点,就可以从集群配置中移除这个分片的主节点和从节点:

redis-cli --cluster del-node <any-cluster-node-ip>:<port> <node-id-to-remove>

这里的<any-cluster-node-ip>:<port>是集群中任何存活节点的地址,而<node-id-to-remove>是要移除的节点的ID。

d. 确认集群状态

在移除节点之后,使用redis-cli --cluster check命令来确认集群的健康状态:

redis-cli --cluster check <any-cluster-node-ip>:<port>

这次讨论了Redis集群中数据是如何分布的、读写操作是如何在集群中进行的、集群扩缩容的操作步骤以及数据迁移过程中的读写操作。

后续将讨论集群的故障发现与转移过程。

转载自:https://juejin.cn/post/7389923941472043034
评论
请登录