计组(计算机组成):cpu+内存+io设备
cpu只和内存交互
Io设备:硬盘+网卡+键盘+鼠标等
进程:程序文件进入内存
内核文件:向下管理计算机硬件和资源,开机后内核文件进入内存
所以所有的文件需要和硬件交互时,都是通过内核来进行操作的
计算机操作系统os:内核+应用程序(shell外壳)
程序文件进入内存》
函数调用:Function_Call,知道调用函数文件位置
实模式》保护模式
虚地址:每个进程独有的(进程之间,进程和内核隔离),映射到实际内存的实际地址
Sc:系统调用,通过中断来实现
中断:晶振硬件中断,程序,进程软中断
Idt:中断描述表0--调度函数,128--sc调用函数
Gdt:全局描述表,保护模式下
调度(进程/线程切换):通过中断cpu,来idt表中找到调度函数(内核文件中)地址,来进行来确认需要切换的进程
平时说的成本和开销??就是中断引起的,也可以说是sc系统调用过多
成本是指什么,为什么成本大系统性能会低?
中断操作会进行进程切换,切换就有保护现场,恢复现场,idt内核地址映射,寻址,用户态切换成内核态?等操作
三高系统:高性能,高并发,高可用,中的高性能,对于程序来说,硬件的算力等是固定的,所以可以理解为不浪费sc就是高性能(单机情况下)
例:mysql+redis
- redis作用:mysql的读写操作是需要做sc的,所以频繁的进行读写,是需要很高的成本,所以引入redis,把数据直接放在内存中,之前查询过的数据就把不用再进入数据库中查询,大大减少sc的次数,来提升效率;
- 当同一个查询结果的查询,有很大量的这种请求过来,超过了Redis的并发,比如,redisn最大支持10000qps,但是这是有100000的请求过来,这时怎么处理?
这时,可以新增加一个redis实例,也就是再部署一台redis,当我们查询的数据再redis中查询不到的时候,去到另一台redis中,可以给数据库的操作加锁,等查询到数据并同步到redis再放开锁,其他的请求等一会再查询,就能在redis中查询到
Bufferfileoutputstream(默认8kb的内存空间)和fileoutputstream区别:
普通的fileoutputstream每次调用write的时候,其实就时进行一次sc,而buffer是给了一个字节数组,当数组长度满了或者超过的时候,才会进行一次系统调用,(内核函数名也是write);所以减少sc,效率会差很多。
Io模型:同步IO模型+异步IO模型
同步IO模型
BIO:一个链接由一个线程维护,线程的创建也是需要成本(内存),所以BIO当链接比较多时就会对内存要求比较高,线程一多,内核进行线程之间的调度成本也变高了
NIO:避免了内存消耗问题和调度成本
一个线程维护所有的连接,然后循环遍历连接,如果有就执行,没有连接则立即返回,也继续执行,
但是如果连接传输数据时间间隔比较大,就会需要一直循环遍历(遍历连接,然后进行数据的接收/发送,我的理解数据的接收和发送这个操作,不管有没有结果数据,都会在编译成机器指令时,最后加上陷进指令,触发cpu的中断),所以这里其实我们就会做很多的无用的中断,增加成本,也就是cpu空转。
多路复用器select.poll:
把代码层面的循环连接,读取数据操作交给内核,先内核遍历后,确认哪些连接有数据进来,返回状态给程序,程序再根据状态去read有数据的连接;原先每次循环都会有sc,时间复杂度为O(n)sc,也就是1000次循环,复杂度变成了我O(1000);但是交给内核之后时间复杂度变成了O(1),
所以NIO要结合多路复用器结合才有意义;
但是这种操作,需要把需要遍历的连接作为参数传递到内核,参数的传递就会引起用户态到内核态的切换,也是成本,如果这个能解决就更好了
Epoll:
在内核中开辟空间,把连接全部存储到内核中,用空间换时间
前台有一个请求,传入大量数据到后台,但是后台还要进行二次操作后才会存入数据库,导致后台处理时间过长,前台响应时间很慢,一个是后台这个线程一直被占用,导致不能处理其它请求,另一个是用户体验感很差,怎么解决?
问题分析:首先这个每一次请求都会有一个response,这明显是一个同步操作
解决方案:CQRS读写分离
这种情况我们可以在后台创建一个缓存,根据每个请求的特殊信息生成唯一的ID,然后存放这个ID,以及value为状态的一个数据,初始初始状态为发送成功,然后我们把这个ID返回给前台,然后异步处理我们的数据,并同时更改缓存中请求处理的状态,前台这边再根据这个ID循环发送查询,直到状态是处理过后的状态,比如处理成功或者处理失败,
处理失败的加一台状态机,状态机处理