Rails 8 移除 Redis,拥抱 SolidQueue:简化 Rails 应用架构
Rails 8 最新版本移除了 Redis 作为标准技术栈的一部分,不再依赖它来执行任务队列、缓存数据和发送实时消息。取而代之的是 Rails 的新功能:SolidQueue 用于任务队列,SolidCache 用于缓存,以及 SolidCable 用于处理 ActionCable 消息,它们均运行在应用程序现有的关系型数据库服务上(例如 PostgreSQL、SQLite 或 MySQL)。这意味着大多数 Rails 应用可以移除 Redis。
虽然 Redis 是一种快速、高效、可靠的关键值存储,被广泛应用于 Rails 任务队列和缓存,但它确实增加了复杂性。SolidQueue、SolidCache 和 SolidCable 的出现让作者意识到,关系型数据库表等“平庸的技术”也可以胜任专门解决方案的任务。
Redis 的真正成本
除了月度托管费用,Redis 还涉及部署、版本控制、补丁和监控服务器软件;配置持久化策略(RDB 快照、AOF 日志或两者结合);设置内存限制和驱逐策略。 此外,还需要维护 Rails 和 Redis 之间的网络连接、身份验证 Redis 客户端、构建高可用性 (HA) Redis 集群,以及协调部署生命周期。 出现问题时,需要同时调试 Redis 和关系型数据库,切换不同的查询语言和工具,以及维护两套备份策略。
相比之下,无 Redis 的 Rails 架构更简单:如果 Rails 或 PostgreSQL 出现故障,一切都会停止。
SolidQueue 的工作原理
SolidQueue 使用关系型数据库 (PostgreSQL) 替代了 Redis。PostgreSQL 9.5 引入了 FOR UPDATE SKIP LOCKED 语句,允许数据库支持高并发的数据库后台任务队列。
当 worker 需要任务时,会执行以下 SQL 查询:
SELECT * FROM solid_queue_ready_executions
WHERE queue_name = 'default'
ORDER BY priority DESC, job_id ASC
LIMIT 1
FOR UPDATE SKIP LOCKED
SolidQueue 的架构基于三个表:
solid_queue_jobs: 存储所有任务的元数据,如任务名称、Ruby 类和时间戳。
solid_queue_scheduled_executions: 存储计划任务,等待其到达执行时间。
solid_queue_ready_executions: 存储准备就绪的任务,等待 worker 领取。
这些表的快速读写可以由 PostgreSQL 的 MVCC 设计轻松处理。
协调这些流程的是几个进程:
- Workers: 以可配置的间隔(最快 0.1 秒)轮询
solid_queue_ready_executions。
- Dispatchers: 每秒轮询
solid_queue_scheduled_executions,将到期的任务移到 ready 表。
- Schedulers: 管理循环任务,按照定义的计划将任务入队。
- Supervisor: 监控所有进程,跟踪心跳并重启崩溃的进程。
Recurring Jobs (循环任务)
SolidQueue 内置了 Cron 风格的循环任务功能,无需额外库。 配置位于 config/recurring.yml。
Job Concurrency (任务并发)
SolidQueue 允许限制单个任务的并发性,通过 limits_concurrency 参数实现。 例如,限制 ProcessUserOnboardingJob 任务的用户并发数为 1,持续 15 分钟。
Mission Control 监控
SolidQueue 提供 Mission Control Jobs,一个免费、开源的监控工具,用于查看任务状态、检查失败的任务、重试和丢弃任务、可视化计划任务时间表,以及管理队列。
迁移路径
迁移到 SolidQueue 的步骤包括:
- 将 Rails 队列适配器设置为
:solid_queue。
- 安装 SolidQueue gem 并运行数据库迁移。
- 将 Sidekiq-cron 的计划转换为 config/recurring.yml。
- 更新 Procfile 以启动 SolidQueue。
- 移除 Redis 和 Sidekiq 相关的 gem。
何时不使用 SolidQueue
如果应用需要处理数千个任务/秒,需要低于 1 毫秒的任务延迟,或者需要复杂的 pub/sub 模式或高强度计数器,则可能仍然需要 Redis。
总结
对于大多数 Rails 应用,SolidQueue 提供了一种更简单、更易于维护的替代方案,可以移除 Redis 并简化应用程序架构。