【Redis】在不使用集群的情况下扩展 Redis
mhr18 2024-11-09 12:18 24 浏览 0 评论
探索无需集群即可扩展 Redis 的技术。发现有效的客户端分片和一致的哈希策略。
Redis 是一种流行的内存数据存储,以其速度和灵活性而闻名。当特定工作负载的内存和计算需求可以在单个节点内管理时,它就能高效运行。然而,超出单个节点的扩展通常会导致考虑 Redis 集群。人们普遍认为过渡到 Redis 集群很简单,现有应用程序的行为也将相同,但实际情况并非如此。虽然 Redis 集群解决了某些扩展问题,但它也带来了巨大的复杂性。这篇文章将讨论 Redis 集群扩展的局限性,并介绍一些可以满足许多组织需求的更简单的替代方案。
一、什么是Redis集群?
Redis 集群是一种分布式实现,允许您在多个主 Redis 实例之间自动共享数据,从而实现水平扩展。在 Redis 集群设置中,键空间被分为 16384 个哈希槽,有效地设置了16384个主实例的集群大小上限。然而,实际上,建议的最大大小约为 1000 个主实例。集群中的每个主实例管理这16384个哈希槽的特定子集。为了确保高可用性,每个主实例可以与一个或多个副本实例配对。这种方法涉及跨多个实例的数据分片以实现可扩展性和复制以实现冗余,是许多分布式数据存储系统中的常见模式。一个具有三个主 Redis 实例的集群,每个主实例有一个副本,如下所示:
正如您所看到的,Redis Cluster 具有优雅的设计。但在没有深入研究实现细节的情况下,我们已经介绍了多个概念(分片、哈希槽等),只是为了有一个基本的了解。我们将在下面探讨更多挑战。
二、水平扩展的挑战
虽然 Redis 集群通常被认为仅仅是独立 Redis 上的一个设置,但它在很多方面都有所不同。这意味着迁移到 Redis 集群充满了隐藏的挑战,即使是经验丰富的开发人员也会感到惊讶。
客户端库要求
从客户端库的角度来看,使用 Redis Cluster 需要适应不同的接口。这意味着您很可能需要使用特定于集群的客户端库 - 用于独立 Redis 的现有客户端将无法在集群中开箱即用。我们以go-redis Redis为例。当连接到独立的Redis时,可以使用以下代码片段连接到具有指定主机、密码和逻辑数据库的实例:
import "github.com/redis/go-redis/v9"
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // 未设置密码
DB: 0, // 使用默认逻辑数据库 0(稍后详细介绍)
})
同一个包提供了特定于集群的客户端,但需要注意的是,它们是不同的结构:redis.Client用于独立 Redis 和redis.ClusterClient用于 Redis 集群。与初始化过程redis.ClusterClient有所不同,如下所示。这种区别至关重要,因为redis.ClusterClient内部利用多个redis.Client对象来管理与集群中所有节点的通信。此设置中的每个redis.Client都维护其单独的连接池。
import "github.com/redis/go-redis/v9"
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{
"localhost:7001",
"localhost:7002",
"localhost:7003",
"localhost:7004",
"localhost:7005",
},
})
附带说明的是,该go-redis包还提供了一个redis.UniversalClient接口来简化初始化过程,但它只是不同类型客户端之上的一个抽象层。要使用 Redis 集群,需要开发如上所述的特定于集群的客户端来满足集群的其他要求。
多键操作
Redis 中的多键操作是指同时作用于多个键的命令或命令集。例如,该MSET命令是单个命令,可以在单个原子操作中将多个键设置为多个值。类似地,事务或 Lua 脚本通常涉及多个键,但并非总是如此。Redis 集群的一个关键限制是它无法处理多键操作,除非所涉及的键共享相同的主题标签,如此处规范中所述。您需要仔细检查应用程序中的所有多键操作,并且需要修改这些操作以避免使用多键操作或仅在同一主题标签的上下文中使用它们。
逻辑数据库
在 Redis 中,逻辑数据库本质上是同一 Redis 实例中的单独键空间。Redis 支持多个数据库,这些数据库由数据库索引(一个简单的整数)来标识。除非另有说明,Redis 客户端在连接时通常使用默认数据库 database 0。利用逻辑数据库可以是分离不同类型数据的有效策略(例如,将会话数据与应用程序数据隔离)。您可以使用该SELECT命令在不同的逻辑数据库之间进行切换。但是,正如SELECT命令文档中所指定的,您将失去 Redis 集群的这种隔离。因此,如果您要过渡到 Redis 集群,则需要从头开始完全重新构建键空间架构。
设置和维护的复杂性
上面我们讨论的只是应用层面。然而,集群的影响延伸到基础设施的复杂性和运营成本。
首先,启用 Redis 集群大大增加了基础设施的复杂性以及管理它的团队的运营负担。您不需要在单个 Redis 实例上监控指标和可用性,而是需要在数十个或数百个节点上进行监控。
其次,工作负载应该在集群中均匀分布,同时最大限度地减少特定实例中的热点。但实际上,这种情况并不经常发生。一个常见的误解是创建集群会自动导致所有分片之间的流量统一。然而,特定的时段几乎总是能比其他时段获得更多的流量。虽然 Redis 允许您对实例进行重新分片,但它没有自动重新平衡功能。
最后但并非最不重要的一点是,实例越多,潜在的故障点就越多。虽然集群在节点出现故障时提供故障转移功能,但成倍增加的风险是真实存在的。我们假设任何单个 Redis 实例发生故障的可能性为 0.01%。如果发生 100 次,这种可能性就会上升到 1-2%,这意味着更多的事故、消防演习以及可能的不眠之夜。
三、Redis 集群替代方案
考虑到 Redis 集群面临的挑战,值得考虑可以提供更简单的 Redis 扩展路径的替代方案。
应用级优化
调整应用程序对 Redis 的访问模式可以显着最小化工作数据大小。通过对键、数据结构和查询进行小幅调整,您可以从现有的 Redis 部署中获得更多收益。例如,在 Abnormal Security,他们将 64 个字符的密钥字符串缩短为 32 个字符。这减少了每个键的内存占用,使它们能够容纳多 15% 的键值对。然而,应用程序级优化并不总是可行的。深入研究优化过程后,有时会感觉您是在满足数据存储的需求,而不是利用它来支持您的业务目标。
内存有限的工作负载
如果吞吐量不是问题,并且您只需要更多内存,最简单的解决方案是升级到更高内存的实例。当然,这意味着这个更强大的实例附带的额外 CPU 将处于闲置状态,不会加入其中。有时付钱很烦人,但至少你没有为全球变暖做出贡献。
然而,由于 Redis 是单线程的,如果您的工作负载受 CPU 限制(例如,涉及大量解析和修改 JSON 数据),那么简单地添加更多 CPU 可能没有帮助。
数据分层到 SSD/闪存
Redis on Flash也称为数据分层,在 Redis 开源版本中不可用,是 Redis 托管解决方案中相对较新的功能。数据分层允许将 Redis 数据集中不经常访问的部分移动到附加到实例的 SSD 存储层。这为工作数据集提供了显着更多的内存容量(在某些云平台上,内存和 SSD 存储组合高达 2TB),同时将热数据集保留在低延迟主内存中。
由于闪存上的 Redis 将所有键保留在内存中,并且仅根据需要将值存储到磁盘,因此只有当您的键大小平均远小于值大小时,闪存上的 Redis 才是一个不错的选择。例如,如果 100 字节的密钥存储 120 字节的值,则使用闪存存储只能节省最少的内存。
此外,在 80% 的时间访问 20% 的数据集的通用原则适用于总数据量,包括键和值。因此,如果您仅检索 20% 的键,但这些键对应 80% 的值,则 Flash 上的 Redis 没有帮助。
除了上述技术之外,另一种选择是采用更现代的 Redis 实现。Dragonfly 是一种简单、高性能且经济高效的内存数据存储,提供与 Redis API 的完全兼容性。Dragonfly 允许您继续垂直扩展至多达 128 个内核和 1TB 内存。单个 Dragonfly 节点可以提供与 Redis 集群类似的规模,但不会增加操作复杂性和上面讨论的 Redis 功能限制。
Dragonfly的扩展能力
Dragonfly 是 Redis 的直接替代品,无需集群即可满足扩展需求。通过在单个节点上利用多线程无共享架构,Dragonfly 可以处理大量内存工作负载和流量峰值,否则需要集群。
Dragonfly 相对于集群设置的一些主要优势包括:
- 无需更改客户端库或应用程序代码
- 操作管理简单,无分片复杂性
- 由于需要更少的实例而节省成本
- 通过灵活的扩展避免性能热点
- 从任何 Redis 部署轻松迁移
将应用程序从 Redis 迁移到 Dragonfly 时,重要的是要认识到可能需要进行一些调整才能充分实现 Dragonfly 的优势。为单线程 Redis 构建的应用程序通常会针对最小并行度进行优化。相比之下,Dragonfly是多线程的。花时间调整客户端代码或配置以增加与 Dragonfly 的连接数量并将数据分散到更多键上可能是值得的。
四、结论
虽然水平扩展的需求在一定规模(通常是700GB或1TB内存)之后是不可避免的,但许多组织在耗尽垂直扩展选项之前过早地进行水平扩展。这导致工作负载出现不必要的操作复杂性,而这些工作负载本来可以放在一个功能强大的节点上。
对于许多用例来说,容量限制是理论上的,而不是实际的:即使你的业务增长了,有时你在Redis中保存数据的特定用例也会受到更多限制。
即使您最终必须横向扩展,您仍然希望使用具有16或32核的相对强大的实例,而不是将工作分散到数百个小实例上。在这种情况下,每个实例都成为潜在的薄弱环节:如果流量发生变化,或者吞吐量或负载突然激增,那么小实例将无法应对。
虽然Redis集群提供水平扩展,但它在复杂性和功能损失方面的成本很高。Dragonfly可以在单个实例上支持每秒数百万个操作和tb大小的工作负载,从而避免了集群解决方案的许多缺陷。
--END--
欢迎关注【辉哥传书vlog】头条号,喜欢记得点赞、收藏、评论、转发哦!
相关推荐
- Java培训机构,你选对了吗?(java培训机构官网)
-
如今IT行业发展迅速,不仅是大学生,甚至有些在职的员工都想学习java开发,需求量的扩大,薪资必定增长,这也是更多人选择java开发的主要原因。不过对于没有基础的学员来说,java技术不是一两天就能...
- 产品经理MacBook软件清单-20个实用软件
-
三年前开始使用MacBookPro,从此再也不想用Windows电脑了,作为生产工具,MacBook可以说是非常胜任。作为产品经理,值得拥有一台MacBook。MacBook是工作平台,要发挥更大作...
- RAD Studio(Delphi) 本月隆重推出新的版本12.3
-
#在头条记录我的2025#自2024年9月,推出Delphi12.2版本后,本月隆重推出新的版本12.3,RADStudio12.3,包含了Delphi12.3和C++builder12.3最...
- 图解Java垃圾回收机制,写得非常好
-
什么是自动垃圾回收?自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用...
- Centos7 初始化硬盘分区、挂载(针对2T以上)添加磁盘到卷
-
1、通过命令fdisk-l查看硬盘信息:#fdisk-l,发现硬盘为/dev/sdb大小4T。2、如果此硬盘以前有过分区,则先对磁盘格式化。命令:mkfs.文件系统格式-f/dev/sdb...
- 半虚拟化如何提高服务器性能(虚拟化 半虚拟化)
-
半虚拟化是一种重新编译客户机操作系统(OS)将其安装在虚拟机(VM)上的一种虚拟化类型,并在主机操作系统(OS)运行的管理程序上运行。与传统的完全虚拟化相比,半虚拟化可以减少开销,并提高系统性能。虚...
- HashMap底层实现原理以及线程安全实现
-
HashMap底层实现原理数据结构:HashMap的底层实现原理主要依赖于数组+链表+红黑树的结构。1、数组:HashMap最底层是一个数组,称为table,它存放着键值对。2、链...
- long和double类型操作的非原子性探究
-
前言“深入java虚拟机”中提到,int等不大于32位的基本类型的操作都是原子操作,但是某些jvm对long和double类型的操作并不是原子操作,这样就会造成错误数据的出现。其实这里的某些jvm是指...
- 数据库DELETE 语句,还保存原有的磁盘空间
-
MySQL和Oracle的DELETE语句与数据存储MySQL的DELETE操作当你在MySQL中执行DELETE语句时:逻辑删除:数据从表中标记为删除,不再可见于查询结果物理...
- 线程池—ThreadPoolExecutor详解(线程池实战)
-
一、ThreadPoolExecutor简介在juc-executors框架概述的章节中,我们已经简要介绍过ThreadPoolExecutor了,通过Executors工厂,用户可以创建自己需要的执...
- navicat如何使用orcale(详细步骤)
-
前言:看过我昨天文章的同鞋都知道最近接手另一个国企项目,数据库用的是orcale。实话实说,也有快三年没用过orcale数据库了。这期间问题不断,因为orcale日渐消沉,网上资料也是真真假假,难辨虚...
- 你的程序是不是慢吞吞?GraalVM来帮你飞起来性能提升秘籍大公开
-
各位IT圈内外的朋友们,大家好!我是你们的老朋友,头条上的IT技术博主。不知道你们有没有这样的经历:打开一个软件,半天没反应;点开一个网站,图片刷不出来;或者玩个游戏,卡顿得想砸电脑?是不是特别上火?...
- 大数据正当时,理解这几个术语很重要
-
目前,大数据的流行程度远超于我们的想象,无论是在云计算、物联网还是在人工智能领域都离不开大数据的支撑。那么大数据领域里有哪些基本概念或技术术语呢?今天我们就来聊聊那些避不开的大数据技术术语,梳理并...
- 秒懂列式数据库和行式数据库(列式数据库的特点)
-
行式数据库(Row-Based)数据按行存储,常见的行式数据库有Mysql,DB2,Oracle,Sql-server等;列数据库(Column-Based)数据存储方式按列存储,常见的列数据库有Hb...
- AMD发布ROCm 6.4更新:带来了多项底层改进,但仍不支持RDNA 4
-
AMD宣布,对ROCm软件栈进行了更新,推出了新的迭代版本ROCm6.4。这一新版本里,AMD带来了多项底层改进,包括更新改进了ROCm的用户空间库和AMDKFD内核驱动程序之间的兼容性,使其更容易...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)