单机架构
-
简介:应用服务和数据库服务共用一台服务器。
-
出现原因:出现在互联网早期,访问量较小,单机足以满足需求。
-
架构工作原理:通过应用(划分了多个模块)和数据库在单个服务器上写作完成业务运行。
-
优点:部署简单,成本低。
-
缺点:存在严重的性能瓶颈,数据库和应用互相竞争资源。
-
通过 DNS 将域名转换为 IP。
-
通过 IP 找到对应的服务器。
-
通过绑定的端口号找到具体的应用服务。
-
通过查找数据库得到具体信息。
-
将数据库中数据返回给应用服务。
-
应用服务将信息返回给浏览器。
应用数据分离架构
-
简介:应用服务和数据库服务使用不同的服务器。
-
出现原因:单机存在严重的资源竞争,导致站点变慢。
-
架构工作原理:应用(划分了多个模块)和数据库在各自的服务器上通过网络协作完成业务运行。
-
优点:成本相对可控;性能比单机有提升;数据库单独隔离,不会因为应用把数据库搞坏,有一定的容灾能力。
-
缺点:硬件成本变高;性能有瓶颈,无法应对海量并发。
-
浏览器通过 DNS 把域名转为应用服务器的 IP。
-
通过 IP 和 port 访问应用服务。
-
应用服务访问数据库服务器。
-
数据库服务器把数据返回给应用服务。
-
应用服务将信息返回给浏览器。
应用服务集群架构
-
简介:引入了负载均衡,应用以集群的方式运作。
-
出现原因:单个应用不足以支持海量的并发需求,高并发的时候站点响应变慢。
-
架构工作原理:应用不再是一个,而是变成了多个。通过负载均衡来支持海量的并发。
-
优点:应用服务高可用,应用满足高可用,不会一个服务出现问题,整个站点都挂掉的情况;应用服务具备一定高性能,如果不访问数据库,应用相关处理通过扩展可以支持海量请求快速响应;应用服务有一定扩展能力,支持横向扩展。
-
缺点:数据库成为性能瓶颈,无法应对数据库的海量查询;数据库是单点,没有高可用;运维工作增多,扩展后部署运维工作增多,需要开发对应的工具应对快速部署;硬件成本较高。
-
垂直扩展/纵向扩展 Scale Up:通过购买性能更优、价格更高的应用服务器来应对更多的流量。这种方案的优势在于完全不需要对系统软件做任何调整;但劣势也很明显,硬件性能和价格的增长关系是非线性的,意味着选择性能 2 倍的硬件可能需要花费超过 4 倍的价格,其次硬件性能提升是有明显上限的。
-
水平扩展/横向扩展 Scale Out:通过调整软件架构,增加应用层硬件,将用户流量分担到不同的应用层服务器上,来提升系统的承载能力。这种方案的优势在于成本相对较低,并且提升的上线空间也很大。但劣势是带给系统更多的复杂性,需要技术团队有更丰富的经验。
经过团队的学习、调研和讨论,最终选择了水平扩展的方案,来解决问题,但这需要引入一个新的组件----负载均衡:为了解决用户流量向哪台应用服务器分发的问题,需要一个专门的系统组件做流量分发。实际中负载均衡不仅仅指的是工作在应用层的,甚至可能是其他的网络层之中。同时流量调度算法也有很多种。
常见的流量调度算法:
-
Round-Robin 轮询算法:即非常公平地将请求依次分给不同的应用服务器。
-
Weight-Round-Robin 轮询算法:为不同的服务器(比如性能不同)富裕不同的权重(weight),能者多劳。
-
一致哈希散列算法:通过计算用户的特征值(比如 IP 地址)得到哈希值,根据哈希结果做分发,优点是确保来自相同用户的请求总是被分给指定的服务器。
负载均衡软件:Nginx、HAProxy、LVS、F5 等。
读写分离/主从分离架构
-
简介:将数据库读写操作分散到不同的节点上,数据库服务器搭建主从集群,一主一从、一主多从都可以,数据库主机负责写操作,从机只负责读操作。
-
出现原因:数据库成为瓶颈,而互联网应用一般读多写少,数据库承载压力大,主要是由这些读的请求造成的,所以把读写操作分开。
-
架构工作原理:数据库服务器不再是一个,而是变成了多个。数据库主机负责写操作,从机负责读操作,数据库主机通过复制将数据同步到从机。
-
优点:数据库的读取性能提升;读取被其他服务器分担,写的性能间接提升;数据库有从库,数据库的可用性提高了。
-
缺点:热点数据的频繁读取导致数据库负载很高;当同步挂掉,或者同步延迟比较大时,写库和读库的数据不一致;服务器成本需要进一步增加。
在应用服务集群架构中,把用户的请求通过负载均衡分发到不同的应用服务器之后,可以并行处理了,并且随着业务的增长,可以动态扩张服务器的数量来缓解压力。
但是无论扩张多少台服务器,这些请求最终都会从数据库读写数据,到一定程度之后,数据库的压力就成了系统承载能力的新瓶颈。
能否像扩展应用服务器一样扩展数据库服务器?否。
因为数据库服务有其特殊性:如果将数据分散到各台服务器之后,数据的一致性无法得到保障。
所谓数据的一致性:针对同一个系统,无论何时何地,都应该看到一个始终维持统一的数据。
解决办法:保留一个主要的数据库作为写入数据库,其他的数据库作为从属数据库。从库的所有数据全部来自主库的数据,经过同步后,从库可以维护着和主库一致的数据。
为了分担数据库的压力,可以将写数据请求全部交给主库处理,但读请求分散到各个从库中。当然这个过程也是有代价的,主库到从库的数据同步其实是有时间成本的。
应用中需要对读写请求做分离处理,可以利用一些数据库中间件,将请求分离的职责托管出去。比如 MyCat、TDDL、Amoeba、Cobar等。
冷热分离架构
-
简介:引入缓存,实行冷热分离,将热点数据放到缓存中快速响应。
-
出现原因:海量的请求导致数据库负载过高,站点响应再度变慢。
-
架构工作原理:对于热点数据全部放在缓存中,不常用的数据再去查询数据库。
-
优点:大幅降低对数据库的访问请求,性能提升非常明显。
-
缺点:带来了缓存一致性,缓存击穿、缓存失败、缓存雪崩等问题;服务器成本进一步增加;业务体量支持变大后,数据不断增加,数据库单库太大,单个表体量也太大,数据查询会很慢,导致数据库再度成为系统瓶颈。
随着访问量继续增加,发现业务中一些数据的读取频率远大于其他数据的读取频率,把这部分数据称为热点数据,与之相对的是冷数据。
针对热数据,为了提升其读取的响应时间,可以增加本地缓存,并在外部增加分布式缓存,缓存热门信息的 html 页面等。通过缓存能把绝大多数请求在读写数据库前拦截,大大降低数据库压力。
其中涉及的技术包括:使用 memcached 作为本地缓存,使用 Redis 作为分布式缓存,还会涉及缓存一致性、缓存穿透/击穿、缓存雪崩、热点数据集中失效等问题。
垂直分库架构
-
简介:数据库的数据被拆分,数据库数据分布式存储,分布式处理,分布式查询,也可以理解为分布式数据库架构。
-
出现原因:单机的写库会逐渐达到性能瓶颈,需要拆分数据库;数据库的数据量太大,处理压力太大,需要进行分表;为降低运维难度,业界逐渐研发了分布式数据库,库表天然支持分布式。
-
架构工作原理:数据库由多个主从库或者存储集群构成,支持分布式大规模并行处理。
-
优点:数据库吞吐量大幅提升,不再是瓶颈。
-
缺点:跨库 join、分布式事务等问题,这些需要对应的解决,目前的 mpp 都有对应的解决方案;数据库和缓存结合目前能够抗住海量的请求,但应用的代码整体耦合在一起,修改一行代码需要整体重新分布。
随着业务的数据量增大,大量的数据存储在同一个库中显得有些力不从心。所以可以按照业务,将数据分别存储。只要实时操作的表数据量足够小,请求能够足够均匀地分发到多态服务器上的小表,数据库就能通过水平扩展的方式来提高性能。
这种做法显著增加了数据库运维难度,对 DBA 要求较高。数据库设计到这种结构时,已经可以称为分布式数据库。但这只是一个逻辑的数据库整体,数据库里不同的组成部分有不同的单机数据库实现。如分库分表的管理和请求分发,由 Mycat 实现,SQL 的解析由单机的数据库实现,读写分离可能由网关和消息队列来实现,查询结果的汇总可能有数据库接口层来实现等。这种架构其实是 MPP(大规模并行处理)架构的一类实现。
微服务架构
-
简介:微服务是一种架构风格,按照业务板块来划分应用代码,使单个应用的职责更清晰,相互之间可以做到独立升级迭代。
-
出现原因:扩展性差,应用程序无法轻松扩展,因为每次需要更新应用程序时,都必须重新构建整个系统;持续开发困难,一个很小的代码改动,也需要重新部署整个应用,无法频繁并轻松地发布版本;不可靠,即使系统的一个功能不起作用,可能导致整个系统无法工作;不灵活,无法使用不同的技术构建单体应用程序;代码维护难,所有功能耦合在一起,新人不知道从何下手。
-
架构工作原理:一个应用拆分成多个微服务,相互之间协作支持整个应用。
-
优点:灵活性高,服务独立测试、部署、升级、发布;独立扩展,每个服务可以各自进行扩展;提高容错性,一个服务问题并不会让整个系统瘫痪;新技术的应用容易,支持多种编程语言。
-
缺点:运维复杂度高,业务不断发展,应用和服务器都会不断变多,应用和服务的部署变得复杂,同一台服务器上部署多个服务还要解决运行环境冲突的问题,此外,对于需要动态扩缩容的场景,需要水平扩展服务的性能,就需要在新增的服务上准备运行环境,部署服务等,运维变得十分困难;资源使用变多,所有独立运行的微服务都需要占用内存和 CPU;处理故障困难,一个请求跨多个服务调用,需要查看不同服务的日志完成问题定位。
随着人员增加,业务发展,将业务分给不同的开发团队维护,每个团队实现自己的微服务,然后互相之间对数据的直接访问进行隔离,可以利用 Gateway、消息总线等技术,实现相互之间的调用关联。甚至可以把一些类似用户管理等业务提成公共服务。
容器编排架构
-
简介:借助容器技术(如 docker)将应用/服务打包成镜像,通过容器编排工具(如 k8s)来动态分发和部署镜像,服务以容器化方式运行。
-
出现原因:微服务拆分细,服务多部署工作量大,而且配置复杂,容易出错;微服务数量多扩缩容麻烦,而且容易出错,每次缩容后再扩容有需要重新配置服务对应的环境参数信息;微服务之间运行环境可能冲突,需要更多的资源来进行部署或者通过修改配置来解决冲突。
-
架构工作原理:一个应用拆分成多个微服务,每个微服务打包到容器中,相互协作来完成系统功能,通过容器编排工具完成部署运维。
-
优点:部署、运维简单快捷,一条命令就可以完成几百个服务的部署或者扩缩容;隔离性好,容器与容器之间文件系统、网络等互相隔离,不会产生环境冲突;轻松支持滚动更新,版本间切换都可以通过一个命令完成升级或回滚。
-
缺点:技术栈变多,对研发团队要求高;机器还是需要公司自身管理,在大多非高并发场景下,还是需要闲置大量的机器资源来应发突然的高并发,机器自身成本和运维成本都很高,资源利用率低,可以通过购买云厂商服务器解决。
随着业务增长,发现系统的资源利用率不高,很多资源用来应对短时高并发,平时又闲置,需要动态扩缩容,没有办法直接下线服务器,而且开发、测试、生产每套环境都要隔离的环境,运维工作量很大。
容器化技术的出现给这些问题带来了新的解决思路。目前最流行的容器化技术是 Docker,最流行的容器管理服务式 Kubermetes(K8S),应用/服务可以打包为 Docker 镜像,通过 K8S 来动态分发和部署镜像。Docker 镜像可理解为一个能运行应用/服务的最小的操作系统,里面放着应用/服务的运行代码,运行环境根据实际的需要设置好。把整个“操作系统”打包为一个镜像后,就可以分发到需要部署相关服务的机器上,直接启动 Docker 镜像就可以把服务起来,使服务的部署和运维变得简单。
服务通常会有生产和研发 K8S 集群,一般不会公用,研发集群通过命名空间来完成应用隔离,有的公司按照研发目的划分为研发和测试集群,有的公司通过组织架构完成部门间的资源复用。