后端术语快速扫盲
点击蓝色字关注我们吧!
大家好我是张拭心,前段时间听完了某时间 app 上的后端架构课程,在公司也参加了一些后端方面的技术培训,想着要总结一下,就吹出了上一篇的牛。
然而在写作过程中,我发现很难用自己的话把学到的知识表述一遍。我们知道如果可以用自己的理解来描述一个知识点,证明这个知识已经和我们当前的知识点建立了联系,但后端开发我经验很少,学到的理论知识还基本是个孤岛,没办法有很多自己的理解。
文章的内容缺乏自己的创作,甚至直接是一些优质文章的复制,这在我看来最多能算作学习笔记,距离我当初吹的牛差的太远,希望读者朋友能够理解包容一下,谢谢了。
读完本文,希望你会对后端一些常用的术语有所理解。
我们知道,与前端关注 C 端体验不同,后端关注后台数据处理能力。用户量多与不多,访问次数多与少,在后端需要做的工作完全不同。
为了应对高并发的请求,后端系统需要具备高性能、高可用、可拓展等特点,为了实现这三点,要做的工作非常多,我们来简单了解下。
经常听到后台人员介绍自己开发的系统 QPS 多少多少,这是什么意思呢?
QPS(TPS)、并发数、响应时间(RT)
简单概括:这些数据代表着系统的处理能力。
QPS
表示的是:每秒处理完的请求数,一般针对单个接口服务,又叫“吞吐量”TPS
表示的是:每秒处理完的事务数,一个事务在分布式中可能对应多个请求,因此这个指标一般针对整个系统并发数
表示系统同时能处理的请求数,受线程数、 进程数、CPU 数等影响响应时间(RT)
:表示处理一次请求所需的平均时间,包括CPU运算、IO、外部系统响应等时间组成。
QPS(TPS)= 并发数/平均响应时间
一个系统吞吐量通常由QPS(TPS)、并发数两个因素决定。
每套系统这两个值都有一个相对极限值,在应用场景访问压力下,只要某一项达到系统最高值,系统的吞吐量就上不去了,如果压力继续增大,系统的吞吐量反而会下降,原因是系统超负荷工作,上下文切换、内存等等其它消耗导致系统性能下降。
做系统设计时,要考虑 CPU 性能、IO 操作耗时以及外部系统响应时间造成的响应时间影响,除了要评估出大概的 QPS、并发数后,还要考虑系统最高能承受的 TPS 多少。
拿淘宝来说,凌晨的访问量比较少,需要的机器不太多,但到了中午或者晚上访问量骤增,为了能灵活的应对这种不同时间要求不同的处理能力,同时尽可能地降低成本,使用云计算资源是一个好的出路。
分布式与集群
单个服务器终究性能有限,要实现能够处理高并发请求的系统,需要有集群,还得设计高性能的分布式系统来提系统的处理能力。
简单概括分布式与集群的区别:分工协作和一群人。
分布式和集群的概念似乎有些重复,都说的是好多机器,但实际上集群指的就是一群机器,没有额外的业务信息。而分布式强调的是将不同的业务分散到不同的机器上,分散每个服务器的压力。
上图中,集群指的是三个 Web Server,而分布式是指:客户端的访问经过负载均衡器分发到不同的 Web 服务器。
分布式包含的内容很多,如下图所示,有兴趣的朋友可以进一步学习:
分布式会带来很多的其他问题,最主要的就是一致性。
推荐阅读:小白科普:分布式和集群分布式与集群的区别是什么?什么是分布式系统,如何学习分布式系统
高性能
后台系统中的“高性能”主要包括两部分:
尽可能多地榨干单台计算机的性能
尽可能高的利益计算机集群的能力
单台计算机的高性能
操作系统和性能最相关的就是进程和线程:
每个进程占据独立内存空间,CPU 分片串行处理,进程通信,操作系统分配资源的最小单位
线程是进程内部的子任务,共享同一份进程数据,多线程并发,互斥锁,操作系统调度的最小单位
它们的存在是为了让计算机在 IO 或者网络时,CPU 仍然能忙碌着。具体实现采用多进程还是多线程,不同的业务可能适合不同的方式,没有最好的选择。
Nginx 可以用多进程也可以用多线程,JBoss 采用的是多线程;Redis 采用的是单进程;Memcache 采用的是多线程。
计算机集群的高性能
拥有计算机集群是提升性能的第一步,第二步就是如何让多台机器配合起来达到高性能。主要有两种方式:
任务分配
任务分解
任务分配指的是在客户端和业务服务器之间增加一层任务分配器,他们的作用就是负责分配任务给合适的机器。这个分配的复杂点在于,任务分配的算法和任务分配器多了,还需要负责分配给任务分配器的分配器。
任务分解指的是将不同的业务系统分配到不同的机器上,把原本大一统但复杂的系统,拆分成多个简单但需要配合的系统,然后再针对部分访问量大的系统做优化。
高可用
高可用指的是系统无中断地执行器功能的能力。
难点就在于“无中断”,无论硬件还是软件都会逐渐不可用,比如硬件会逐渐老化,软件会逐渐复杂不好维护。
软件系统的高可用主要是通过增加冗余机器实现的,一般包括两种:
计算高可用
存储高可用
计算高可用
“计算”指的是业务逻辑,计算高可用的目的是无论在哪台机器上执行业务逻辑,最后的结果都一致。
在前面一小节我们提到不同的业务最好分配到不同的机器上,为了实现高访问量的业务高可用,就需要为它提供备用服务器,比如 1 主 N 备.
和前面高性能一样,同样需要有一个任务分配器来分配业务给主服务器或备服务器:
这就要求分配器高可用以及算法合适,同时做到数据及时同步。
存储高可用
我们知道,数据 + 逻辑 = 业务。存储高可用的目的是尽可能地保证数据在不同机器上都是一致的。
但由于数据从一台机器搬到另一台机器需要时间,不同地理位置、不同网络状况下需要的时间各不同。对于整个系统而言,在某个时间点上,数据一定是不一致的,最后会导致业务出问题。
因此,存储高可用的难点在于如何减少或者规避数据不一致导致的业务异常。
状态决策
无论计算高可用还是存储高可用,本质上都是通过冗余实现。系统需要能够根据当前状态做出决策,一般有三种决策方式:
独裁式
只有一个独立的决策者,其余冗余的个体不参与决策。优点是简单,缺点是决策者故障时系统就会故障。
协商式
两台机器通过交流信息,根据规则进行决策,比如主备决策。难点在于规则的确定和信息交换异常的处理。
选举式
通过投票的方式来进行状态决策。难点在于算法复杂,还有可能乎产生“脑裂”。
推荐阅读:复杂度来源:高可用
可拓展
可扩展性是指系统应对需求变化的一种扩展能力。当新需求出现时,可以不修改或者尽可能少的修改即可支持。
设计可扩展的系统,主要有两步:
正确预测变化
结合行业业务发展方向,预测未来技术方向
结合公司业务发展规模,预测高性能、高可用相关压力
适度预测,不要过度设计
完美封装变化
拆分出变化层和稳定层
设计变化层和稳定层之间的接口
数据库集群
在业务复杂到一定程度后,数据库服务器也需要集群,数据库集群一般有两种实现方式:
读写分离
分库分表
读写分离及 主从/主备复制
读写分离是指将对数据库的读和写分配到不同的机器上。
“主从复制”,其实是实现“读写分离”的一种方案,如下图所示:
读写分离中,有一个主机,多个从机。主机既可以写入又可以读取,从机只能读取。
主机需要定时将写入的数据同步到从机,但这个写入的过程可能会有延时,因此可能会导致不同的查询得到的结果数据不一致。
可以看到,从机帮主机分担了读取的重担,但写入的重担还是集中在主机上,在写操作频繁的情况下,主机也会面临很大压力。
另外,为了实现读写操作的分离访问,在数据库集群前还需要一个“读写分离器”,这个读写分离器可能还需要实现连接的管理。
主备复制 和 主从复制 的区别就在于,备机只负责备份,不提供读的功能。
数据库切分,分库分表
前面提到的“读写分离”是将访问压力分散到集群中的多个节点,但是没有分散每台数据库的存储压力。
当一张表的数据达到千万甚至上亿级别时,即使做了读写分离,单台数据库的存储压力还是没有得到解决。
针对这种情况,有了“数据库切分”的概念。
“数据库切分”是指当单台数据库存储的数据量过大时,需要将它进行拆分,将存储分散到多台数据库服务器上。主要有两种拆分方式:
业务分库
分表
业务分库
分库指的是:按照业务模块将数据分散到不同的数据库服务器。
比如下图所示的,将原本存储在一个数据库服务器上的用户数据、消息数据和其他数据,拆分到三台独立的数据库服务器上。
单台数据库服务器存储的数据量降低后,查询压力也会降低。但硬币总是有双面的,分库虽然有好处,但同时由于单机变成了集群,复杂度上升了很多。
常见的几点问题:
join 查询无法使用,导致需要多次查询
多台数据库存储的数据如果有关联关系,要实现事务的功能比较杂
成本上升,一台服务器变成多台
分表
某个数据库中的某个表数据过大时,也会导致性能问题。分表指的是:对同一业务的单表数据进行拆分。 主要有两种拆分方式:
垂直切分
水平切分
垂直切分
垂直切分是指将一个表中的某些字段相关的数据拆分到另外一个数据库中。
如上图所示,垂直切分前,该表中存储的是 name age sex nickname description 相关的数据,列比较多;垂直拆分后,该表中存储的是 name age sex 相关的数据,nickname description 相关的数据被放到了另外的表中。
这样在单独查询 name age sex 时,可以提高一些性能。
水平切分
水平切分是指将一个表中的某些行的数据拆分到另一个数据库中。
如上图所示,水平切分前,该表存储着 9999999 列数据;水平切分后,当前表中只保存 999999 列数据,剩余的数据可能会被切分多次分到不同的表中。
切分后是否要将多切出来的表放到不同的数据库服务器,需要根据实际业务情况决定。单表切分为多表后,即使都在同一个数据库服务器,也可以带来可观的性能提升。
对于海量数据的数据库,如果是因为表多而数据多,这时候适合使用垂直切分,即把关系紧密(比如同一模块)的表切分出来放在一个server上。如果表并不多,但每张表的数据非常多,这时候适合水平切分,即把表的数据按某种规则(比如按ID散列)切分到多个数据库(server)上。当然,现实中更多是这两种情况混杂在一起,这时候需要根据实际情况做出选择,也可能会综合使用垂直与水平切分,从而将原有数据库切分成类似矩阵一样可以无限扩充的数据库(server)阵列。
应该是这些操作依次尝试1.做硬件优化,例如从机械硬盘改成使用固态硬盘,当然固态硬盘不适合服务器使用,只是举个例子2.先做数据库服务器的调优操作,例如增加索引,oracle有很多的参数调整;3.引入缓存技术,例如Redis,减少数据库压力4.程序与数据库表优化,重构,例如根据业务逻辑对程序逻辑做优化,减少不必要的查询;5.在这些操作都不能大幅度优化性能的情况下,不能满足将来的发展,再考虑分库分表,也要有预估性
负载均衡
只有一台机器时我们收到请求直接处理即可,但如果有多台机器,就需要考虑这个请求究竟要让哪台机器访问,是均衡一些让每台机器承受的访问量差不多,还是由处理性能最高的机器处理,或者是由靠的最近的机器来处理。完成这个处理、分发请求功能的组件,被大家称为“负载均衡”。
常见的负载均衡主要有三种:
DNS 负载均衡
硬件负载均衡
软件负载均衡
DNS 负载均衡
DNS 负载均衡一般用于地理级别的负载均衡,比如给北京用户返回离北京近的机器 A,给上海用户返回离上海近的机器 B。这需要后端服务器部署到不同地区的不同机房。
如下图所示:
图片来自:高性能负载均衡:分类及架构
硬件负载均衡
硬件负载均衡是指通过单独的硬件设备来实现负载均衡,类似路由器和交换机,知名的有 F5 和 A10:
相对 DNS 软件负载均衡,硬件负载均衡性能更好,但价格也更高,动辄几十万甚至上百万一台,贴几张图感受一下:
软件负载均衡
软件负载均衡是指通过软件来实现负载均衡,知名的有 Nginx 和 LVS:
Nginx 起到的是一个代理服务器的作用,它将客户端的请求转发给服务端,然后再将接收到的响应转发给客户端。转发给服务端的过程中可以制定一些负载均衡策略。
LVS 即 Linux Virtual Server,也就是 Linux 虚拟服务器。现在 LVS 已经是 Linux 内核标准的一部分。使用 LVS 可以达到的技术目标是:通过 LVS 达到的负载均衡技术和 Linux 操作系统实现一个高性能高可用的 Linux 服务器集群,它具有良好的可靠性、可扩展性和可操作性。从而以低廉的成本实现最优的性能。LVS 是一个实现负载均衡集群的开源软件项目,LVS架构从逻辑上可分为调度层、Server集群层和共享存储。
负载均衡架构
实际项目中,我们可能会使用上述负载均衡分类的一种甚至多种,比如用 DNS 实现地理级别的负载均衡;用硬件负载均衡实现集群级别的负载均衡;用软件实现机器级别的负载均衡。
图片来自:高性能负载均衡:分类及架构
推荐阅读:高性能负载均衡:分类及架构快速了解负载均衡浅谈Nginx负载均衡与F5的区别使用LVS实现负载均衡原理及安装配置详解
限流,熔断,降级
分布式系统中,服务间的依赖链可能会非常长,很有可能会出现某个基础服务奔溃或者阻塞,导致其他依赖的服务器也奔溃或者阻塞,如下图所示:
图片来自:防雪崩利器:熔断器 Hystrix 的原理与使用
上图中 DC 依赖 B,B 依赖 A,当 A 不可用时会导致 B 不可用,从而导致 DC 也不可用。这种“因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大”的过程,叫做“服务雪崩”。
服务雪崩出现的原因有很多,其中比较常见的一种是客户端流量过大或者失败后重试频繁。
为了避免大量请求因为某个服务不可用而阻塞,提出了“限流器”、“熔断器”和“降级”的概念。
“限流器”即流量控制,一般有网关限流、用户交互限流和关闭重试等。
“熔断器”即通过一个开关控制某个服务的使用与关闭,如果该服务在处理多次请求中都不可用,就打开开关,让请求到达不了它,即停止使用该服务。在过段时间(时间窗)后,尝试半开开关(即允许少量流量通过),观察处理性能,如果响应时间等还没有恢复正常,就再次关闭;反之如果恢复,就让它回到正常使用状态。
降级不仅是在服务器不可用时要设置“备胎”,更要提前做好预防工作(资源进行隔离、依赖的服务进行分类等)。
在某个服务不可用时快速响应,避免大量请求因为某个服务不可用通通阻塞。
推荐阅读
毕业两年总结