一种使用 Redis 深度驱动的,为构建轻量级分布式应用程序(Microservices)的工程方案(二)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
日志服务 SLS,月写入数据量 50GB 1个月
简介: 一种使用 Redis 深度驱动的,为构建轻量级分布式应用程序(Microservices)的工程方案(二)

Service Discovery(服务发现)



接下来,让我们考虑服务发现,这是任何微服务架构的另一个必备功能。

通过名称发现服务的 IPPORT 位置的能力极大地简化了通信。其他好处包括不必管理 DNS 条目或创建固定的路由规则。


服务发现信息以一种 “nodes” 的形式存储在 Redis Hash 中。使用 Hash 可以实现快速的查找。我们使用 Redis 的“hget”“hset”“hgetall” 命令来处理 nodes hash。


微信图片_20220610213042.png


以下 Redis 操作可用于实现服务发现。首先是对特定服务类型的查找。第二个是查找可用实例。第三次查找,允许Hydra检索有关特定服务实例的信息。

我们可以看到有用的信息,例如服务的版本,instanceID,IP地址和端口,最后还有主机名。在此示例中,主机名也恰好是Docker 容器 ID


微信图片_20220610213057.png


我们可以使用 Redis “hgetall” 命令检索有关所有可用实例的信息。这就是 Hydra Router 如何检索要显示在其仪表板上的服务列表。

微信图片_20220610213108.png


让我们回顾一下。Hydra 使用 servicename key 段进行查询,以发现有关服务的各种信息。可以使用 Redis Hash 管理服务详细信息,该服务可提供快速的服务发现

接下来,让我们考虑路由。


Routes(路由)



同时路由 HTTP 和消息(例如 Web Socket 或 PubSub )- 要求对 routes 进行验证。微服务可以发布其 routes 到 Redis。举个例子,HydraRouter 使用发布的 routes 来实现动态的服务感知路由。


每个服务以 “service:routes” 类型的 key 发布其路由。在这里,我们看到 “asset-svcs” 路由的 key


微信图片_20220610213125.png


服务路由存储在 Set 结构中。非常适合,因为您不想重复输入路由条目。使用 SADDSMEMBERS 命令。


回到我们的 routes 上。我们可以使用 key 模式拉出路由列表。在这里我们可以看到许多服务的路由。


微信图片_20220610213136.png


我们可以使用 “smembers” 命令查看特定路由集的内容。顺便说一下,括号中的 [get][post][put] 位表示 HTTP REST 端点。对于其他消息传递传输,可以省略括号方法的使用。


让我们回顾一下。每个服务都会向一个 Redis Set 发布它的路由。访问一个单独的路由会显示该服务的路由条目集合。


路由使用 Set 数据结构存储在 Redis 中,这避免了重复的路由。发布的路由可用于实现动态的服务感知路由。接下来,让我们考虑负载平衡。


Load Balancing(负载平衡)



随着应用程序的增长,您将需要在可用的服务实例之间平衡请求。这是通过使用我们看到的服务呈现(service presence)和路由(routing)功能完成的。在应用程序级别,使用 Hydra,这与使用 “makeAPIRequest”“sendMessage” 调用一样简单。当 Hydra 使用路由和 presence 信息在可用的目标实例中进行选择时,就会在这些调用中进行负载平衡。


一个很好的好处是,在路由过程中,如果某个请求在某个特定实例上失败,Hydra 可以在出现 HTTP 503 服务器不可用错误之前重试其他可用实例。


如您所见,负载平衡依赖于其他功能,例如 presence,服务发现和路由。


微信图片_20220610213154.png


回顾一下,可以使用我们已经看到的 Presence、服务发现(Service Discovery)和路由(Routing)特性来完成服务之间的负载平衡请求。Redis Strings,Hashes 和 Sets 使这成为可能。整体大于部分之和。


Messaging(消息)



分布式服务强制通过底层网络彼此通信。HTTP Rest 调用可能是最常见的,但是 socket 消息传递可能更有效。Hydra 中的消息传递是通过 Redis 的 Pub/Sub 通道完成的,而 Redis 通过 socket 连接实现了 Pub/Sub


这里有一个例子。Hydra 使用 Redis 的 “subscribe”、“unsubscribe” 和 “publish” 命令。


微信图片_20220610213219.png


顺便说一句,Hydra router 能够通过 HTTP 和 WebSocket 接受消息并将其转换为 pub/sub 消息。


要了解其工作原理,请考虑两个服务,即 “asset-svcs”“project-svcs”。每个服务创建两个 key,一个使用服务名(service name),另一个使用服务名(service name)和实例ID(instance ID)。每个服务都监听两个 channel


微信图片_20220610213239.png

在大多数情况下,您并不关心哪个服务实例处理请求。在这些情况下,将使用没有特定实例ID的通道。


现在,当您需要向特定实例发送消息时,可以使用具有实例ID的通道。需要特别注意的是,hydra 在负载均衡时会将请求转换为具有特定实例ID的服务名称。这样可以确保只有一个实例可以处理给定的消息或请求。


我们可以使用 Redis pub/sub channels 命令查看 channel key 列表。注意这里有四个 key。第一个 key 是 “asset-svcs” 的名称 —— 由 asset service 的所有实例共享。接下来,我们将看到三个具有惟一实例id的附加 key。三个服务实例各有一个。


微信图片_20220610213253.png


继续关注消息传递。为了确保微服务之间的互操作性,必须标准化共享的通信格式。通用消息格式是已记录的基于JSON的格式,其中包括对消息传递,路由和排队的支持。这些消息作为JSON字符串文本存储在Redis中。

继续关注消息传递。为了确保微服务之间的互操作性,必须对共享的通信格式进行标准化。通用消息格式是一种文档化的 JSON-based 的格式,包括对消息传递(messaging)、路由(routing)和队列(queuing)的支持。这些消息作为 JSON 字符串文本存储在 Redis 中。

下面是一个示例 UMF 消息。

微信图片_20220610213346.png


“to”“frm”“bdy” 字段是必填字段,服务可以自由地在 “body” 对象中包含自己的自定义字段。

让我们看看如何在实践中使用它。

在左边,“client-svcs”“project-svcs” 发送消息。注意,这只需要一个 UMF 创建调用和一个发送消息调用,这里用黄色显示。

在右边 —— “project-svcs” 侦听消息并根据需要进行处理。这是使用事件消息侦听器完成的。


微信图片_20220610213420.png


请注意,Hydra 抽象了服务发现(service discovery)、负载平衡(load balancing)、路由和发布/订阅(pub/sub)等细节。发送和接收消息只涉及三个成员函数。在这里稍作停留是值得的。花几秒钟考虑一下使用您最喜欢的堆栈时这个示例会是什么样子。

让我们仔细看看。Send message 通过解析消息中的 “to” 字段来确定目标服务名称。有了服务名,下一步是检查可用的实例。有了目标实例,消息就会被字符串序列化,并通过 Redis 的 “publish” 命令发送。


微信图片_20220610213432.png


同样,我们可以列出Redis中的所有发布/订阅通道(Pub/Sub Channnel)。消息可以通过这些通道发送,并由侦听器(listeners)检索。因此,只需编写一些编程代码,我们就可以使用 Redis 通过组织良好的通道集合(collection of channels)来路由消息。


微信图片_20220610213448.png


总而言之,值得注意的是,由于服务是物理分布的,因此最终需要进行消息传递。Redis 使用其发布/订阅(pub/sub)功能启用消息传递。

标准化通信可以实现服务之间的互操作性。我们还看到,当我们抽象出底层服务发现(service discover)、负载平衡(load balancing)、 路由(routing)和发布/订阅(pub/sub)细节时, 在应用程序级别上的通信是多么容易。

接下来,让我们考虑消息队列。


Queuing(队列)



作业(Job)和消息队列(message queues)是许多重要应用程序的另一个重要部分。Hydra 使用 Redis 为每种服务类型维护动态队列(dynamic queues)。

然后,服务实例可以读取其队列和处理项目。


队列消息的内容是UMF消息,遵循用于消息传递的相同格式。同样,互操作性为王!

Hydra 会为每种服务类型自动创建三个队列。


  • “已接收(received)”队列
  • “进行中(inprogress)”队列
  • 还有一个“不完整(incomplete)”队列。


因为这些是列表,我们使用 Redis 的 “lpush”“rpush”“rpoplpush”“lrem” 命令。


下面的图表显示了队列之间的消息流。在 Redis 中,在队列之间移动项目是一个原子操作。所以不管你有多少微服务,它都是安全的。


微信图片_20220610213516.png

在下一个左边的示例中, 对消息进行排队就像创建一个 UMF 消息并调用 “queueMessage” 来发送它一样简单。右下角的代码显示了图像处理服务通过调用 “getQueuedMessage”, 然后在处理完消息后调用 “markQueueMessage”,使消息脱离队列。很简单吧?


微信图片_20220610213528.png


因此,回顾一下,有时无法期望立即做出回应。在这种情况下,我们只需要排队等待后续处理。 Redis List 数据结构可以用作消息队列。使用原子操作的 “lpush”“rpoplpush” 之类的命令使此操作可行。再次在这里,我们看到了使用高级抽象进行基本排队有多么容易。


Logging(日志记录)



分布式日志记录(Distributed logging)是任何微服务体系结构的另一个重要特征。但是,如果您知道 Redis,可能会对将其用作分布式记录器(distributed logger)感到震惊。您可能会理所当然地担心。但是,您可以将其用作飞行记录器(flight recorder)。仅存储最严重的错误,并使用 “lpush”“ltrim” 限制条目的数量。然后,至少您将有一种快速的方法来检查微服务可能出了什么问题。

这是 key 的样子。注意,key 类型为 health:log


微信图片_20220610213553.png


在这里,我们可以看到 health:log key 类型实际上是一个 “List” 数据结构。所以我们可以使用 Redis 的 “lrange” 命令来查看 “imageproc-svcs” 的飞行记录器(flight recorder)日志。

微信图片_20220610213607.png


总结:使用微服务无法登录数十台或更糟的数百台计算机。分布式日志记录绝对是必经之路。使用 Redis,您可以构建一个轻量级的记录器(light-weight logger)以用作飞行记录器(flight recorder)。使用 Redis List 数据结构以及方便的 “lpush”“ltrim” 命令可以实现此目的。

最后,让我们考虑配置管理。


Configuration management(配置管理)



管理分布式微服务的配置文件可能具有挑战性。然而,你甚至可以使用 Redis 来存储你服务的配置文件。但这并不理想,得远离,核心缺点是在 Redis 中存储配置会使 Redis 有状态。但这是可以做的。


让我们看看它是如何工作的。configs key 类型是一个 hash。该 hash 的 key 由服务版本和设置为该版本配置数据的值组成。


微信图片_20220610213624.png

下面是一个配置示例。在我们的示例中,我们使用名为 “hydra-cli” 的命令行工具, 它允许我们将配置文件推到特定的服务版本。所做的一切就是创建一个 hash 条目,其键由服务名称和版本组成, 并将文件内容字符串序列化后(stringified)作为其值。记住,你也可以使用 shell 脚本来驱动 redis cli。


我们可以使用 “hget” 命令和配置的版本提取一个特定的版本。


微信图片_20220610213637.png


让我们快速回顾一下,我们了解了 Redis 如何用于存储应用程序配置文件。 Redis Hash 数据结构允许我们存储每种服务类型的配置。每个配置条目均由服务版本标签索引,并且内容仅指向字符串化的 JSON 配置。


总结



这里分享的是一种大量地使用 JavaScript 和 NodeJS 来利用 Redis 构建分布式应用程序的工程方案。但是,你完全可以用其他你爱的语言(如:Golang)对 Redis 做同样的事情。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6天前
|
存储 缓存 NoSQL
云端问道21期方案教学-应对高并发,利用云数据库 Tair(兼容 Redis®*)缓存实现极速响应
云端问道21期方案教学-应对高并发,利用云数据库 Tair(兼容 Redis®*)缓存实现极速响应
|
1月前
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
163 5
|
2月前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
87 8
|
28天前
|
存储 监控 NoSQL
Redis集群方案汇总:概念性介绍
本文介绍了Redis的三种高可用和分布式解决方案:**Redis Replication(主从复制)**、**Redis Sentinel(哨兵模式)** 和 **Redis Cluster(集群模式)**。Redis Replication实现数据备份和读写分离,适合数据安全和负载均衡场景;Redis Sentinel提供自动故障转移和监控功能,适用于读写分离架构;Redis Cluster通过分布式存储和自动故障转移,解决单点性能瓶颈,适合大规模数据和高并发场景。文中还详细描述了各方案的工作原理、优缺点及适用场景。
36 0
|
2月前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
70 16
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
55 5
|
3月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
1月前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
175 85
|
3月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
92 6
|
6天前
|
缓存 NoSQL 关系型数据库
云端问道21期实操教学-应对高并发,利用云数据库 Tair(兼容 Redis®)缓存实现极速响应
本文介绍了如何通过云端问道21期实操教学,利用云数据库 Tair(兼容 Redis®)缓存实现高并发场景下的极速响应。主要内容分为四部分:方案概览、部署准备、一键部署和完成及清理。方案概览中,展示了如何使用 Redis 提升业务性能,降低响应时间;部署准备介绍了账号注册与充值步骤;一键部署详细讲解了创建 ECS、RDS 和 Redis 实例的过程;最后,通过对比测试验证了 Redis 缓存的有效性,并指导用户清理资源以避免额外费用。

热门文章

最新文章