亿级流量网站架构核心技术

Executive Summary

核心观点(金字塔原理)

结论先行: 亿级流量网站架构的核心是通过高并发设计(无状态、拆分、缓存)和高可用设计(降级、限流、隔离)来保障系统稳定性和性能。

支撑论点:

  1. 高并发原则:无状态设计、多维度拆分、服务化、消息队列、缓存银弹
  2. 高可用原则:降级、限流、切流量、可回滚,确保系统在极端情况下仍能提供核心服务
  3. 业务设计原则:防重、幂等、状态机设计,从业务层面保障系统健壮性

SWOT 分析

维度 分析
S 优势 内容来自京东实战经验,涵盖从负载均衡到业务设计的完整架构知识体系
W 劣势 技术方案偏向特定技术栈(Nginx/OpenResty),云原生时代部分方案需更新
O 机会 互联网公司普遍面临流量增长挑战,高并发架构能力是核心竞争力
T 威胁 云服务已封装大量基础能力,需结合云原生架构理解传统方案的演进

适用场景

  • 系统从万级向亿级流量演进的架构升级
  • 电商大促、秒杀等高并发场景设计
  • 构建高可用分布式系统的技术选型

第1部分 概述

  • 交易系统设计的一些原则
    • 墨菲定律
      1. 任何事情都没有表面看起来那么简单
      2. 所有的事情都会比你预计的时间长
      3. 可能出错的事情总会出错
      4. 如果你担心某种情况发生,那么它就更有可能发生
    • 系统划分时,也需要思考康威定律
      1. 系统架构是公司组织架构的反映
      2. 应该按照业务闭环进行系统拆分/组织架构划分,实现闭环/高内聚/低耦合,减少沟通成本
      3. 如果沟通出现问题,那么应该考虑进行系统和组织架构的调整
      4. 在合适时机进行系统拆分,不要一开始就把系统/服务拆得非常细,虽然闭环,但每个人维护的系统多,维护成本高。
    • 二八定律
高并发原则
  • 无状态
  • 拆分
    • 系统维度:按照系统功能/业务拆分,比如商品系统,购物车,结算,订单系统等
    • 功能维度:对一个系统进行功能再拆分,比如优惠券系统可以拆分为后台券创建系统,领券系统,用券系统等
    • 读写维度:根据读写比例特性进行拆分。读量大采用缓存,写量大采用分库分表。聚合读取场景,考虑数据异构拆分系统,将分散在多处的数据聚合到一起存储,提升系统的性能和可靠性。
    • AOP维度:根据访问特性,按照AOP进行拆分。
    • 模块维度:比如按照基础或者代码维护特性进行拆分,如基础模块分库分表,数据库连接池等。代码结构按照三层架构Web,Service,DAO进行划分。
  • 服务化:进程内服务-》单机远程服务-》集群手动注册服务-》自动注册和发现服务-》服务的分组/隔离/路由-》服务治理如限流/黑名单
  • 消息队列:大流量缓冲,数据校对
  • 数据异构:数据异构,数据闭环
  • 缓存银弹: 浏览器端缓存,APP客户端缓存,CDN缓存,接入层缓存,应用层缓存,分布式缓存
  • 并发化
高可用原则
  • 降级:流量降级,业务降级
  • 限流:目的防止恶意请求流量,恶意攻击,以及防止流量超出系统峰值。
  • 切流量:DNS,HttpDNS,LVS/HaProxy/Nginx
  • 可回滚
业务设计原则
  • 防重设计,重复提交表单,下单扣库存,考虑防重key,防重表。
  • 幂等设计,接口幂等,异步回调
  • 流程可定义
  • 状态与状态机
  • 后台系统操作可反馈
  • 后台系统审批化
  • 文档和注释
  • 备份
总结

高可用脑图

第2部分 高可用

负载均衡与反向代理
  • LVS/F5 + Nginx + OpenResty + Tomcat
  • 对于负载均衡关心如下方面:
    • 上游服务器配置:使用upstream server配置上游服务器
    • 负载均衡算法:配置多个上游服务器时的负载均衡机制
    • 失败重试机制:配置当超时或上游服务器不存活时,是否需要重试其他上游服务器
    • 服务器心跳检查:上游服务器的健康检查/心跳检查
  • 给Nginx 配置上游服务器,即负载均衡到真实处理业务的服务器,通过http指令下配置upstream即可
upstream backend {
  server 192.168.61.1:9080 weight=1;//权重:默认为1,权重越大分配给这台服务器的请求越多,需要根据服务器的实际处理能力设置权重
  server 192.168.61.1:9090 weight=2;
}
// proxy_pass
location / {
  proxy_pass http://backend; //当访问Nginx时,会将请求反向代理到backend配置的upstream server
}
  • 负载均衡算法,用来解决用户请求到来时如何选择服务器进行处理.
    • 默认round-robin(轮询,通过配合weight配置实现基于权重轮询);
    • ip_hash:根据客户IP进行负载均衡即相同的IP将负载均衡到同一个upstream server.
upstream backend {
  ip_hash;
  server 192.168.61.1:9080 weight=1;//权重:默认为1,权重越大分配给这台服务器的请求越多,需要根据服务器的实际处理能力设置权重
  server 192.168.61.1:9090 weight=2;
}
  • hash key [consistent]:对某一个key进行哈希或者使用一致性哈希算法进行负载均衡。问题是:当添加/删除一台服务器时,导致很多key被重新负载均衡到不同的服务器,从而可能导致后端出现问题,因此建议考虑一致性哈希算法,当添加/删除一台机器,只有少数key被重新负载均衡到不同的服务器
  • 哈希算法:此处是根据请求uri进行负载均衡,可以使用Nginx变量,因此可以实现复杂的算法。
upstream backend {
  hash $uri;
  server 192.168.61.1:9080 weight=1;//权重:默认为1,权重越大分配给这台服务器的请求越多,需要根据服务器的实际处理能力设置权重
  server 192.168.61.1:9090 weight=2;
}
  • 一致性哈希算法:consistent_key动态指定。
upstream nginx_local_server {
  hash $consistent_key consistent;
  server 192.168.61.1:9080 weight=1;//权重:默认为1,权重越大分配给这台服务器的请求越多,需要根据服务器的实际处理能力设置权重
  server 192.168.61.1:9090 weight=2;
}
location / {
  set $consistent_key $arg_cat; //优先考虑请求参数cat,如果没有再根据uri进行负载均衡
  if ($consistent_key = "") {
    set $consistent_key $request_uri;
  }
}
  • 基于Lua设置一致性哈希key TODO
  • 失败重试
upstream backend {
  server 192.168.61.1:9080 max_fails=2 fail_timeout=10s weight=1;//表示10s内失败了2次就任务该服务器不可用/不存活,然后摘掉,10s后会再次将该服务器加入存活上游服务器列表进行重试
  server 192.168.61.1:9090 max_fails=2 fail_timeout=10s weight=2;
}
location /test {
  proxy_connect_timeout 5s;
  proxy_read_timeout 5s;
  proxy_send_timeout 5s;

  proxy_next_upstream_error timeout;
  proxy_next_upstream_timeout 10s;
  proxy_next_upstream_tries 2;
  proxy_pass http://backend;
  add_header upstream_addr $upstream_addr;
}
  • 健康检查:TCP心跳检查,HTTP心跳检查
  • 域名上游配置
upstream backend {
  server c0.3.cn;
  server c1.3.cn;
}
  • 备份上游服务器
  • 不可用上游服务器
  • 长连接
  • HTTP反向代理
  • HTTP动态负载均衡
  • Nginx四层负载均衡
隔离术
  • 线程池隔离
  • 进程隔离
  • 集群隔离
  • 机房隔离
  • 读写隔离
  • 动静隔离
  • 爬虫隔离,1. 限流 2. 在负载均衡层面将爬虫路由到单独集群,从而保证正常流量可用。 IP+Cookie避免误杀
  • 热点隔离
  • 资源隔离
  • 使用Hystrix实现隔离
限流详解
  • 常见限流算法:令牌桶算法(Token Bucket)以固定速率生成令牌,请求需获取令牌才能通过,允许一定程度的突发流量;漏桶算法(Leaky Bucket)以恒定速率处理请求,平滑流量峰值;滑动窗口计数器将时间划分为细粒度窗口进行精确统计,避免固定窗口的边界突发问题
  • Nginx层限流:使用 limit_req 模块基于漏桶算法对请求速率进行限制(如 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s);使用 limit_conn 模块限制单个IP的并发连接数,防止恶意占用连接资源
  • 应用层限流:Google Guava 提供的 RateLimiter 基于令牌桶算法实现单机限流,支持平滑突发限流(SmoothBursty)和平滑预热限流(SmoothWarmingUp),适用于API接口级别的精细化流量控制
  • 分布式限流:基于 Redis + Lua 脚本实现集群级别的统一限流,利用 Redis 的原子操作保证计数准确性;常见方案包括 Redis INCR + EXPIRE 实现固定窗口计数,或用 Redis + Lua 实现令牌桶/滑动窗口等更复杂的算法
  • 限流后的优雅降级:被限流的请求不应直接丢弃,而应返回友好的提示信息(如”系统繁忙,请稍后重试”)、引导至排队页面、或降级返回缓存数据,保证用户体验不会断崖式下降
降级特级
  • 降级分级策略:开关降级(通过预埋开关手动/自动关闭非核心功能)和自动降级(根据系统负载、响应时间、错误率等指标自动触发),降级粒度从页面级、服务级到接口级逐层细化
  • 读降级:当核心数据源不可用时,优先从本地缓存或分布式缓存读取数据;缓存也失效时返回预设的默认值或静态兜底数据,保证页面可展示,如商品详情降级为基础信息展示
  • 写降级:核心写入链路出现瓶颈时,将同步写转为异步写(写入消息队列后返回成功),或采用日志记录+事后重放的方式保证数据最终一致性,避免写操作阻塞主流程
  • 降级配置中心:通过统一的配置中心(如Apollo、Nacos)管理降级开关,支持动态推送和实时生效,无需重启应用;开关按业务维度分组管理,支持灰度推送和一键全局降级
  • 熔断器模式:Hystrix 熔断器包含关闭(Closed)、打开(Open)、半开(Half-Open)三种状态;当错误率超过阈值时熔断器打开,直接走降级逻辑;经过休眠窗口期后进入半开状态,放行少量请求探测下游是否恢复,成功则关闭熔断器恢复正常调用
超时与重试机制
  • 超时分类:连接超时(Connection Timeout)控制建立TCP连接的最大等待时间,通常设置较短(如1-5秒);读超时(Read/Socket Timeout)控制等待响应数据的最大时间;写超时(Write Timeout)控制发送数据的最大时间,三者需根据业务场景独立配置
  • 分层超时设置:代理层(Nginx proxy_connect_timeout/proxy_read_timeout 一般5-10秒),应用层(HTTP客户端、RPC框架超时一般3-5秒),数据层(数据库连接池超时、SQL执行超时一般1-3秒),上层超时应大于下层超时之和,避免上层已超时但下层仍在执行造成资源浪费
  • 重试策略:立即重试适用于网络抖动等瞬时故障;指数退避重试(Exponential Backoff)每次重试间隔翻倍(如1s、2s、4s),并加入随机抖动(Jitter)避免重试风暴;固定间隔重试适用于下游有明确恢复时间的场景
  • 重试风暴防护:限制最大重试次数(通常2-3次),避免级联重试导致下游雪崩;在服务链路中只在最近调用方重试,上游不叠加重试;引入熔断机制,当错误率超过阈值时停止重试直接降级
  • 幂等重试设计:重试前提是接口必须支持幂等,通过唯一请求ID(RequestId)、去重表、乐观锁版本号等机制保证重复请求不会产生副作用;非幂等操作(如扣款)不应自动重试,需人工介入或走补偿机制
回滚机制
  • 代码回滚:基于版本控制系统(Git Tag/分支)快速回退到上一稳定版本;蓝绿部署架构下通过流量切换在新旧版本间秒级切换,回滚时直接将流量切回蓝组(旧版本),无需重新部署
  • 数据回滚:定期全量备份 + 实时 Binlog 增量备份,出现数据问题时可通过 Binlog 回放恢复到指定时间点(Point-in-Time Recovery);关键业务表变更前自动创建快照,支持表级别的快速回滚
  • 配置回滚:配置中心(Apollo/Nacos)保留配置的历史版本,支持一键回滚到任意历史版本并实时推送生效;所有配置变更记录审计日志,包含变更人、变更时间、变更内容的完整追溯链
  • 灰度发布与快速回滚:通过金丝雀发布(Canary Release)先将新版本部署到小比例机器(如1%-5%),观察监控指标和错误日志,发现异常立即回滚灰度机器,将影响范围控制在最小
  • Feature Flag 安全发布:使用功能开关(Feature Flags)控制新功能的可见性,新代码上线但功能默认关闭,通过配置中心逐步开放;出现问题时关闭开关即可”回滚”功能,无需回滚代码和重新部署
压测与预案
  • 压测方法论:基线压测确定单机/集群的正常处理能力;峰值压测模拟预期最大流量(如大促峰值的1.5倍)验证系统承压能力;破坏性压测逐步加压找到系统瓶颈和崩溃临界点,为容量规划提供数据依据
  • 生产流量回放:通过 TCPCopy、GoReplay 等工具录制线上真实流量,在压测环境中按倍数回放,真实模拟用户请求分布和访问模式,比手工构造的压测脚本更接近真实场景
  • 影子压测(Shadow Testing):将线上流量复制一份到影子环境(使用影子库、影子表),在不影响真实用户的前提下对新版本或新架构进行全链路压测,验证系统在真实流量下的表现
  • 容量规划公式:根据压测结果计算所需资源,核心公式为:所需机器数 = 预估峰值QPS /(单机QPS × 利用率阈值),利用率阈值通常取0.7,预留30%的Buffer应对突发流量和机器故障
  • 应急预案体系:制定分级应急预案包括流量切换方案(DNS切换、机房切流)、降级预案(按优先级逐级关闭非核心功能)、弹性扩容方案(云环境自动扩容规则),定期进行故障演练(如Chaos Engineering)验证预案有效性