把学习当成一种习惯
选择往往大于努力,越努力越幸运

网站架构的演进

初级阶段的网站架构

  最开始的网站,没有太多人访问(并发量小),只需要一台服务器就绰绰有余,即应用服务、数据库服务、文件的存储服务等所有资源都集中在同一台服务器中,例如购买一台Linux操作系统的服务器,使用Java开发的应用程序部署在Tomcat上,数据库使用MySQL,文件存储在本地服务器中,如下图 :

服务分离到不同服务器

  随着网站业务的发展,越来越多的用户导致网站的性能越来越差,这个时候一台服务器已经不能满足需求了,需要将各个服务分离到不同服务器中,应用服务、数据库服务和文件服务可以分布到三台配置不同的服务器中,如下图 :

不同服务器可以承担不同的角色,对硬件资源的要求也就不同 :

  • 应用服务器 : 需要处理大量的业务逻辑,因此需要更快更强大的CPU的服务器;
  • 数据库服务器 : 大量的磁盘I/O检索以及数据的缓存,所以需要更快、更大的硬盘、更大的内存;
  • 文件服务器 : 文件需要存储大量的用户上传的文件,所以需要更快、更大的硬盘;

引入缓存来提高服务器性能

  随着网站业务的进一步发展,网站的性能再次来到了瓶颈,数据库压力太大导致访问延迟、进而影响整个网站的性能.
  根据二八定律,80%的业务集中在20%的数据上,如果这20%的数据缓存在内存中,可以减少数据库的访问能力、提高整个网站的数据访问速度,改善数据库的写入能力.
  缓存有本地缓存和远程分布式缓存服务器 :

  • 本地缓存访问速度更高一些,但是受限于应用服务器内存有限;
  • 远程分布式缓存服务器可以使用集群的方式来部署大内存的服务器作为专门的缓存服务器,并且水平扩容服务器,理论上做到不受限内存容量限制.

使用应用服务器集群来提高并发处理能力

  使用缓存后,数据访问压力得到缓解,但是单一应用服务器能够处理的请求连接数有限,应用服务器高峰时达到了瓶颈,通过集群来提高应用服务器的并发处理能力.
  集群 : 增加服务器的方式改善负载压力,从而提高系统性能,实现系统的伸缩性.
  应用服务器是网站可伸缩性集群架构中较为简单成熟的一种 : 应用服务器是无状态的,没有保存数据,所有服务器是对等的,可根据负载均衡保证每台服务器均衡调度,可不断加入新的服务器来.
  【PS : 使用集群是网站解决高并发、海量数据问题的常用手段】

数据库读写分离

  引入集群、缓存后,一些读操作(缓存未命中、缓存过期等)、写操作还是会走数据库,当业务规模发展到一定规模后,数据库再次成为了瓶颈.
  通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到另一台数据库服务器上,即应用服务器在写、更新数据时,访问主数据库,主数据库通过主从复制机制将数据更新同步到从数据库;当应用服务器在读数据时,就可以通过从数据库读取.

分布式数据库系统、分布式文件系统

  随着网站业务的发展依然不能满足需求,大量的写请求还是需要Master来承担,当业务量量级再次增高时,这时需要使用分布式数据库.

分布式数据库的拆分思想

  • 两种拆分思想 :
    • 垂直拆分 :
      • 垂直分表 : "大表拆小表"的思想 : 将一个多字段的表按照字段分成多表,每个表存储其中一部分字段,这种方式是我们开发过程中常用的一种手段;
        • 优势 : 增加数据页中数据行的存储、减少跨页、减少I/O操作.
        • 劣势 : 单一数据库实例在高并发情况下的数据库连接数、磁盘I/O、内存等硬件资源、单表数据量过大的性能瓶颈
      • 垂直分库 : 根据业务特点,拆分不同的数据库,每个数据库可以部署在不同的服务器上.
        • 优势 : 业务解耦、更多节点使访问压力被均摊,解决了单实例数据库连接数、硬件资源等的性能瓶颈、易于开发、维护、监控、扩展.
        • 劣势 : 单表数据量较大导致的性能瓶颈、跨库带来的所有复杂问题,例如分布式事务
    • 水平拆分 : 根据数据按照策略分散到不同的表中.
      • 水平分库 : 把表的数据分散在不同的数据库中,每个数据库可以部署在不同的服务器.
        • 优势 : 解决了单库数据库连接数、硬件资源等的性能瓶颈、单表数据量大的问题
        • 劣势 : 数据路由问题、跨库带来的复杂问题,例如跨表查询、聚合查询、分布式事务等
      • 库内分表 : 同一个库内拆分成N个结构相同的表
        • 优势 : 一定程度上优化了单一表数据量过大而产生的性能问题
        • 劣势 : 单实例数据库连接数、硬件资源等的性能瓶颈、跨表查询、聚合查询等
    • 总结 :
      • 垂直拆分 : 在系统设计阶段就应该根据业务耦合松紧来确定垂直分库、垂直分表方案.
      • 水平拆分 : 数据量极大,且持续增长,再考虑水平分库、水平分表方案.

【PS : 在数据量及访问压力不是特别大的情况,首先考虑缓存、NoSQL技术、读写分离等方案】

分布式数据库

  • 分布式数据库 :
    • 读写分离 : master节点负责写请求、slave节点负责读请求;
    • 分库分表 : 根据特定字段的路由规则,把数据分散到不同的库,不同的表中;
    • 业务分库 : 基于业务特点拆分数据库,是当前分布式架构下,或者微服务模式的基础用法;

  分布式数据库是网站数据库拆分的最后手段,只有在单表数据规模非常庞大的时候才使用.不到不得已时,网站更常用的数据库拆分手段是业务分库,将不同业务的数据库部署在不同的服务器上,即优先考虑垂直拆分.

分布式文件系统

  文件系统到一定的性能瓶颈后,也是一样需要使用分布式文件系统.像开源的TFS、FastDFS、GFS等,都是解决文件的高可用、高性能存储等问题.

NoSQL、搜索引擎

随着业务的发展越来越复杂,对数据的存储、检索也越来越复杂,需要引入一些NoSQL和搜索引擎.

业务拆分

  为了应对大型复杂的业务场景,通过使用分而治之的思想,将整个网站业务分成许多不同的应用,每个应用独立部署;应用之间通过消息队列进行数据分发或者通过访问同一个数据存储系统来构建一个完整的系统.

分布式

  根据业务拆分后的服务,可以部署在不同的服务器上,随着拆分的服务越来越多,服务之间的工作需要通过分布式服务框架来协调,如Dubbo、SpringCloud等.

  • 分布式服务框架必须具备 :
    • 分布式配置中心
    • 服务管理、注册和发现
    • 分布式RPC框架
    • 网关
    • 服务监控、健康检查、异常警告

  分布式意味着需要更多的计算机来完成同样的功能,计算机越多,能够处理的并发访问、数据处理的能力就越大,进而能够使系统高性能、高可用、可扩展、易伸缩.但是分布式带来了利的同时也带来了弊 :

  • 分布式带来的问题,例如 :
    • 服务不可用导致其他调用服务也不可用,即存在服务雪奔效应
    • 多个数据库之间跨库问题,即分布式事务
    • 负载均衡
    • 有状态的数据存储层 : 分布式锁、乐观锁
    • 有状态的服务层 : 分布式Session
    • 全局Id : 分布式Id
    • 网络分区、缓存等带来的数据一致性问题
    • 增加系统的复杂性
  • 分布式带来的优势 :
    • 改善系统的性能、可扩展、易伸缩
    • 系统解耦,提高开发效率、发布效率
    • 可复用公共的服务、减少数据库连接资源

大型网站架构模式

  从简单的单体架构系统到复杂的分布式架构系统的演进,最终是为了实现一个高性能、高可用、可扩展、易伸缩、安全性等各种技术架构目标的系统,而在这一过程中衍生出的许许多多的问题所一一对应的解决方案,这些解决方案又被更多网站重复使用,从而逐渐形成了网站架构模式.

分层

  分层思想在计算机世界中无处不在,例如计算机网络中的七层协议的分层结构;在大型网站架构中也采用分层思想,把网站分为 应用层、服务层、数据层,各层之间都是独立性、互不影响、只需要维护调用接口的不变,并且易于不同工种的开发、系统的维护和扩展;对于开发人员,必须严格遵循分层架构的一些约束,比如必须是上层调用下层,即下层服务于上层,不能出现逆向调用或者跨层调用.
  【PS : 分层结构对网站支持高并发向分布式方向发展至关重要】

分割(纵向扩展或者叫垂直扩展)

  分层后的每一层可由不同工种的进行开发,但是随着系统发展得越来越复杂,使得开发人员的开发、发布、维护也随着复杂.
  复杂的系统可根据业务功能垂直拆分为不同的服务,由独立的团队进行开发、维护,同时也可以进行分布式部署、易于扩展,提高网站的并发处理能力.

分布式

分层和分割的主要目的就是为了便于分布式部署、开发、维护、扩展.

分布式架构支持横向扩展和纵向扩展 :

  • 纵向扩展 : 主要解决了业务扩展的问题,系统随着业务的发展而越来越复杂,可以在架构上按照业务(功能)去拆分服务,降低系统的耦合、提高系统的可扩展性.
  • 横向扩展 : 主要解决了容量扩容的问题,系统随着业务的发展而并发量越来越高,单服务器的系统资源已经成为了瓶颈,必须在架构上做到水平扩展的能力,计算机越多,CPU、内存、存储资源就越多,能够支撑的并发处理能力、数据存储能力就越大.

集群

  使用分布式后的服务可以独立部署,但是对于一些比较核心的服务,即并发量较高,需要做到集群部署,即多台服务器部署多个相同的服务构成的一个集群,通过负载均衡设备共同对外提供服务.
  服务器集群可以提供更好的并发性、扩展性,当并发量增加时,只需增加新的服务器即可(水平扩展);当集群中某台服务器宕机了,负载均衡设备也会将请求转移转发到其他集群中的服务器上,不影响整体的用户使用,从这里可以看出集群保证了服务的高可用.

缓存

  • 缓存可分为本地缓存 和 分布式缓存 :
    • 本地缓存 : 在应用服务器本地缓存着热点数据,应用程序直接访问本机内存中的数据,无需访问数据库,减少数据库的压力.由于是缓存在本机内存中,所以本地缓存读取数据可以很快,但是需要跟本机应用程序竞争内存.
    • 分布式缓存 : 数据量庞大的情况下,除了本地缓存,还需要分布式缓存,即缓存在一个专门的分布式缓存集群中,通过网络访问缓存数据,
  • 缓存带来的问题,例如 :
    • 数据不一致.即脏读 : 数据库、缓存不一致
    • 正确的使用缓存,即频繁被访问的数据应该放在缓存中

【PS : 缓存是改善系统性能的第一手段】

异步

  异步是典型的生产者消费者模式,最常见的是多线程编程的内存队列(或者叫阻塞队列、工作队列),生产者把任务添加到内存队列中就完成工作了,而消费者,即工作线程会从内存队列中取出任务来完成执行操作;Java提供了几种内存队列,并且线程池就有使用到内存队列.
  在分布式系统中,多个服务器集群通过分布式消息队列来实现异步,分布式消息队列可以看成是内存队列的分布式部署

异步消息队列可以给系统带来以下特性 :

  • 解耦 : 生产者负责生产数据,消费者负责消费数据,两者互不干扰.
  • 可用性 : 消费者宕机后,生产者可以继续处理业务请求,数据会存储堆积在消息队列服务器中,消费者服务器恢复正常后,继续处理消息队列中的数据
  • 响应速度 : 生产者将数据存进消息队列后,不需要等待消费者服务器的响应即可返回了
  • 削峰 : 对一些突发性的暴增访问请求,先放进消息队列,消费者服务器根据自己的处理能力去消费数据,就不会导致一下子负载照成压力过大.

架构中引入异步消息队列给系统带来以下问题 :

  • 由于是网络的不确定因素,需要保证消息的可靠性传输
  • 消息队列中保证消息的不丢失
  • 消费者对消息的幂等性消费
  • 消息队列的消息积压

【PS : 常用的几种开源消息队列有 : RabbitMq、Kafka、RockeyMq】

冗余

  服务器可能随时宕机,通过冗余来保证服务器宕机情况下依然可以提供继续服务,通过服务器冗余运行、数据冗余备份来实现系统的高可用.

  • 集群 : 至少两台服务器构成一个集群
  • 冷备份 : 定期备份
  • 热备份 : 主从架构,实时同步
  • 灾备数据中心

安全

  • 密码、手机效验码、人脸认证等;
  • 敏感信息进行网络加密传输;
  • 防XSS攻击、SQL注入;
  • 对于一些涉及到金额较一的需要做风险控制;

大型网站核心架构要素

大型网站核心架构要素 : 高性能、高可用、易伸缩、可扩展、安全性.

高性能

性能是网站的一个重要指标

服务层

服务层的优化手段主要是缓存、异步、集群;网站性能优化第一定律 : 优先考虑使用缓存优化性能

  • 缓存 :
    缓存主要用来存放那些读写比很高、很少变化的数据,即读多写少;读取数据时,先到缓存读取,如果没有读取到,则再访问数据库,然后写入缓存.
    数据缓存一般以K-V的形式存储在内存散列表中,散列表的数据读写平均时间复杂度为O(1),例如开源的有MongoDB、Redis.
    • 合理使用缓存 :
      • 读多写少 : 读写比在 2:1 以上,即修改一次数据最少要2次读才有意义,这个比例越高越好;
      • 保留热点数据 : 内存资源宝贵且有限,尽可能缓存一些热点的数据,旧数据清理出去,例如常用的LRU最近最少使用算法清理旧数据;
      • 数据不一致导致的脏读 :
        • 实时性弱的场景 : 一般设置过期时间,超过时间后需要从数据库重新读取,这种延迟导致的脏读在大部分场景通常是可以接受的;
        • 实时性强的场景 :
          • 数据库和缓存双写 : 更新数据库数据后删除缓存,还是 删除缓存后更新数据库?由于这两个读写缓存的操作不是原子性操作,所以都存在脏读;
          • 异步串行化 : 把读写请求路由到同一个JVM工作队列,保证读写缓存的操作串行化,这个方案比较复杂;
      • 高可用 :
        • 分布式缓存架构 : 主从复制、主从切换、多主多从
      • 缓存预热 : 启动时把热点数据加载好
  • 异步 :
    • 提高响应速度 : 生产者把数据发送到消息队列就可以立即返回,消费者从消息队列获取数据,异步执行.
    • 肖峰 : 有效抵御大量请求对系统造成的性能影响
    • 系统解耦
  • 集群 : 通过集群提高并发处理能力,避免单一服务器负载压力过大导致的响应缓慢、宕机后服务不可用等问题.
  • 其他层面 :
    • 多线程 :
      • 优先使用线程池来创建线程,而创建线程数应考虑是磁盘IO密集型还是CPU密集型,如果任务是CPU密集型,那么创建的线程数不能超过CPU内核数;如果任务是磁盘IO密集型,那么可以多启动线程有助于提高任务的并行度.
      • 并发安全问题 : 并发工具、局部对象、锁(互斥锁、乐观锁等)
    • 资源复用 : 线程池、对象池、单例模式
    • 数据结构 : 选择合适的数据结构,时间复杂度、空间复杂度的权衡
    • JVM : 根据系统的运行模型来对JVM参数的优化,尽量减少GC,降低延迟、提高吞吐量

数据层

数据层优化手段优先考虑索引B+Tree、固态硬盘、如HDFS分布式文件服务.

  • B+Tree : 保证了数据不断更新、插入、删除后依然有序,传统关系型数据库如MySQL的InnoDB存储引擎使用的就是B+Tree,加快了磁盘数据的检索速度.
  • 固态硬盘 : 固态硬盘又称SSD,SSD的磁盘访问速度比机械硬盘具有更好的性能.
  • HDFS : 分布式文件系统.

高可用

  实现高可用的主要手段是冗余.即应用部署在多台服务器上提供访问,数据存储在多台服务器上相互备份,任何一台服务器宕机了,并不影响系统整体的运行.
  衡量一个系统架构设计是否高可用目标,就是系统中如果有任何一台或者多台服务器宕机了,并不影响系统的整体运行.

  • 与高可用相关 :
    • 集群 : 多台服务器部署多个相同的服务构成的一个集群
    • 负载均衡 : 主要是在并发量较高导致单台服务器的性能不足以承担负载压力,需要通过负载均衡将流量分摊到一个集群组成的多台服务器,从而提高整体系统的并发处理能力.
    • 无状态 : 指应用服务器不保存上下文信息,多个服务节点之间完全对等,请求到任意服务器处理的结果完全一样.
    • 有状态 : 例如登录后的Session(会话)就是有状态的,负载均衡必须保证每次请求到正确的Session服务器.

服务层

  服务层的服务使用集群的方式来实现高可用;服务与服务之间通过分布式调用框架来协调,服务调用会根据负载均衡把请求分发给各个服务器、服务注册中心的心跳检测剔除不可用的服务、网关限流、集群、监控、服务降级、限流、熔断等技术手段来保证整个系统保持高可用.

  服务层的服务的业务大部分都是有状态的,即存在Session,如果不做处理,就会出现用户的多次请求被负载均衡到集群中的不同服务器上,导致Session不一致的问题.如下图,假设用户的Session信息保存在服务2,如果请求被路由到服务1或者服务3,那么会导致用户需要重新登录.

解决session不一致的方案

  • Session 复制 : 集群中的节点同步session,使用的每台服务器都保存了所有session信息.
    • 优势 :
      • 简单,Tomcat自带;
    • 劣势 :
      • 每个节点都存储所有的session,高并发情况下会导致内存不够问题;
      • 节点与节点之间同步导致的内网带宽占用;
      • 受限于内存问题,不利于水平扩展.
  • Session 绑定 : 利用负载均衡的源地址进行Hash算法,路由到同一台服务器;保证了用户所有的请求总是可以路由到同一台服务器上.
    • 优势 :
      • 只需要修改负载均衡配置,不需要修改应用代码
    • 劣势 :
      • 失去了负载均衡的初心,比如性能更好的服务器应该承担更多的请求
      • 扩容一台服务器,会导致一些session失效
      • 不利于水平扩展,性能不好的服务器可能会承担更多的请求
  • Cookie记录Session : 客户端每次请求,把从Cookie取到的Session一起发送给服务器,服务器处理完之后再把修改过的Session响应给客户端.
    • 优势 :
      • 服务器无需存储
      • 支持水平扩展
    • 劣势 :
      • 每次请求都要携带Session,占用外网带宽
      • 受限于Cookie大小
      • 存储在客户端上,存在安全隐患问题
      • 需要支持Cookie,移动端不支持
  • Session服务器 : 独立部署Session服务器统一管理Session,每次请求验证时,访问Session服务器验证即可.由于Session的读取频率很高,所以可以考虑优先使用缓存来存储.
    • 优势 :
      • 没有安全隐患问题
      • 可水平扩展
    • 劣势 :
      • 由服务端统一管理,引入了redis,增加了系统的维护、复杂性
  • Token、JWT替代Session :
    • Token : 可以是一个唯一的32位字符串,用户验证成功后可将token值作为key、value值作为用户信息存储在缓存中
      • 优势 :
        • 由服务端管理,支持一些额外功能,例如 强制用户下线、在线人数等
      • 劣势 :
        • 需要额外存储,占用系统资源
        • 每次验证需要进行一次查询操作
    • JWT : 是Json Web Token的缩写,用户的一些信息可以通过加密到Token,服务端只需对Token解密验证,验证通过就可以直接获取到用户信息,无需进行额外的查询、存储操作,去中心化.
      • 优势 :
        • 无状态、去中心化,无需额外的查询、存储
        • 安全,不会被篡改
      • 劣势 :
        • 服务端无法控制这些无状态的JWT,JWT一旦生成,在失效之前,总是有效的,无法做到强制用户下线、在线人数等功能
        • 开发人员误用导致存储大量的信息,即为了达成"无状态",每个请求都必须把全量的JWT都带着,就会极大的损耗带宽和IO性能
        • 安全问题 : 如果发生 Token 泄露,服务器也只能任其蹂躏,在其未过期期间不能有任何措施

服务层高可用的其他策略

  • 请求超时设置;
  • 异步调用;
  • 服务限流、降级、熔断;

数据层

  数据层的服务器上存储着数据,需要使用持久化保证宕机后数据不丢失,并且使用同步策略保证服务高可用,即主服务宕机时,可选择一台从服务来作为主服务.
  缓存服务的失效会导致数据库访问负载过高而宕机,进而影响整个系统的可用性,因此缓存也需要保持高可用,而缓存不是数据存储服务,缓存服务宕机了会丢失数据,而缓存服务器宕机导致的数据丢失问题进而导致数据库访问负载过高的问题可以通过扩大缓存服务器集群规模来解决,那么单机宕机引起的缓存数据失效的比例和数据库负载变化就较小,对整个系统的影响也较小,即任何一台缓存服务器宕机了,也只是引起一小部分缓存数据失效,不会对应用性能和数据库负载造成太大的影响.

【PS : 同步策略 : 数据写入、更新时,同时也需要同步到多台服务器上,即Slave服务器.】

其他策略

  • 服务性能监控;
  • 系统异常告警;

伸缩性

  指系统通过增加(减少)集群中服务器来提高(缩小)系统的整体吞吐量,这种增减是成比例的,可以叫之为线程伸缩性."伸":服务器的规模总是在不断扩大;"缩":服务器的规模可以根据业务的访问量减少而减少,节约成本.

  • 物理分离实现更好的伸缩 : 不同服务器部署不同的特定服务,如早期的单个服务器处理所有服务到不同服务分离到不同的服务器 :
  • 按不同业务模块分离实现更好的伸缩 :
  • 通过集群规模实现更好的伸缩 : 一个复杂的系统拆分为多个独立部署的服务,有利于我们对一些核心服务做服务器集群部署来对外提供高可用、高性能的服务,这就是集群服务的伸缩性.

  集群伸缩性分为应用服务器集群伸缩性和数据服务器集群伸缩性,这两种集群对于数据状态管理不同,技术实现也有不同的区别;数据服务器集群还可以分为分布式缓存服务器集群和分布式存储服务器集群,这两种集群的伸缩性设计也不同.

应用服务器集群

  应用服务器应该设计成无状态的(分布式共享Session),即应用服务器不存储上下文信息,所以在一个应用服务器集群中,用户每次请求根据负载均衡算法路由到任意一台集群中的服务器,都不影响最终的处理结果.

【PS : 负载均衡算法 : 轮询、加权轮询、随机、最少连接、IP地址Hash计算等.】

分布式缓存服务器集群

  分布式缓存服务器上缓存着数据,所以不能用简单的负载均衡手段来实现,对于缓存访问请求必须路由到对应需要数据的服务器,这一特点严重制约了分布式缓存集群的伸缩性,因为新上线的缓存服务器是没有缓存数据的,而下线的缓存服务器还缓存着热点数据;所以必须做到新上线或者下线的缓存服务器对整体分布式缓存集群影响最小,即新上线 或者 下线缓存服务器后,尽可能减少缓存失效的问题.

  分布式缓存的路由算法 : 路由算法至关重要,决定着缓存请求该访问哪台集群中的服务器、减少缓存失效.常用的缓存的路由算法 :

  • 简单的Hash取余算法 : 对Key值计算出Hash值后对服务器数量取余,得到的余数就是服务器的下标编号.这种算法实现简单,但是对于伸缩性的支持非常的不友好 : 当分布式缓存集群需要扩容时,例如由原来的3台缓存服务器扩容到4台,那么路由算法的计算由原来的除3取余变成除4取余,大约导致75%的缓存失效了(没有命中),而且随着服务器集群扩容规模扩大,这个比例是线性上升的,这个结果是不能接受的.
  • 一致性Hash算法 : 构造一个 0 ~ 2的32次方 的一个整数闭环,根据节点名称的Hash值将缓存服务器节点放置在这个Hash环上,然后根据Key计算出的Hash值,根据这个Hash值顺时针查找距离这个Key的Hash值最近的缓存服务器节点,完成Key到服务器的Hash映射查找,如下图 :

  扩容服务器会造成多大的缓存失效 : 如下图,NODE3是新增的节点,那么对整体的缓存只对NODE2和NODE3之间的缓存数据失效了,其他缓存数据没有影响,并且随着服务器的继续扩容,缓存命中率也是线性增加的,虽然仍有小部分的缓存数据失效了,但是对于整体的影响比例是较小的.

  一致性Hash算法还存在负载不均衡的问题,即可能出现NODE节点的Hash值之间的距离不均匀导致的各个缓存服务器的负载压力不均匀.解决负载不均衡的手段是通过添加虚拟节点,即每台缓存服务器都有一组虚拟缓存服务器(虚拟节点),将虚拟服务器的Hash值放置在环上,Key在环上先找到虚拟服务器节点后再找到真是的缓存服务器,如下图 :

  每个缓存服务器对于的虚拟服务器节点越多,各个缓存服务器节点之间的负载越均衡,在实践中,一台缓存服务器一般为150个(经验值)虚拟节点,太多会影响性能、太少会导致不均衡,具体的还是根据集群规模、负载均衡的精度去设置这个值.

数据存储服务器集群

  数据存储需要保证数据可用性、正确性,相对于分布式缓存服务器集群的伸缩性设计更加复杂.数据存储具体分为关系型数据库和NoSQL数据库.

  • 关系型数据库的伸缩性 : 以MySQL(行式数据库)为例.
    • 读写分离架构 : 数据的更新、写操作都在主服务器上,主服务器通过bin log 同步到从服务器,数据的读操作都是在从服务器上进行.
    • 数据分库(垂直分库) : 不同业务部署不同的数据库.
    • 水平分库 : 对数据量很大的单表进行分片存储(某些字段路由的规则),即一张表的数据被分别存储在多个数据库中.
  • NoSQL数据库的伸缩性 : 以应用最广泛的HBase(列式数据库)为例,HBase的伸缩性主要依赖可分裂的HRegion及可伸缩的分布式文件系统HDFS实现.

可扩展

  指对系统新增新功能时,对现有系统的功能不影响,或者影响最小,不需要对现有系统的结构、代码进行修改.与伸缩性不同的是,伸缩性是增加(减少)集群中的服务器来增强(减少)计算处理能力.开发低耦合系统是软件设计的目标之一,低耦合系统更容易扩展、复用和维护.

分布式消息队列降低系统耦合性

  消息队列是典型的生产者-消费者模式,生产者发送消息到消息队列,一个或多个消费者通过订阅对应的消息队列来消费消息;生产者只需要把消息发送到消息队列,而消费者只需要从消息队列消费消息,全程通过消息队列来解耦,实现了系统的扩展性.
  生产者把消息发送到消息队列后就可以直接返回了,降低了响应延迟,并且在高峰时期,消息可以暂且存储在消息队列中,消费者可以根据自己负载能力去主动到消息队列消费消息,降低数据库等后端的负载压力.

分布式服务降低系统耦合性

  前面已经讲过了分布式服务的拆分,即一个复杂系统进行拆分为多个服务,使用分布式服务也是降低系统耦合性的一个重要手段.

可扩展的数据结构

  关系型数据库的存储方式是结构化的,需要遵循表、字段等设计规范,这些僵硬的数据结构规范限制了扩展,例如新增、修改字段信息时带来的问题,而例如NoSQL数据库对数据的写入就没有这些限制,使应用程序的数据结构可随意扩展,查询的时候也可以根据指定的字段名称去查询.

其他方面

  • 设计模式;
  • 开放平台 : 不同的接口有不同的授权码;当新增服务接口时,只需新增服务相关的授权信息即可,通过统一的授权平台来减少因新增服务接口而影响其他接口的调用.
  • API接口 : 基于RESTful风格;

相关参考资料

  • 《大型网站技术架构核心原理与案例剖析》--- 作者李智慧【书籍】

目录