首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >架构师养成记之全局架构视角下的百万级流量到千万级流量用户的系统设计

架构师养成记之全局架构视角下的百万级流量到千万级流量用户的系统设计

作者头像
睡前大数据
发布2025-06-23 17:31:25
发布2025-06-23 17:31:25
2020
举报
文章被收录于专栏:睡前大数据睡前大数据

第 1 步:用例和约束概要

用例

解决这个问题是一个循序渐进的过程:

1) 基准/负载 测试, 

2) 瓶颈 概述, 

3) 当评估可选和折中方案时定位瓶颈,

4) 重复,这是向可扩展的设计发展基础设计的好模式。

我们就处理以下用例讨论这一问题
用户
  •  进行读或写请求
    • 服务 进行处理,存储用户数据,然后返回结果
  • 服务 需要从支持小规模用户开始到百万用户
    • 在我们演化架构来处理大量的用户和请求时,讨论一般的扩展模式
  • 服务 高可用

约束和假设

状态假设

流量不均匀分布
  • 需要关系数据
  • 从一个用户扩展到千万用户
    • 用户量+
    • 用户量++
    • 用户量+++
    • ...
    • 表示用户量的增长
    • 1000 万用户
    • 每月 10 亿次写入
    • 每月 1000 亿次读出
    • 100:1 读写比率
    • 每次写入 1 KB 内容
计算使用
  • 1 TB 新内容 / 月
    • 1 KB 每次写入 * 10 亿 写入 / 月
    • 36 TB 新内容 / 3 年
    • 假设大多数写入都是新内容而不是更新已有内容
  • 平均每秒 400 次写入
  • 平均每秒 40,000 次读取

便捷的转换指南:

  • 250 万秒 / 月
  • 1 次请求 / 秒 = 250 万次请求 / 月
  • 40 次请求 / 秒 = 1 亿次请求 / 月
  • 400 次请求 / 秒 = 10 亿请求 / 月

第 2 步:创建高级设计方案

用所有重要组件概述高水平设计

Imgur
Imgur

第 3 步:设计核心组件

深入每个核心组件的细节。

用例:用户进行读写请求

目标

只有 1-2 个用户时,你只需要基础配置

  • 为简单起见,只需要一台服务器
  • 必要时进行纵向扩展
  • 监控以确定瓶颈
以单台服务器开始
Web 服务器
  •  在 EC2 上
    • 存储用户数据
    • MySQL 数据库

运用 纵向扩展

  • 选择一台更大容量的服务器
  • 密切关注指标,确定如何扩大规模
    • 使用基本监控来确定瓶颈:CPU、内存、IO、网络等
    • CloudWatch, top, nagios, statsd, graphite等
  • 纵向扩展的代价将变得更昂贵
  • 无冗余/容错

折中方案, 可选方案, 和其他细节:

  • 纵向扩展 的可选方案是 横向扩展
自 SQL 开始,但认真考虑 NoSQL
    约束条件假设需要关系型数据。我们可以开始时在单台服务器上使用 MySQL 数据库
分配公共静态 IP
弹性 IP 提供了一个公共端点,不会在重启时改变 IP。
  • 故障转移时只需要把域名指向新 IP。
使用 DNS 服务
    添加 DNS 服务,比如 Route 53(Amazon Route 53 - 译者注),将域映射到实例的公共 IP 中。
安全的 Web 服务器
只开放必要的端口
  • HTTP 80
  • HTTPS 443
  • SSH IP 白名单 22
  • 允许 Web 服务器响应来自以下端口的请求
  • 防止 Web 服务器启动外链

第 4 步:扩展设计

在给定约束条件下,定义和确认瓶颈。

用户+

Imgur
Imgur
假设
    我们的用户数量开始上升,并且单台服务器的负载上升。基准/负载测试 和 分析 指出 MySQL 数据库 占用越来越多的内存和 CPU 资源,同时用户数据将填满硬盘空间。

        目前,我们尚能在纵向扩展时解决这些问题。不幸的是,解决这些问题的代价变得相当昂贵,并且原来的系统并不能允许在 MySQL 数据库 和 Web 服务器 的基础上进行独立扩展。

目标
减轻单台服务器负载并且允许独立扩展
  • 在 对象存储 中单独存储静态内容
  • 将 MySQL 数据库 迁移到单独的服务器上
  • 缺点
    • 这些变化会增加复杂性,并要求对 Web服务器 进行更改,以指向 对象存储 和 MySQL 数据库
    • 必须采取额外的安全措施来确保新组件的安全
    • AWS 的成本也会增加,但应该与自身管理类似系统的成本做比较
独立保存静态内容
考虑使用像 S3 这样可管理的 
  • 对象存储 服务来存储静态内容
    • 高扩展性和可靠性
    • 服务器端加密
  • 迁移静态内容到 S3
    • 用户文件
    • JS
    • CSS
    • 图片
    • 视频
迁移 MySQL 数据库到独立机器上
考虑使用类似 RDS 的服务来管理 
  • MySQL 数据库
    • 简单的管理,扩展
    • 多个可用区域
    • 空闲时加密
系统安全
在传输和空闲时对数据进行加密
  • 使用虚拟私有云
    • 为单个 Web 服务器 创建一个公共子网,这样就可以发送和接收来自 internet 的流量
    • 为其他内容创建一个私有子网,禁止外部访问
    • 在每个组件上只为白名单 IP 打开端口
  • 这些相同的模式应当在新的组件的实现中实践

用户+++

Imgur
Imgur
假设
    我们的 基准/负载测试 和 性能测试 显示,在高峰时段,我们的单一 Web服务器 存在瓶颈,导致响应缓慢,在某些情况下还会宕机。随着服务的成熟,我们也希望朝着更高的可用性和冗余发展。
目标
下面的目标试图用 
  • Web服务器 解决扩展问题
    • 基于 基准/负载测试 和 分析,你可能只需要实现其中的一两个技术
  • 使用 横向扩展 来处理增加的负载和单点故障
    • ELB 是高可用的
    • 如果你正在配置自己的 负载均衡器, 在多个可用区域中设置多台服务器用于 双活 或 主被 将提高可用性
    • 终止在 负载平衡器 上的SSL,以减少后端服务器上的计算负载,并简化证书管理
    • 添加 负载均衡器 例如 Amazon 的 ELB 或 HAProxy
    • 在多个可用区域中使用多台 Web服务器
    • 在多个可用区域的 主-从 故障转移 模式中使用多个 MySQL 实例来改进冗余
  • 分离 Web 服务器 和 应用服务器
    • 独立扩展和配置每一层
    • Web 服务器 可以作为 反向代理
    • 例如, 你可以添加 应用服务器 处理 读 API 而另外一些处理 写 API
  • 将静态(和一些动态)内容转移到 内容分发网络 (CDN) 例如 CloudFront 以减少负载和延迟

用户+++

Imgur
Imgur

注意: 内部负载均衡 不显示以减少混乱

假设
我们的 性能/负载测试 和 性能测试 显示我们读操作频繁(100:1 的读写比率),并且数据库在高读请求时表现很糟糕。
目标
下面的目标试图解决 
  • MySQL数据库 的伸缩性问题
    • 基于 基准/负载测试 和 分析,你可能只需要实现其中的一两个技术
  • 将下列数据移动到一个 内存缓存,例如弹性缓存,以减少负载和延迟:
    • Web 服务器 变成无状态的, 允许 自动伸缩
    • 首先, 尝试配置 MySQL 数据库 缓存以查看是否足以在实现 内存缓存 之前缓解瓶颈
    • MySQL 中频繁访问的内容
    • 来自 Web 服务器 的会话数据
    • 从内存中读取 1 MB 内存需要大约 250 微秒,而从SSD中读取时间要长 4 倍,从磁盘读取的时间要长 80 倍。
  • 添加 MySQL 读取副本 来减少写主线程的负载
  • 添加更多 Web 服务器 and 应用服务器 来提高响应
添加 MySQL 读取副本
除了添加和扩展 
  • 内存缓存MySQL 读副本服务器 也能够帮助缓解在 MySQL 写主服务器 的负载。
  • 添加逻辑到 Web 服务器 来区分读和写操作
  • 在 MySQL 读副本服务器 之上添加 负载均衡器 (不是为了减少混乱)
  • 大多数服务都是读取负载大于写入负载

用户++++

Imgur
Imgur
假设
基准/负载测试 和 分析 显示,在美国,正常工作时间存在流量峰值,当用户离开办公室时,流量骤降。我们认为,可以通过真实负载自动转换服务器数量来降低成本。我们是一家小商店,所以我们希望 DevOps 尽量自动化地进行 自动伸缩 和通用操作。
目标
根据需要添加 
  • 自动扩展
    • 跟踪流量高峰
    • 通过关闭未使用的实例来降低成本
  • 自动化 DevOps
    • Chef, Puppet, Ansible 工具等
  • 继续监控指标以解决瓶颈
    • 主机水平 - 检查一个 EC2 实例
    • 总水平 - 检查负载均衡器统计数据
    • 日志分析 - CloudWatch, CloudTrail, Loggly, Splunk, Sumo
    • 外部站点的性能 - Pingdom or New Relic
    • 处理通知和事件 - PagerDuty
    • 错误报告 - Sentry
添加自动扩展
考虑使用一个托管服务,比如AWS
  • 自动扩展
    • 自动扩展会引入复杂性
    • 可能需要一段时间才能适当扩大规模,以满足增加的需求,或者在需求下降时缩减规模
    • 可预测负载的简单时间度量
    • 一段时间内的指标:
    • CPU 负载
    • 延迟
    • 网络流量
    • 自定义指标
    • 为每个 Web 服务器 创建一个组,并为每个 应用服务器 类型创建一个组,将每个组放置在多个可用区域中
    • 设置最小和最大实例数
    • 通过 CloudWatch 来扩展或收缩
    • 缺点

用户+++++

Imgur
Imgur

注释: 自动伸缩 组不显示以减少混乱

假设
当服务继续向着限制条件概述的方向发展,我们反复地运行 基准/负载测试 和 分析 来进一步发现和定位新的瓶颈。
目标
由于问题的约束,我们将继续提出扩展性的问题:
  • 如果我们的 MySQL 数据库 开始变得过于庞大, 我们可能只考虑把数据在数据库中存储一段有限的时间, 同时在例如 Redshift 这样的数据仓库中存储其余的数据
    • 像 Redshift 这样的数据仓库能够轻松处理每月 1TB 的新内容
  • 平均每秒 40,000 次的读取请求, 可以通过扩展 内存缓存 来处理热点内容的读取流量,这对于处理不均匀分布的流量和流量峰值也很有用
    • SQL读取副本 可能会遇到处理缓存未命中的问题, 我们可能需要使用额外的 SQL 扩展模式
  • 对于单个 SQL 写主-从 模式来说,平均每秒 400 次写操作(明显更高)可能会很困难,同时还需要更多的扩展技术

SQL 扩展模型包括:

  • 集合
  • 分片
  • 反范式
  • SQL 调优

为了进一步处理高读和写请求,我们还应该考虑将适当的数据移动到一个 NoSQL数据库 ,例如 DynamoDB。

我们可以进一步分离我们的 应用服务器 以允许独立扩展。不需要实时完成的批处理任务和计算可以通过 Queues 和 Workers 异步完成:

  • 以照片服务为例,照片上传和缩略图的创建可以分开进行
    • 创建缩略图
    • 更新 数据库
    • 在 对象存储 中存储缩略图
    • 客户端 上传图片
    • 应用服务器 推送一个任务到 队列 例如 SQS
    • EC2 上的 Worker 服务 或者 Lambda 从 队列 拉取 work,然后:
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 睡前大数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第 1 步:用例和约束概要
    • 用例
    • 解决这个问题是一个循序渐进的过程:
    • 1) 基准/负载 测试, 
    • 2) 瓶颈 概述, 
    • 3) 当评估可选和折中方案时定位瓶颈,
    • 4) 重复,这是向可扩展的设计发展基础设计的好模式。
      • 我们就处理以下用例讨论这一问题
      • 用户
    • 约束和假设
    • 状态假设
      • 流量不均匀分布
      • 计算使用
  • 第 2 步:创建高级设计方案
  • 第 3 步:设计核心组件
    • 用例:用户进行读写请求
    • 目标
    • 只有 1-2 个用户时,你只需要基础配置
      • 以单台服务器开始
      • Web 服务器
      • 自 SQL 开始,但认真考虑 NoSQL
      •     约束条件假设需要关系型数据。我们可以开始时在单台服务器上使用 MySQL 数据库。
      • 分配公共静态 IP
      • 弹性 IP 提供了一个公共端点,不会在重启时改变 IP。
      • 使用 DNS 服务
      •     添加 DNS 服务,比如 Route 53(Amazon Route 53 - 译者注),将域映射到实例的公共 IP 中。
      • 安全的 Web 服务器
      • 只开放必要的端口
  • 第 4 步:扩展设计
    • 用户+
      • 假设
      •     我们的用户数量开始上升,并且单台服务器的负载上升。基准/负载测试 和 分析 指出 MySQL 数据库 占用越来越多的内存和 CPU 资源,同时用户数据将填满硬盘空间。
      • 目标
      • 减轻单台服务器负载并且允许独立扩展
      • 独立保存静态内容
      • 考虑使用像 S3 这样可管理的 
      • 迁移 MySQL 数据库到独立机器上
      • 考虑使用类似 RDS 的服务来管理 
      • 系统安全
      • 在传输和空闲时对数据进行加密
    • 用户+++
      • 假设
      •     我们的 基准/负载测试 和 性能测试 显示,在高峰时段,我们的单一 Web服务器 存在瓶颈,导致响应缓慢,在某些情况下还会宕机。随着服务的成熟,我们也希望朝着更高的可用性和冗余发展。
      • 目标
      • 下面的目标试图用 
    • 用户+++
      • 假设
      • 我们的 性能/负载测试 和 性能测试 显示我们读操作频繁(100:1 的读写比率),并且数据库在高读请求时表现很糟糕。
      • 目标
      • 下面的目标试图解决 
      • 添加 MySQL 读取副本
      • 除了添加和扩展 
    • 用户++++
      • 假设
      • 基准/负载测试 和 分析 显示,在美国,正常工作时间存在流量峰值,当用户离开办公室时,流量骤降。我们认为,可以通过真实负载自动转换服务器数量来降低成本。我们是一家小商店,所以我们希望 DevOps 尽量自动化地进行 自动伸缩 和通用操作。
      • 目标
      • 根据需要添加 
      • 添加自动扩展
      • 考虑使用一个托管服务,比如AWS
    • 用户+++++
      • 假设
      • 当服务继续向着限制条件概述的方向发展,我们反复地运行 基准/负载测试 和 分析 来进一步发现和定位新的瓶颈。
      • 目标
      • 由于问题的约束,我们将继续提出扩展性的问题:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档