Redis 集群是 Redis 提供的一种分布式实现,用于水平扩展数据存储能力。通过 Redis 集群,可以将数据分片存储在多个 Redis 节点上,同时提供高可用性和故障转移功能。
- 分片(Sharding):
- Redis 集群将数据划分为 16384 个插槽(slots),每个插槽代表一部分数据。
- 每个 Redis 节点负责一部分插槽。数据键通过哈希函数映射到特定的插槽。
- 主从复制(Replication):
- 每个分片可以有一个主节点和多个从节点。
- 主节点负责处理写请求,从节点作为备份,提供读取和故障切换。
- 高可用性:
- 如果主节点故障,从节点会自动提升为主节点,确保服务可用性。
- 这只限于每个分片的主从节点范围内,如果主从节点都挂了,那么这个分片上的数据是访问不到的。
- 一致性模型:
- Redis 集群采用 最终一致性,在网络分区的情况下使用部分可用性,但不会丢失数据。
在 Spring Boot 项目中集成 Redis 集群,可以使用 Spring Data Redis 来进行配置。
在 Spring Boot 中,可以使用 RedisTemplate 来操作 Redis 数据。通过 Lettuce 客户端来实现 Redis 集群中的读写分离,可以利用 Lettuce 对读策略(ReadFrom)的支持,将读操作分配到从节点,写操作保持在主节点。这适用于 Redis 的主从复制架构。
创建一个配置类,用于设置 RedisTemplate。
- 使用 LettuceConnectionFactory 配置 Redis 连接。
- 设置 ReadFrom 策略,选择将读请求发送到从节点。
- 使用 RedisTemplate 执行读写操作,Lettuce 会根据配置的 ReadFrom 策略自动选择节点。
配置 LettuceConnectionFactory,通过自定义 LettuceConnectionFactory 配置 Redis 集群连接和读策略。
可以将 Redis 集群的配置部分放在 application.yml 文件中,使配置更加灵活。
spring:redis:cluster:nodes:- 127.0.0.1:7000- 127.0.0.1:7001- 127.0.0.1:7002timeout: 5000lettuce:read-from: REPLICA_PREFERRED # 优先从从节点读取pool:max-active: 8max-idle: 8min-idle: 0
在配置类中读取配置文件
@Configuration
public class RedisConfig {@Value("${spring.redis.cluster.nodes}")private List<String> clusterNodes;@Beanpublic LettuceConnectionFactory redisConnectionFactory() {// 使用配置文件中的 Redis 集群节点信息RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(clusterNodes);LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()// 使用配置文件中的读取策略.readFrom(ReadFrom.REPLICA_PREFERRED).build();return new LettuceConnectionFactory(clusterConfig, clientConfig);}// 配置 RedisTemplate,用于与 Redis 交互@Beanpublic RedisTemplate<String, Object> redisTemplate() {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory());// 设置序列化器template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(new StringRedisSerializer());return template;}
}
- read-from 配置项说明:
- MASTER: 所有操作都在主节点执行(默认)。
- MASTER_PREFERRED:优先从主节点读取数据,如果主节点不可用则从从节点读取。
- REPLICA: 所有读取操作都从从节点执行。
- REPLICA_PREFERRED: 优先从从节点读取,如果没有可用从节点则读取主节点。
- ANY: 读取请求可以从任意节点执行(包括主节点和从节点)。
RedisTemplate 会根据配置的 LettuceConnectionFactory,自动进行读写分离。写操作会默认发往主节点,而读操作则根据 ReadFrom 策略发往从节点。
在 Redis 集群中,为了在执行 Lua 脚本时能够确保操作的多个键位于同一哈希槽中,Redis 引入了 哈希标签(Hash Tag) 的概念。
- 哈希标签 是一种机制,用来告诉 Redis 集群哪些键应该被视为一个整体,映射到同一个哈希槽(Hash Slot)中。
- 哈希标签是通过将键名的一部分用大括号 {} 包围来实现的。Redis 只会对 {} 内部的内容进行哈希计算,以决定该键的哈希槽位置。
- 如果你有两个键 key1 和 key2,通常它们会映射到不同的哈希槽中。然而,如果使用哈希标签,例如 user:{123} 和 order:{123},那么 123 部分会被用于哈希计算,使这两个键落在同一个哈希槽中。
- user:{123} 和 order:{123} 将会落在同一个哈希槽。
- user:123 和 order:123 将可能落在不同的哈希槽中。
- 在 Redis 集群环境中,当执行 Lua 脚本时,所有涉及的键必须位于同一个哈希槽中,否则会报错,因为 Redis 集群无法在不同的节点之间自动协调 Lua 脚本。使用哈希标签可以确保多个相关键位于同一哈希槽,这样在执行 Lua 脚本时可以正常运行。
在 Redis 集群架构中,如果发生数据倾斜(即某些节点存储的数据明显多于其他节点),这可能会导致部分节点的负载过高,影响性能和稳定性。为了解决数据倾斜问题,可以采取以下措施:
调整哈希槽的分配
Redis 集群中使用哈希槽(hash slots)来分布数据,每个节点管理一定数量的哈希槽。如果某些节点的哈希槽数量明显多于其他节点,可能会导致数据倾斜。可以通过 redis-cli --cluster rebalance 命令重新分配哈希槽,让数据更均匀地分布在各个节点上。
# <node-address>:<port> 表示集群中任一主节点的地址和端口,用于连接到 Redis 集群。Redis 会通过这个节点获取集群的状态信息。
# 最终重新平衡哈希槽的分配是针对整个集群的。
redis-cli --cluster rebalance --cluster-use-empty-masters <node-address>:<port>
添加新的节点:增加新的节点可以减轻现有节点的负担,并改善数据分布:
- 使用 redis-cli --cluster add-node 命令将新节点加入到集群中。
- 加入新节点后,使用 redis-cli --cluster rebalance 来重新平衡数据和哈希槽的分布,使得新节点参与数据存储。
迁移数据:可以手动或自动将数据从高负载节点迁移到其他节点:
- 使用 redis-cli --cluster reshard 命令将部分哈希槽从高负载节点迁移到其他节点。
- 迁移数据时,需要指定源节点、目标节点以及要迁移的哈希槽数量。
redis-cli --cluster reshard <node-address>:<port>
- 输入目标哈希槽数量和目标节点,Redis 会自动完成迁移。
选择合适的分片键:如果数据倾斜是由于分片键选择不合理造成的,可以考虑重新选择分片键:
- 使用均匀分布的数据字段作为分片键,例如随机数或 UUID,而不是用户 ID 等容易造成数据集中化的字段。
- 使用哈希策略来确保分片键的散列值在集群中均匀分布。
监控和优化:通过监控工具持续关注 Redis 集群的运行状态,及早发现并解决数据倾斜问题:
- 使用 redis-cli --cluster info 或其他 Redis 监控工具来查看每个节点的哈希槽和内存使用情况。
- 借助 INFO 命令获取每个节点的状态信息,了解内存和负载分布。
- 定期评估数据分布,必要时进行数据迁移或重新分配哈希槽。
在创建 Redis 集群时,哈希槽的分配通常是自动进行的,但也可以手动分配哈希槽给每个主节点。
首先,使用以下命令创建一个 Redis 集群,并为每个主节点分配哈希槽。
redis-cli --cluster create \
192.168.1.1:6379 \
192.168.1.2:6379 \
192.168.1.3:6379 \
192.168.1.4:6379 \
--cluster-replicas 1 \
--cluster-slots 16384
此命令将创建一个包含 4 个主节点的 Redis 集群,并为每个主节点指定 16384 个哈希槽。
手动分配哈希槽
# 为主节点 1 分配哈希槽 0 - 4095
redis-cli --cluster addslots 192.168.1.1:6379 0 4095# 为主节点 2 分配哈希槽 4096 - 8191
redis-cli --cluster addslots 192.168.1.2:6379 4096 8191# 为主节点 3 分配哈希槽 8192 - 12287
redis-cli --cluster addslots 192.168.1.3:6379 8192 12287# 为主节点 4 分配哈希槽 12288 - 16383
redis-cli --cluster addslots 192.168.1.4:6379 12288 16383