如何从单个服务器扩展到百万用户的系统?

假如你开发了一个网站(例如网上商店、社交网站或者其他任何东西),之后你把它发布到了网上,网站运行良好,每天有几百的访问量,能快速地响应用户的请求 。
 

如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
但是有一天,不知道什么原因,你的网站出名了! 每分每秒都有成千上万的用户蜂拥而至,你的网站变得越来越慢……
对你来讲,这是个好消息,但是对你的 Web 应用来说这是个坏消息 。因为现在它需要扩展了,你的应用需要为全球用户提供 7*24 不宕机服务 。
如何进行扩展?
几年前,我讨论过水平扩展与垂直扩展 。简而言之,垂直扩展意味着在性能更强的计算机上运行同样的服务,而水平扩展是并行地运行多个服务 。
如今,几乎没有人说垂直扩展了 。原因很简单:
  • 随着计算机性能的增长,其价格会成倍增长 。
  • 单台计算机的性能是有上限的,不可能无限制地垂直扩展 。
  • 多核 CPU 意味着即使是单台计算机也可以并行的 。那么,为什么不一开始就并行化呢?
现在我们水平扩展服务 。需要哪些步骤呢?
单台服务器+数据库
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
上图可能是你后端服务最初的样子 。有一个执行业务逻辑的应用服务器(Application Server)和保存数据的数据库 。
看上去很不错 。但是这样的配置,满足更高要求的唯一方法是在性能更强的计算机上运行,这点不是很好 。
增加一个反向代理
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
成为大规模服务架构的第一步是添加反向代理 。类似于酒店大堂的接待处 。
你也可以让客人直接去他们的客房 。但是实际上,你需要一个中间人他去检查是否允许客人进入,如果客房没有开放,得有人告诉客人,而不是让客人处于尴尬的境地 。这些事情正是反向代理需要做的 。
通常,代理是一个接收和转发请求的过程 。正常情况下,「正向代理」代理的对象是客户端,「反向代理」代理的对象是服务端,它完成这些功能:
  • 健康检查功能,确保我们的服务器是一直处于运行状态的 。
  • 路由转发功能,把请求转发到正确的服务路径上 。
  • 认证功能,确保用户有权限访问后端服务器 。
  • 防火墙功能,确保用户只能访问允许使用的网络部分等等 。
【如何从单个服务器扩展到百万用户的系统?】引入负载均衡器
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
大多数反向代理还有另外一个功能:他们也可以充当负载均衡器 。
负载均衡器是个简单概念,想象下有一百个用户在一分钟之内在你的网店里付款 。
遗憾的是,你的付款服务器在一分钟内只能处理 50 笔付款 。这怎么办呢?同时运行两个付款服务器就行了 。
负载均衡器的功能就是把付款请求分发到两台付款服务器上 。用户 1 往左,用户 2 往右,用户 3 再往左 。。。以此类推 。
如果一次有 500 个用户需要立刻付款,这该怎么解决呢?确切地说,你可以扩展到十台付款服务器,之后让负载均衡器分发请求到这十台服务器上 。
扩展数据库
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
负载均衡器的使用使得我们可以在多个服务器之间分配负载 。但是你发现问题了吗?
尽管我们可以用成百上千台服务器处理请求,但是他们都是用同一个数据库存储和检索数据 。
那么,我们不能以同样的方式来扩展数据库吗?很遗憾,这里有个一致性的问题 。
系统使用的所有服务需要就他们使用的数据达成一致 。数据不一致会导致各种问题,如订单被多次处理,从一个余额只有 100 元的账户中扣除两笔 90 元的付款等等......那么我们在扩展数据库的时候如何确保一致性呢?
我们需要做的第一件事是把数据库分成多个部分 。一部分专门负责接收并存储数据,其他部分负责检索数据 。
这个方案有时称为主从模式或者单实例写多副本读 。这里假设是从数据库读的频率高于写的频率 。
这个方案的好处是保证了一致性,因为数据只能被单实例写入,之后把写入数据同步到其他部分即可 。缺点是我们仍然只有一个写数据库实例 。


推荐阅读