4000字教你如何创建一个基于Redis构建微服务的反应式架构
mhr18 2025-03-19 00:12 25 浏览 0 评论
如何使用 Redis 的特性来生成反应式数据流?
Redis 是我遇到的最强大、最通用的技术之一。可悲的是,大多数人只知道它是因为它是一个很好的缓存解决方案。我们需要解决这个问题。
特别是,我想向您展示您可以创建一个以 Redis 作为主要组件的反应式架构。这是一个巨大的优势,特别是如果您由于其他要求(即好的 ol'cache)已经将它作为基础架构的一部分。
您使用 Redis 与我将在此处描述的功能进行交互的方式取决于您,老实说,此时任何选项都与下一个选项一样有效。我倾向于使用 Node.js,但这就是我,你可以自由使用最适合你的东西。
构建反应式架构
这里首先要了解什么是反应式架构,为什么我们要构建一个而不是采用更传统的方法?
简而言之,反应式架构是在满足所有前提条件的那一刻开始执行每一位逻辑的架构——我想我应该在“简单”这个词周围加上引号。
让我换一种说法:当您需要在特定事件发生后触发逻辑时,您有两种选择:
- 定期检查某种标志,直到它打开,这意味着事件发生了。
- 坐等,直到其他东西通知您的服务该事件已触发。
第二部分是面向对象编程中观察者模式的关键。观察到的对象让对其内部状态感兴趣的每个人都知道,它实际上已更新。
我们在这里尝试做的是将相同的 OOP 模式外推到架构级设计中。因此,与其在我们的程序中加入一些逻辑,我说的是一旦正确的事件发生,就会触发服务的功能。
这是分发和扩展平台的最有效方式,因为:
- 您不必浪费时间和网络流量轮询特定标志的数据源(或您认为应该轮询的任何内容)。此外,如果您使用的是按使用付费的基础架构,则不需要的轮询可能会导致额外费用,在目标服务上进行不必要的工作,并且如果在您的代码等待轮询期间发生多个事件,您可能最终不得不聚合事件.
- 您可以通过添加新服务、并行工作和尽可能快地捕获事件来扩展服务的处理能力。
- 平台更稳定。通过被动工作,您可以确保您的服务以最佳速度运行,而不必担心由于来自客户端的数据过载而崩溃。
反应式平台本质上是异步的,因此任何尝试使用它们的客户端应用程序也需要适应相同的范例。外部 API 可能是通过 HTTP 实现的 REST,但这并不意味着您将获得作为响应的答案,相反,您将获得一个200 OK响应,这意味着您的请求已被接收。为了让您的应用程序获得实际结果,它必须订阅将包含此类响应的特定事件。
请记住这一点,否则,您将花费很长时间来调试为什么没有得到您想要的响应。
那我们需要什么?
撇开这一点,我们需要什么才能使我们的平台/架构成为反应式平台/架构?它不是 ReactJS,这是肯定的。我们需要一个消息代理,它可以集中多个服务之间的消息分发。
有了可以充当代理的东西,我们需要确保我们的代码的编写方式可以通过让代理知道它在哪里以及它需要的事件类型来订阅某些事件。
之后,将向我们的服务发送通知,并触发我们的逻辑。
听起来很简单吧?那是因为它就是!
那么 Redis 是如何考虑的呢?
Redis 不仅仅是一个键值内存存储,事实上,它有 3 个我喜欢它的特性,允许我根据不同的预期行为创建反应式架构。
这3个特点是:
- 发布/订阅。Redis 内部有一个消息队列,它允许我们发送消息并将它们分发给每个订阅的进程。这是一种即发即弃的合约,这意味着如果没有监听器处于活动状态,那么消息就会丢失。所以在使用这个频道时要考虑到这一点。
- 键空间(KeySpace)通知。可能是我最喜欢的 Redis 功能。这些坏男孩是由 Redis 本身创建的事件,并分发给决定订阅它们的每个进程。它们与键空间的变化有关,这意味着您存储在其中的数据发生的任何事情。例如,当您删除或更新密钥时,或者当其 TTL 计数器达到 0 时自动删除。这允许您生成定时事件。在“某事”发生 3 天后,您是否必须触发一些逻辑?这是如何。
- Redis 流。这是 Redis 数据类型的混合体,混合了键空间通知和发布/订阅,所有这些组合在一起并且运行良好。Streams 尝试模拟tail -f命令在您的终端上的行为。如果您从未见过该命令,那么这是一个 *nix 命令,它显示文件的最后一行,并持续监听文件的更改,以便在您添加新行时,它会立即列出。流也会发生同样的情况。考虑到正确的用例,它们非常强大且非常有用。您可以在此处阅读有关它们的更多信息。
所有这些功能都允许您以一种或另一种方式与您的流程进行通信,并且根据您所追求的行为类型,您可能想要解决其中一个或全部。
让我们快速浏览一些示例,让您了解使用什么以及何时使用。
经典的基于事件的消息传递
最简单的例子是每个微服务都在等待某事发生。要触发的事件,该事件可能来自外部,即系统的用户或客户端。
看上图,把中央的红管看成是Redis的Pub/Sub或者Blocking list,这是一个更可靠的Pub/Sub的自定义实现。
流程从 #1 开始,由“客户端应用程序”提交请求,并在 9 点结束,“客户端应用程序”收到有关响应的通知。其余的部分?我不在乎,客户端应用程序也不应该在乎。
这是这种范式的优点之一,该架构成为客户端的黑匣子。单个请求可以触发数百个事件或仅触发一个,行为将是相同的:一旦响应准备就绪,它将被传递给客户端。而不是客户端知道需要多长时间或多久需要检查它是否准备好。这些都不重要。
请记住以下注意事项:
- 消息由其订阅者发布到“通道”中。如果您想发布不同类型的主题,建议您拥有不同的频道。此外,如果您需要额外的粒度来区分哪个消费者必须负责处理一条特定的消息,则详细信息将需要成为消息的一部分。这是因为一个频道的所有订阅者都将获得相同的消息,因此如果您有多个进程侦听并获得相同的消息,您最终可能会重新执行相同的操作。可以在 Redis 中使用消息的 ID 实现一个标志(例如),以确保创建它的第一个进程是负责处理事件的进程,而其余进程可以忽略它。这是一种可靠的方法,因为在 Redis 中设置密钥是一个原子过程,
- 如果没有订阅者收听某个特定频道,则发布的消息将丢失。如果您使用 Pub/Sub 模式就是这种情况,因为它在“即发即忘”机制下工作。如果您想确保您的邮件在处理之前一直保留在那里,您可以使用“阻止列表”方法。该解决方案包括直接在 Redis 的键空间上创建一个列表(即一个普通的值列表),并让进程订阅以获取有关该键的键空间通知。这样他们就可以决定如何处理插入的数据(即如果他们想忽略它,处理它并删除它等)。
- 如果您要发送复杂的消息,例如 JSON,则需要对其进行序列化。这是因为对于阻止列表和 Pub/Sub,您唯一可以发送的是字符串。话虽如此,如果您需要在没有序列化的情况下通过线路发送复杂类型,您可以考虑使用 Redis Streams,这是它们允许的。当然,这里的限制是唯一允许的类型是 Redis,而不是您用来编写解决方案的语言的类型。
现在让我们看看如果您的事件触发取决于某些时间会发生什么。
基于时间的触发
反应式架构的另一个常见行为是能够在预定义的时间过去后触发某些事件。例如:在发现数据问题 10 分钟后触发警报。或者等待 30 分钟,然后触发 IoT 设备已停止发送数据的警报。
这些通常是与现实世界的限制相关的行为,需要一些时间来解决,或者甚至可以通过“稍等片刻”并重新开始倒计时来解决自己的问题(例如连接不可靠的物联网设备) )。
对于这种情况,架构保持不变,唯一的区别是中央通信集线器肯定使用来自 Redis的键空间通知。
您会看到,您需要了解有关 Redis 的两个主要功能才能实现这一目标:
- 设置键值对时,您可以选择以秒为单位定义 TTL(生存时间)。这就变成了倒计时,一旦达到 0,密钥将自动销毁。
- 当您订阅一个键空间时(这也适用于 pub/sub,但我们在这里没有使用它),您可以使用模式进行订阅。换句话说,您可以订阅“last_connection_time_of_device*”,而不是订阅键“last_connection_time_of_device100002”的事件。然后,一旦发生某些事情,创建的每个与该模式匹配的密钥都会通知您。
考虑到这两点,您可以创建订阅这些特定键的服务,并在它们被删除后(即事件被触发时)做出反应。同时,您让生产者不断更新密钥,这也会重置 TTL 计时器。
因此,如果您正在跟踪设备上次发送其心跳的时间,则可以像我上面显示的那样为每个设备设置一个密钥,并在每次获得新的心跳时更新该密钥。一旦 TTL 结束,这意味着您在配置的时间内没有收到新的心跳。您订阅的进程将只接收密钥名称,因此如果您只需要设备的 ID,您可以像我展示的那样构造您的密钥,并解析名称以捕获所需的信息。
影键技术
另一方面,如果您在该键中保存了一个复杂的结构并且需要它,则必须稍微更改此方法。这是因为当 TTL 到期时,密钥将被删除,从而删除其中的数据,因此您无法真正检索它。这时,您可以使用一种称为“阴影键”的技术。
影子键本质上是用于触发事件的键,但这实际上是在隐藏包含您需要的数据的实际键。回到我们的例子,假设生产者每次收到心跳都会更新 2 个键:
- “last_connection_time_of_device100002”带有最后从设备接收到的有效负载的unix时间戳。
- “device_data_id100002”带有来自设备的额外信息。
在这两个键中,只有第一个也有 TTL,第二个没有。
因此,当您收到过期通知时,您将从过期密钥 (
last_connection_time_of_device100002) 中获取 ID 并使用它来读取第二个密钥的内容。
然后,如果需要,您也可以继续删除其他密钥,或者将其保留在那里,无论对您的用例是否有效。
这里需要考虑的唯一警告是,如果您在集群模式下配置了 Redis,则密钥空间通知不会在整个集群中传播。
这意味着您必须确保您的消费者连接到每个节点。其中一些通知会丢失,否则没有人会收到它们。这是这种技术的唯一缺点,但在您花几天时间调试异步逻辑之前了解它很重要(去过那里,做过)。
如您所见,两种情况下的复杂性都降低到只需确保您订阅正确的事件或分发渠道。
例如,如果您要尝试使用普通 SQL 数据库执行此操作,则必须围绕代码创建大量逻辑,以有效确定何时输入新数据或何时删除一条信息。
相反,这里的所有复杂性都由 Redis 抽象出来,您需要担心的只是编写业务逻辑。那对我来说就是黄金。
原文:
https://www.jdon.com/57489
相关推荐
- 【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...
- Pure Storage推出统一数据管理云平台及新闪存阵列
-
PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...
- 对Java学习的10条建议(对java课程的建议)
-
不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...
- SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!
-
官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...
- JDK21有没有什么稳定、简单又强势的特性?
-
佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...
- 「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了
-
在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...
- Java面试题及答案最全总结(2025版)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...
- 数据库日常运维工作内容(数据库日常运维 工作内容)
-
#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...
- 分布式之系统底层原理(上)(底层分布式技术)
-
作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...
- oracle 死锁了怎么办?kill 进程 直接上干货
-
1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...
- SpringBoot 各种分页查询方式详解(全网最全)
-
一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...
- 《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略
-
《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...
- LoadRunner(loadrunner录制不到脚本)
-
一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...
- Redis数据类型介绍(redis 数据类型)
-
介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...
- RMAN备份监控及优化总结(rman备份原理)
-
今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- 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)