Lesson 7 分布式系统架构 性能优化,操作系统,文件系统
引言
训练营的课程也接近一半了,本周课程讲了好多东西,性能优化,操作系统,文件系统
一 性能测试
性能测试是性能优化的前提和基础,也是性能优化结果的检查和度量标准。
不同视角下的网站性能有不同的标准,也有不同的优化手段。
主观视角:用户感受到的性能
比如可以数据来多少就显示多少,虽然最后接收完成的时间比较长,
但过程中不会出现无响应的情况降低用户体验
客观视角:性能指标衡量的性能
性能测试指标
不同视角下有不同的性能标准,不同的标准有不同的性能测试指标,网站性能测试的主要指标有响应时间、并发数、吞吐量、性能计数器等。
响应时间
指应用系统从发出请求到收到最后响应数据所需要的时间。
响应时间是系统最重要的性能指标,直观的反映了系统的“快慢”。
并发数
系统能够同时处理请求的数目,这个数字也反映了系统的负载特性。
对于网站而言,并发数即系统并发用户数,指同时提交的用户数目
于此对应,还有
在线用户数(当前登录系统的用户数)
系统用户数(可能访问系统的总用户数)
吞吐量
指单位时间内系统处理的请求的数量,体现了系统的处理能力
对于网站可以用“请求数/秒”或是“页面数/秒”来衡量,也可以用“访问人数/天”或是“处理业务数/小时”等来衡量
TPS(每秒事务数)
HPS(每秒HTTP请求数)
QPS(每秒查询数)
吞吐量=(1000 / 响应时间ms)x 并发数
性能计数器
描述服务器或操作系统性能的一些数据指标
包括System Load、对象与线程数、内存使用、CPU使用、磁盘与网络I/O等指标。
这些指标也是系统监控的重要参数,对这些指标设置报警阈值,当监控系统发现性能计数器超过阈值的时候,就向运维和开发人员报警,及时发现处理系统异常。
性能测试方法
性能测试
以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能瓶颈。
负载测试
对系统不断地增加并发请求以增加系统压力,直到系统的某项或多项性能指标达到安全临界值,如某种资源已经呈饱和状态,这时候继续对系统施加压力,系统的处理能力不但不能提高,反而会下降。
压力测试
超过安全负载的情况下,对系统继续施加压力,直到系统崩溃或不能再处理任何请求,以此获得系统最大压力承受能力。
稳定性测试
被测试系统在特定硬件、软件、网络环境条件下,给系统加载一定业务压力,使系统运行一段较长时间,以此检测系统是否稳定。
在生产环境,请求压力是不均匀的,呈波浪特性
为了更好地模拟生产环境,稳定性测试也应不均匀地对系统施加压力。
并发数与TPS关系、并发数与响应时间关系
[a,b)区间:可以认为服务器较多,资源较多,请求的响应时间基本是不变的,所以此区间可认为TPS是随着并发数的增加而线性增加的。
b点:刚好服务器数量合适,资源刚好够用,请求的响应时间也基本不变,是最佳运行点
(b,c)区间:服务器资源开始不够使用,请求的响应时间增加,但还是能够对每个请求进行处理,不会丢失响应。
[c,d]区间:c点之后,服务器资源随着并发数的增加已严重不足,请求响应时间急剧增加,新的请求得不到及时处理导致超时或无响应等结果,d点时请求响应时间已无限大,服务器完全无响应,认为此时系统已崩溃。
如何选择运行点?
如果认为安全性比较重要,而且成本不是问题,则建议在[a,b]区间运行,在软件架构没问题的情况下随着服务器资源增多,TPS是随着并发数线性增加的,自然能够应对更大程度TPS激增场景,而不会使系统处于崩溃的边缘
如果安全性不是那么重要或者成本受限,则选择在[b, c]区间运行,相应的系统很可能会轻易地达到最大负载点而导致系统开始丢失响应,这是必须要考虑清楚的
全链路压测
指的是在特定的业务场景下,将相关的链路完整的串联起来同时施压,尽可能模拟出真实的用户行为。
当系统整站流量都被打上来的时候,必定会暴露出性能瓶颈,才能够探测出系统整体的真实处理能力,以及有指导的在大促前进行容量规划和性能优化,这便是线上实施全链路压测的真实目的。
全链路压测的挑战
压测相关的业务系统上众多,并且牵涉到整条链路上所有的基础设施和中间件,如何确保压测流量能够畅通无阻,没有死角?
压测的数据怎么构造(亿万级的商品和用户),数据模型如何与真实贴近?
全链路压测直接在线上的真实环境进行模拟,怎么样来保障对线上无影响?
大型促销活动所带来的巨大流量要怎么样制作出来?
数据隔离
逻辑隔离
直接把测试数据和正常数据写到一起,通过特殊的标识能够区分开
可能污染线上数据,破坏线上数据安全性
虚拟隔离
在所有写数据的地方做mock,并不真正的写进去
这个方案不会对线上产生污染,但是mock对压测结果的准确性会产生干扰
物理隔离
所有写数据的地方对压测流量进行识别,判断一旦是压测流量的写,就写到隔离的位置,包括存储、缓存、搜索引擎等等
流量构造
压测管控台
master
管理上千个slave节点
负责整个平台的运转控制、命令发送、数据收集、决策等
压测引擎
slave
部署在全球各地的cdn节点
负责模拟从全球各地过来的用户请求
全链路压测平台化
压测资源池子
CDNs
引擎分组
CDNs
需求绑定
压测需求
业务方
PE
软件性能优化的两个基本原则
你不能优化一个没有测试的软件
你不能优化一个你不了解的软件
性能优化的一般方法
性能测试,获得性能指标
指标分析,发现性能与资源瓶颈点
架构与代码分析,寻找性能与资源瓶颈关键所在
架构与代码优化,优化关键技术点,平衡资源利用
性能测试,进入性能优化闭环
系统性能优化的分层思想
机房与骨干网络性能优化
异地多活的多机房机构
专线网络与自主CDN建设
服务器与硬件性能优化
使用更优的CPU,硬盘(SSD优于HDD),内存,网卡
二 操作系统
进程
进程是具有一定独立功能的程序在一个数据集合上的一次动态执行过程。
操作系统通过进程的分时执行,在CPU资源有限的情况下实现数以千计的并发请求。
进程运行期的状态
运行: 当一个进程在CPU上运行时,则称该进程处于运行状态。处于运行状态的进程的数目小于等于CPU的数目。
就绪: 当一个进程获得了除CPU以外的一切所需资源,只要得到CPU即可运行,则称此进程处于就绪状态,就绪状态有时候也被称为等待运行状态。
阻塞: 也成为等待或者睡眠状态,当一个进程正在等待某一件事情发生(例如等待I/O完成,等待锁)而暂时停止运行,这时即使把CPU分配给进程也无法执行,故称该进程处于阻塞状态。
线程
是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
线程栈
线程栈存储的信息是指某时刻线程中方法调度的信息,当前调用的方法总是位于栈顶。当某个方法被调用时,此方法的相关信息压入栈顶。
线程安全
当代码修改进行共享内存里的数据时,如果有多个线程同时在执行时,就可能会出现同时修改的情况,但是这个数据最终只会被修改一次。这个就是人们常说的线程安全问题。
临界区
多个线程访问共享资源的这段代码被称为临界区,解决线程安全问题的主要方法是使用锁,将临界区的代码加锁,只有获得锁的线程才能执行临界区的代码。
阻塞导致高并发系统的奔溃
锁会引起线程阻塞,阻塞导致线程既不能继续执行,也不能释放资源。进而导致资源耗尽。最终导致系统奔溃。
避免阻塞引起的奔溃
限流: 控制进入计算机的请求数,进而减少创建的线程数。
降级: 关闭部分程序的功能,尽早释放程序。
避免阻塞: 异步I/O; 无临界区。
锁
偏向锁
指一段同步代码一直被一个线程访问,那个该线程会自动获取锁,降低获取锁的代价。
轻量级锁
当锁是偏向锁时,被另外一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式升级锁,不会阻塞提高性能。
重量级锁
当锁是轻量级锁时,另一个线程虽然会自旋,当自旋到一定次数时,还没有获得到锁,就会进入阻塞,该锁膨胀为重量级锁,重量级锁会让其他申请的线程进入阻塞,性能降低。
各种锁介绍
总线锁
使用处理器的Lock#信号,当一个处理器在内存总线上输出此型号时,其他处理器的请求将被中断,该处理器独占内存。
缓存锁
指在内存区域如果被缓存在处理器的缓存中,并且在Lock操作期间被锁定,那么当他执行操作回写到内存时,处理器不在总线上声言Lock#信号。而实修改内部的内存地址,并允许他的缓存一致性机制来保证操作的原子性,因为缓存一致性机制阻止同时修改由两个以上处理器缓存的内存数据,当其他处理器h回写已被锁定的缓存行数据时,会使缓存行无效。
公平锁
多个线程按照申请锁的顺序来获得锁。
非公平锁
多个线程并不是按照申请锁的顺序来获得锁的,有可能后申请的先获得锁,可能会造成饥饿现象。
可重入锁
某个线程已经获得锁,可以再次获得锁而不会出现死锁。
独享锁/互斥锁
该锁一次只能被一个线程所持有。
共享锁
可以被多个线程持有。
读写锁
多个读线程之间并不互斥,而写线程与其他线程要互斥。
乐观锁
对于同一个数据的并发操作,是不会发生修改的。在更新数据时,检查是否被修改过,如果已修改,则放弃。
悲观锁
对于同一个数据的并发操作,是一定会发生修改的。因此只要对同一个数据进行并发操作就采取枷锁的形式。
分段锁
细化锁的颗粒度,当操作不需要更新整个数组数据时,就仅仅针对数组的一段进行加锁操作。
自旋锁
指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,从而减少线程上下文切换的内存消耗。缺点是循环会消耗CPU的资源。
三 文件与硬盘I/O
B+树
B+树主要是提升磁盘的读的性能。快速的原因是,索引结点中不存数据,只存键和指针,所以一个索引结点就可以存储大量的分支,而一个索引结点只需要一次磁盘IO即可读取到内存中。通常只要几次磁盘IO就可以访问到你想要的数据。
LSM树
LSM树主要是提升磁盘的写的性能。能显著地减少硬盘磁盘臂的开销,一次性的读取或写入固定大小的一块数据,并尽可能的减少随机寻道这个操作的次数。
文件控制块
文件系统将硬盘空间以块为单位进行划分,每个文件占据若干块,然后再通过一个文件控制块的FCB记录每个文件占据的硬盘数据块。
磁盘阵列
分布式文件系统 HDFS
架构
NameNode: NameNode用于存储、生成文件系统的元数据。运行一个实例。
DataNode: DataNode用于存储实际的数据,将自己管理的数据块上报给NameNode ,运行多个实例。
Client: 支持业务访问HDFS,从NameNode ,DataNode获取数据返回给业务。多个实例,和业务一起运行。
HDFS数据的写入流程
业务应用调用HDFS Client提供的API,请求写入文件。
HDFS Client联系NameNode,NameNode在元数据中创建文件节点。
业务应用调用write API写入文件。
HDFS Client收到业务数据后,从NameNode获取到数据块编号、位置信息后,联系DataNode,并将需要写入数据的DataNode建立起流水线。完成后,客户端再通过自有协议写入数据到DataNode1,再由DataNode1复制到DataNode2, DataNode3。
写完的数据,将返回确认信息给HDFS Client。
所有数据确认完成后,业务调用HDFS Client关闭文件。
业务调用close, flush后HDFSClient联系NameNode,确认数据写完成,NameNode持久化元数据。
HDFS数据的读取流程
业务应用调用HDFS Client提供的API打开文件。
HDFS Client联系NameNode,获取到文件信息(数据块、DataNode位置信息)。
业务应用调用read API读取文件。
HDFS Client根据从NameNode获取到的信息,联系DataNode,获取相应的数据块。(Client采用就近原则读取数据)。
HDFS Client会与多个DataNode通讯获取数据块。
数据读取完成后,业务调用close关闭连接。
评论