Redis Cluster 分片机制

ops/2024/12/18 4:52:57/

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

http://www.ppmy.cn/ops/142809.html

相关文章

springboot430校园食堂订餐系统boot(论文+源码)_kaic

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装校园食堂订餐系统软件来发挥其高效地信息处理的作用&#x…

【C语言】库函数常见的陷阱与缺陷(五):数学函数

目录 一、sqrt 函数 1.1. 功能与场景用法 1.2. 陷阱与缺陷 1.3. 安全使用建议 1.4. 代码示例 二、pow 函数 2.1. 功能与用法 2.2. 陷阱与缺陷 2.2.1. 底数和指数的取值范围问题 2.2.2. 精度和舍入误差 2.3. 安全使用建议 2.4. 代码示例 三、sin 函数 3.1. 功能与…

如何快速开发一款AI小程序?基于微信云开发的实战指南

如何快速开发一款AI小程序&#xff1f;基于微信云开发的实战指南 引言 微信小程序凭借其轻便、易推广等特点&#xff0c;已成为应用开发的重要方式之一。而AI技术的快速发展让智能化应用成为可能。通过微信云开发&#xff08;CloudBase&#xff09;与小程序结合&#xff0c;开…

如何高效获取Twitter数据:Apify平台上的推特数据采集解决方案

引言 在数据分析和市场研究领域&#xff0c;Twitter&#xff08;现在的X&#xff09;数据一直是重要的信息来源。但是&#xff0c;自从Twitter更改API定价策略后&#xff0c;获取数据的成本大幅提升。本文将介绍一个经济实惠的替代方案。 为什么需要Twitter数据&#xff1f; …

MySQL基础大全(看这一篇足够!!!)

文章目录 前言一、初识MySQL1.1 数据库基础1.2 数据库技术构成1.2.1 数据库系统1.2.2 SQL语言1.2.3 数据库访问接口 1.3 什么是MySQL 二、数据库的基本操作2.1 数据库创建和删除2.2 数据库存储引擎2.2.1 MySQL存储引擎简介2.2.2 InnoDB存储引擎2.2.3 MyISAM存储引擎2.2.4 存储引…

让PPT不再“难搞”:智能工具如何改变办公体验

PPT的世界是一场属于设计感与逻辑力的双重较量。那些字体配色的小心思&#xff0c;排版设计的大考验&#xff0c;无不让人抓耳挠腮。然而&#xff0c;科技的加持让这一切正悄然改变。比如&#xff0c;随着 ai生成ppt 工具的兴起&#xff0c;许多复杂操作正被重新定义&#xff0…

springboot422甘肃旅游服务平台代码-(论文+源码)_kaic

摘 要 使用旧方法对甘肃旅游服务平台的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在甘肃旅游服务平台的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的…

HTML、CSS表格的斜表头样式设置title 画对角线

我里面有用到layui框架的影响&#xff0c;实际根据你自己的框架来小调下就可以 效果如下 上代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wi…