分布式架构入门

2,208 阅读8分钟

分布式系统

在了解分布式架构之前,我们先来了解下分布式系统。按照维基百科的定义:分布式系统是一组电脑,透过网络相互连接传递消息与通信后并协调它们的行为而形成的系统。组件之间彼此进行交互以实现一个共同的目标。把需要进行大量计算的工程数据分割成小块,由多台计算机分别计算,再上传运算结果后,将结果统一合并得出数据结论的科学。

大概就是这样的一个架构,由多个组件之间彼此交付来完成对外的服务。

那这样的系统有什么好处呢?为什么需要这样的系统呢?

分布式系统前身

分布式系统前身就是集中式的系统,他有一个中心化的节点,可能是一台或者多台机器组成,所有的数据存储、计算都在主机上完成。集中式系统的优点:部署简单,可靠性高,数据一致性强等等。

随着客户量和交易量的不断增长,建立在大型主机上的集中式架构系统性能越来越吃紧,这个时候能采用的手段就是提升硬件配置,比如加内存、扩展磁盘、升级 CPU 等等。这样的扩展方式叫做横向扩展(scale up)

但是硬件并不能无条件的扩展,在扩展到某个点以后,扩展硬件对系统的提升将会非常有限。而且系统硬件的价格也随着水涨船高。随着计算机的发展,这样的架构越来越难适应人们的需求,比如说:

  1. 由于大型主机的复杂性,导致培养一个能够熟练运维大型主机的人的成本很高
  2. 大型主机很贵,一般只有土豪(政府、金融、电信)才能用得 起
  3. 单点问题,一台大型主机出现故障,那么整个系统将处于不 可用状态。而对于大型机的使用群体来说,这种不可用导致的 损失是非常大的
  4. 科技在进步,技术在进步。PC 机性能不断提升,很多企业 放弃大型机改用小型机及普通 PC 来搭建系统架构

分布式架构的意义

  1. 升级单机处理能力的性价比越来越低
    • 单机的处理能力主要依靠 CPU、内存、磁盘。通过更换硬件 做垂直扩展的方式来提升性能,成本会越来越高。
  2. 单机处理能力存在瓶颈
    • 单机处理能力存在瓶颈,CPU、内存都会有自己的性能瓶颈, 也就是说就算你是土豪不惜成本去提升硬件,但是硬件的发 展速度和性能是有限制的。
  3. 稳定性和可用性这两个指标很难达到
    • 单机系统存在可用性和稳定性的问题,这两个指标又是我们 必须要去解决的

分布式架构的演进

一个成熟的大型应用系统架构并不是一开始就设计得很完美的,也不是一开始就具备高性能、高可用、安全性等特性,而且随着业务数据量的增加而逐步完善的。在这个过程中,开发模式,技术架构都会发生比较大的变化。而针对不同业务的系统,会有各自的侧重点,比如电商平台的网站,要解决的是海量商品搜索、下单、支付等问题。通信软件需要解决的是数亿用户的实时消息传输。搜索引擎要解决的是海量数据的搜索。每一个种类的业务都有自己不同的系统架构。

这里通过一个 javaweb 电商应用来模拟一个架构的演变过程。这个模拟过程关注的是数据,访问量提升带来的结构变化,不关注具体的业务点。

假设我们的系统具有如下功能:

  • 用户功能:用户注册和管理。
  • 商品功能:商品展示和管理。
  • 交易功能:创建交易和支付结算。

单应用架构

网站的初期(也可以认为是互联网发展早期),我们经常会在单机上部署我们的程序和软件。

把所有的应用都部署在同一台机器上,这样就完成了一个简单系统的搭建。

应用服务和数据库分离

随着网站的上线,访问量逐步加大,服务器的负载会越来越高。加入代码层面的优化已经没有办法提高了,在不提升硬件的情况下,增加机器是一个好的方法,投入产出比非常高。这个阶段主要讲的是数据库与应用服务分离,这样不仅提高了单机的负载能力,也提高了容灾能力。

应用服务器集群

继续随着访问量的不断提高。单台机器已经不能满足需求了。假设测试数据库还没有遇到瓶颈,我们可以按照上一阶段的方式继续增加机器。增加应用服务器,通过应用服务器将用户请求分流到各个服务器中,从而提升负载能力,测试多台应用服务器之前还没有直接的交互。

架构发展到这个阶段,各种问题开始慢慢浮现:

  • 用户的请求如何确认转发到那个应用服务器,由谁来做?
  • 用户访问到不同的应用服务器时,如何维护 session ?

读写分离

在把应用服务做集群后,把应用层的性能拉上来了。但是随着业务量的增加,这时候数据库成为了瓶颈。怎么去提高数据库层面的负载呢?有了上面的经验,会自然想到增加服务器。但是如果我们单纯增加一个数据库服务器,后续的请求分别负载到不同的数据库服务器上,那么一定会造成数据库数据不一致的问题(写请求也会被负载到不同的数据库服务器上)。所以这时候一般会先采用读写分离的方式。 发展到该阶段,遇到的问题大多是数据库的问题:

  • 如何保证数据库主从的数据同步;使用 mysql 自带的 master-slave 实现主从复制。
  • 如何选择对应的数据源;通过第三方插件,如 mycat,shardingjdbc;

引入缓存机制减轻数据库压力

随着访问量的提升,逐渐会出现很多用户访问同一个部分内容的情况。对这一部分热点数据,如果每次都去数据库查询,会给读库带来很大的压力。这时候可以引入环境机制,比如 redis。用来做应用的缓存,读请求时,可以先查看缓存中的数据,如果没有再去查询数据库。

使用搜索引擎来缓解数据库压力

数据库做读库的话,对模糊查找效率不是特别好,像电商类的 网站,搜索是非常核心的功能,即便是做了读写分离,这个问题也 不能有效解决。那么这个时候就需要引入搜索引擎了 使用搜索引擎能够大大提高我们的查询速度,但是同时也会带来一 些附加的问题,比如维护索引的构建。

数据库的水平/垂直拆分

到这个时候,用户,商品,交易的数据还在同一个库中,虽然采用了缓存及读写分离的形式。但是随着数据量的增加,数据库仍然是一个瓶颈,因此这里考虑把数据库进行拆分:

  • 垂直拆分:把数据库中不同的业务数据拆分到不同的库
  • 水平拆分:把同一个表中数据拆分为几个表。水平拆分的原因一般是某些业务量已经达到了单个数据库的瓶颈。

应用拆分

随着业务的发展,业务越来越复杂,应用的压力也越来越大。这个时候就可以考虑应用拆分,按照不同的功能拆分为多个子系统(上图中虽然明确标识出了用户、商品,但这只是为了表示 app 的功能,其实在这之前都是只有一个 app。)

到这里以后其实就是来到了微服务架构,但是这个架构中会有比较多的问题:

  • 服务拆分以后,多个服务之间如何通信?
  • 同一服务部署了多个节点,如何保证节点的配置一致性?
  • 服务拆分后,同一个请求可能会落在节点 A 及节点 B ,查看日志非常不方便。
  • 服务的定时任务,多个节点同时运行,如何保证任务不重复执行及漏执行?
  • 分布式的一致性问题。

这些问题都会在后续的文章中一一为大家解决。

总结

我们把集中式架构改造为分布式架构。是因为在业务发展的过程中,集中式的架构会越来越慢,且提升有较高的成本。稳定性及可用性很难保证。我们想要高性能及高可用的架构,因此将架构向分布式架构改造。