线上投票的流量并不均匀。活动开始和结束时,大量用户会在短时间内同时打开页面、提交投票、刷新排名。一次全国性活动的峰值可以集中在几分钟内,读请求远多于写请求,实时排名还要跟着票数一起变。如果接入、缓存、消息和数据库任何一层扛不住,页面就会变慢,投票也会超时。
投票咖面向这类短时高峰,用五层物理架构承接流量:阿里云应用型负载均衡(ALB)做弹性接入,弹性伸缩(ESS)按流量加减无状态应用,Redis Cluster 承担投票热路径,RabbitMQ 高可用队列把明细和统计从主链路里拆出去,MySQL 读写分离负责持久化和查询回源。下面按这五层说明各自的职责、数据支撑和高可用设计,以及它们如何一起支撑 100 万 QPS 以上的流量,并把系统端到端可用性做到 99.99%。
整体架构概述
投票咖面向大规模在线投票场景,业务特征为短时高频读、峰值突发写入、实时排名频繁更新。为承载单场活动峰值 100 万 QPS 以上的请求压力,系统采用“弹性接入—热路径缓存—异步削峰—读写分离持久化”的数据流设计,物理架构由五层核心组件构成:
- 阿里云应用型负载均衡(ALB)作为统一流量入口;
- 弹性伸缩(ESS)承载无状态应用层;
- Redis Cluster 承担投票热路径的实时读写;
- RabbitMQ 高可用队列承接异步消息传递;
- MySQL 读写分离负责数据持久化与查询回源。
五层协同支撑系统端到端可用性达到 99.99%,对应全年停机时间不超过 52.6 分钟,满足企业级投票平台对稳定性的严苛要求。
1. 五层职责
| 架构 | 职责 |
|---|---|
| ALB | 同城多可用区接入。请求只进健康实例,故障机器从服务器组摘除 |
| ESS | 无状态应用。初始 5 台,按流量加机器,分布在两个可用区 |
| Redis Cluster | 投票热路径:是否已投、次数、作品计数、实时排名。主从跨可用区 |
| RabbitMQ 高可用 | 3 节点仲裁队列,跨可用区,允许单节点故障。承接投票明细、统计、日志的异步传递 |
| MySQL 读写分离 | 主库承担批量写入和配置变更,只读实例承担主办方实时查询、导出和缓存回源 |
2. 第一层:ALB——同城多可用区弹性接入
ALB 是系统流量的第一道关口,承担将海量用户请求分发至后端健康实例的职责。投票咖将 ALB 实例部署在同城多个可用区,配合跨可用区故障转移能力,健康检查自动摘除异常节点后,流量可在秒级切换至其余可用节点。
在性能层面,ALB 单实例可支撑高达 100 万 QPS,基于 Tengine(Nginx 增强版)实现七层负载均衡,具备应用层内容路由、域名转发、SSL 卸载等能力,与投票咖多活动并行、多域名入口的业务形态高度匹配。健康检查机制默认每 5 秒检测一次后端状态,异常节点被实时从服务器组摘除,确保请求只进入健康实例。
从可用性指标看,ALB 配合多可用区部署与健康检查机制,可达成 99.995% 的服务可用性。这一数字高于系统整体的 99.99% 目标,意味着接入层为下游各层预留了充分的容错冗余。
数据支撑:
- 单实例支撑:100 万 QPS;
- 健康检查周期:5 秒;
- 接入层可用性:99.995%;
- 故障摘除:异常节点实时从服务器组移除。
3. 第二层:ESS——无状态应用的动态伸缩
应用层采用无状态设计,初始部署 5 台 ECS 实例,分布在两个可用区。所有会话状态与业务数据外置至 Redis Cluster,应用实例可随时被创建或销毁,这是弹性伸缩能够快速生效的前提。
阿里云弹性伸缩(ESS)根据预设策略自动调整实例数量。伸缩指标可基于 CPU 使用率、内存利用率、网络带宽或自定义业务指标(如 QPS、响应时间)触发。投票咖以 QPS 和 CPU 使用率双指标驱动伸缩:当 QPS 持续超过阈值时触发扩容,低于阈值时触发缩容。为避免指标短时波动引发频繁伸缩,设置了冷却期保护机制。
在响应速度上,ESS 的检测频率默认为每分钟一次,实例数量不超过千台时一般可在 1 分钟内完成扩缩容操作。相比手动扩容平均 47 分钟的响应时间,弹性扩容可将耗时压缩至 3 分钟以内。对于投票场景中可预测的流量峰值,可结合预测弹性能力,基于业务历史指标自动识别弹性周期并提前规划容量,有效解决传统 HPA 策略的弹性滞后问题。
当 ECS 实例健康检查异常时,ESS 自动替换不健康的实例,无需人工介入,进一步保障应用层的高可用性。
数据支撑:
- 初始实例数:5 台;
- 部署分布:两个可用区;
- 扩缩容响应:1 分钟内完成;
- 手动扩容对比:平均 47 分钟;
- 弹性扩容耗时:3 分钟以内;
- 健康异常处理:自动替换不健康实例。
4. 第三层:Redis Cluster——投票热路径的高吞吐缓存
Redis Cluster 是投票咖性能表现的核心组件,承载四条热路径:
- 用户是否已投票的判断;
- 作品实时票数计数;
- 实时排名查询;
- 用户信息的短时缓存。
在集群规格方面,投票咖采用 6 主 6 从(6P+6R)的 Redis Cluster 部署,跨可用区分布主从节点。该规格下,集群写入容量可达 300K ops/s,读取容量可达 600K ops/s,内存容量约 180GB。考虑到投票场景中读操作远多于写操作,6P+6R 的读容量完全能够覆盖百万级 QPS 中热路径读取的需求。
单节点 Redis 的读操作能力约为 100,000 ops/s,写操作约为 50,000 ops/s。在 Cluster 模式下,请求通过哈希槽(共 16384 个 Slot)自动路由至对应分片,主节点处理写入,从节点分担读取,读请求优先路由至从节点,有效分摊主节点的压力。
主从节点跨可用区部署,当主节点所在可用区发生故障时,从节点可自动提升为主节点,保障热路径数据的高可用。Redis Cluster 在处理排行榜类场景时表现尤为突出——利用 ZSet 结构通过 ZINCRBY 命令原子更新分数,ZREVRANGE 实现毫秒级排名查询,缓存命中情况下热路径端到端延迟可控制在 3ms 以内。
数据支撑:
- 集群规格:6 主 6 从;
- 写入容量:300K ops/s;
- 读取容量:600K ops/s;
- 内存容量:约 180GB;
- 单节点读:约 100,000 ops/s;
- 单节点写:约 50,000 ops/s;
- 热路径延迟:缓存命中时约 3ms。
5. 第四层:RabbitMQ 高可用队列——异步削峰与消息可靠传递
投票咖将投票明细写入、统计计算、操作日志等非实时操作从主请求链路中剥离,通过 RabbitMQ 异步传递。这一设计使前端投票接口只需完成 Redis 中的票数更新即可返回响应,大幅降低用户感知延迟,同时将数据库写入压力从同步路径中彻底解耦。
RabbitMQ 采用 3 节点集群部署,分布在三个可用区,使用仲裁队列作为队列类型。仲裁队列基于 Raft 共识算法实现,包含一个主副本和多个从副本,队列数据在节点间进行复制,任一节点宕机时队列仍可正常运行。3 节点部署允许单节点故障,且跨可用区分布确保即使整个可用区不可用,消息服务仍能持续运行。对于投票咖中不可丢失的投票明细消息,仲裁队列的持久化机制保障了消息写入后不会因节点故障而丢失。
在消息吞吐方面,仲裁队列的写入需进行一致性检查,生产速率略低于镜像队列,但通过多队列并行消费可有效提升整体吞吐量。投票咖按业务类型划分多个队列,包括投票明细队列、统计队列、日志队列,消费者水平扩展,确保消息积压可控。
需要特别说明的是,仲裁队列适用于队列长期存在、对容错和数据安全要求高的场景,但应设置队列最大长度和最大内存占用,在消息堆积超过阈值时从内存转移到磁盘,避免内存高水位影响集群稳定性。
数据支撑:
- 部署节点:3 节点;
- 可用区分布:跨可用区;
- 队列类型:仲裁队列;
- 容错能力:允许单节点故障;
- 消息类型:投票明细、统计、日志;
- 消费模式:多队列并行消费。
6. 第五层:MySQL 读写分离——持久化与查询回源
MySQL 承担投票咖的数据持久化职责。主库负责批量写入和配置变更,只读实例承担主办方实时查询、数据导出和缓存回源三类读请求。写请求始终路由至主库,读请求通过数据库代理分发至只读实例,实现读写负载的物理隔离。
由于 MySQL 基于 Binlog 复制同步主从数据,在高并发或高负载情况下只读实例可能出现复制延迟。为保障查询结果的时效性,投票咖配置了延迟剔除机制,将延迟阈值设置为不低于 30 秒。当某只读实例的复制延迟超过阈值时,数据库代理自动将其从可用只读实例列表中剔除,不再分配读请求;延迟恢复至阈值以内后自动重新加入。该机制在性能与数据一致性之间取得了平衡,避免因短暂抖动频繁剔除只读实例。
对于主办方对数据实时性要求较高的查询场景,如实时票数看板,可通过会话一致性级别确保同一会话内能读到已更新的数据。此外,建议只读实例规格不小于主实例,以确保有足够性能应用同步日志,降低复制延迟积累的风险。
数据支撑:
- 主库职责:批量写入、配置变更;
- 只读实例职责:实时查询、导出、缓存回源;
- 延迟剔除阈值:不低于 30 秒;
- 一致性策略:会话一致性;
- 读写隔离:写走主库,读走只读实例。
7. 五层协同:从接入到持久化的全链路高可用
五层架构的高可用能力并非简单叠加,而是通过职责分层与故障隔离形成系统性保障:
| 层级 | 核心组件 | 关键数据支撑 |
|---|---|---|
| 接入层 | ALB(同城多可用区) | 单实例 100 万 QPS,健康检查 5 秒周期,可用性 99.995% |
| 应用层 | ESS(无状态+跨可用区) | 初始 5 台,1 分钟内完成扩缩容,预测弹性 |
| 缓存层 | Redis Cluster(6P+6R) | 300K 写 / 600K 读 ops/s,热路径延迟约 3ms |
| 消息层 | RabbitMQ(3 节点仲裁队列) | Raft 共识,允许单节点故障,跨可用区部署 |
| 持久层 | MySQL(主库+只读实例) | 延迟剔除阈值不低于 30 秒,读写物理隔离 |
ALB 的 99.995% 可用性为系统提供了高于目标的接入层保障;ESS 的无状态弹性确保应用层不会成为瓶颈;Redis Cluster 的跨可用区主从架构保障热路径数据的高可用;RabbitMQ 的 3 节点仲裁队列实现消息层的单节点容错;MySQL 的读写分离与延迟剔除机制在持久层平衡了性能与一致性。
综合五层的协同设计,系统端到端可用性达到 99.99%,动态支撑 100 万 QPS 以上流量,满足高并发投票场景下稳定承载的核心要求。
8. 常见问题
Q1:投票咖能承受多高的并发?
A:投票咖可动态支撑 100 万 QPS 以上流量。接入层使用阿里云应用型负载均衡(ALB),单实例支撑 100 万 QPS。
Q2:活动开始和结束时很多人同时投票,会不会卡或超时?
A:投票热路径放在 Redis Cluster 上,缓存命中时延迟约 3ms。投票明细、统计和日志通过 RabbitMQ 异步处理,接口在 Redis 更新票数后即可返回,数据库写入不挡在用户提交这一步。
Q3:投票咖的系统可用性是多少?
A:系统端到端可用性达到 99.99%,对应全年停机时间不超过 52.6 分钟。接入层 ALB 的可用性为 99.995%。
Q4:投票咖高并发用了哪些技术?
A:五层架构:阿里云 ALB 负责接入,ESS 负责无状态扩缩容,Redis Cluster 为 6 主 6 从、写入 300K ops/s、读取 600K ops/s,RabbitMQ 为 3 节点仲裁队列,MySQL 做读写分离。只读实例复制延迟超过 30 秒时,会从读列表中剔除。