Hashnode 构建可扩展的事件驱动架构 (EDA) 用于生成用户动态数据
Hashnode 为数千名用户构建了一个基于事件驱动架构 (EDA) 的可扩展系统,用于生成用户动态数据。该公司采用了 AWS 的无服务器服务,包括 Lambda、Step Functions、EventBridge 和 Redis Cache。该解决方案利用了 Step Functions 的分布式映射功能,支持高并发处理。
背景与问题
Hashnode 之前曾实现了一个个性化用户动态数据的解决方案,但很快发现该方案存在页面加载速度较慢的问题,并且由于动态生成用户动态数据时执行昂贵的查询,存在数据库不稳定性的潜在风险。Hashnode 的软件工程师 Florian Fuchs 提出了优化动态数据计算的总体思路:通过预计算用户动态数据来优化页面加载速度,而不是每次用户访问时都进行计算,从而直接从缓存中返回动态数据,减少页面加载时间。
解决方案架构
工程师们使用 AWS Step Functions 实现了动态数据计算逻辑,并设计了两个工作流:
- 数据准备工作流:使用三个 Lambda 函数从数据库中提取相关数据,并将其存储在 AWS ElastiCache (Redis) 缓存中。
- 动态数据计算工作流:根据缓存中是否存在用户元数据,动态数据计算逻辑可以完全基于 Redis 缓存中的元数据,或者需要从数据库中提取用户元数据。
在新架构中,动态数据的重新计算由以下事件触发:
- 帖子创建或更新时,通过 AWS EventBridge 发布事件。
- 定期通过 EventBridge Scheduler 触发。
Step Functions 的分布式映射功能
Hashnode 团队利用了 Step Functions 中的 Map 状态来编排并行工作负载。Map 状态支持两种模式:
- 默认内联模式:支持有限的并发,仅接受 JSON 数组作为输入。
- 分布式模式:适用于大规模并行工作负载,支持处理存储在 S3 中的数据源。在分布式模式下,Step Functions 可以运行超过 10,000 个并行子工作负载。
具体实现
解决方案中使用了两个 Step Functions,均采用分布式模式的 Map 状态:
- 一个用于处理有缓存元数据的用户。
- 另一个用于处理没有缓存元数据的用户。
开发人员报告称,目前对数千名用户的动态数据完全重新计算仅需 26 秒。团队还实现了定期缓存清除逻辑,以确保旧的缓存数据被定期清除。
总结
Hashnode 通过使用 AWS 的无服务器服务和 Step Functions 的分布式映射功能,成功构建了一个高效且可扩展的动态数据生成系统。该方案显著提高了页面加载速度,并避免了数据库的潜在不稳定性问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。