🚀 扩展至 93K RPM:将配额管理从 SQL 移至 Redis

发布: (2026年1月15日 GMT+8 12:41)
3 min read
原文: Dev.to

Source: Dev.to

发生了什么?

你最喜欢的艺术家宣布即将举办演唱会,顾客们抢购门票。电子票务平台开始返回错误并变得异常缓慢。

根本原因是数据库 CPU 使用率飙升至 100 %,因为用于统计活动配额的单个“热点”行被持续查询和更新。表结构如下:

eventIdshowtimeIdquotareserved
1115,00010,000

每个请求都会读取并写入这行数据,导致锁争用并耗尽 CPU 资源。

解决方案

将配额计数器迁移到 Redis

Redis 将数据存储在内存中,延迟远低于基于磁盘的数据库。一个朴素的实现可能如下所示:

function reserveTicket(showtimeId, amount) {
    const reserved = parseInt(redis.get('{key}'));
    if (reserved  {
        // …order creation logic…
        const result = await redis.eval(reserveLuaScript, {
            keys: ['{key}'],
            arguments: [String(amount), String(quota)],
        });
        if (result !== 1) {
            throw error('reservation failed');
        }
    });
    // …other logic…
}

将计数持久化回数据库

因为 Redis 是缓存,权威的真相来源仍然是关系型数据库。后台工作线程每 5 秒轮询一次 Redis,并将当前计数写回数据库,从而在不牺牲性能的前提下实现最终一致性。

结果

  • 每分钟订单量从 5,000 提升至 93,240
  • 数据库负载显著下降,CPU 瓶颈被消除。
  • 系统现在能够可靠地处理高峰售票流量。

关键要点

  • 诊断性能问题的真实原因;本例中是热点行导致的 DB 锁争用。
  • 将系统设计与实际使用模式对齐——在高吞吐场景下,热点行需要特殊处理。
  • 使用 Redis(或其他内存存储)配合原子 Lua 脚本安全地管理计数器。
  • 保持关系型数据库作为真相来源,并通过异步同步来保证持久性。
Back to Blog

相关文章

阅读更多 »

Rapg:基于 TUI 的密钥管理器

我们都有这种经历。你加入一个新项目,首先听到的就是:“在 Slack 的置顶消息里查找 .env 文件”。或者你有多个 .env …

技术是赋能者,而非救世主

为什么思考的清晰度比你使用的工具更重要。Technology 常被视为一种魔法开关——只要打开,它就能让一切改善。新的 software,...

踏入 agentic coding

使用 Copilot Agent 的经验 我主要使用 GitHub Copilot 进行 inline edits 和 PR reviews,让我的大脑完成大部分思考。最近我决定 t...