知识库导读 · 约 1,671 字 · 预计推送 1 部分

导读:How Discord Scaled Elixir to 5,000,000 Concurrent Users 未开始

目录

题记与说明

元信息
标题How Discord Scaled Elixir to 5,000,000 Concurrent Users
作者Stanislav Vishnevskiy(Discord CTO & 联合创始人)
来源 URLhttps://discord.com/blog/how-discord-scaled-elixir-to-5-000-000-concurrent-users
发表日期2017-07-06
存档日期2026-11-04
标签Elixir、并发架构、系统设计、性能优化、工程取舍、Agent 系统

这篇讲什么

2017 年,Discord 冲到近 500 万并发用户、每秒数百万事件,CTO 亲述 Elixir/Erlang 技术栈在膨胀路上撞到的三个瓶颈及解法:消息扇出、热点共享数据、并发过载保护。主线只有一句话:性能问题不靠加机器解决,靠拆解成本结构、找到真瓶颈、再选或造合适的原语。

核心观点

1. 消息扇出 → 自研 Manifold。 单次 send/2 因 Erlang 去调度要 30~70μs,大 guild(如 /r/Overwatch,3 万在线)一次发布要 0.9~2.1s,guild 进程消息队列积压到要手动关功能。Manifold 把发送工作按远端节点分组、每节点内按核数一致哈希分片给子 worker,并行了 CPU 成本还顺带降低节点间流量,同时保住客户端依赖的事件线性一致性——send/2 的即插即用替代品。

2. 热点数据 → 共享只读堆。 一致性哈希环查找原走单进程 request/reply(约 12μs/次),session 节点重启光查询就要 30 秒;搬进 ETS 后仍有 17.5s,因为环很大、进出 ETS 的拷贝才是大头。最终借 mochiglobal 思路把环编译成常量函数、放进 VM 的只读共享堆,单次查找降到 0.3μs,总耗时压到 750ms,代价是重建模块最多 1 秒——环很少变,值得付。

3. 并发保护 → ETS 信号量。 修好热路径反而撤掉了天然背压:500 万 session 进程踩踏 10 个注册进程,超时重试无限堆积,队列膨胀到 OOM 整个 VM,级联宕机。他们明确拒绝熔断器(不想要"超时爆发后一段时间什么都不试"的状态),改用 :ets.update_counter/4 的原子条件自增做信号量,让注定失败的调用提前放弃。效果:之后一次下游崩溃中,session 服务"纹丝不动",几分钟内自愈。

最值得记住的 3 个数据/金句

对我的启发

适合谁读

后端/分布式系统工程师、Erlang/Elixir 使用者、设计 Agent 并发编排需要限流背压思路的人,以及想把架构决策写成好文章的每个工程师。

← 资料库今日播报 →