书名:《软件架构设计:大型网站技术架构与业务架构融合之道》,豆瓣评分很高,内容质量确实不错。
第一部分 计算机功底
一、操作系统
1、缓冲I/O和直接I/O
缓冲I/O是C语言提供的库函数,直接I/O是Linux的系统API,操作系统的API也是C写的。
- 应用程序内存:比如new等分配的内存
- 用户缓冲区:C语言FILE缓冲
- 内核缓冲区:linux操作系统的Page Cache。Linux系统会把磁盘上的数据以Page为单位缓存在操作系统的内存里。一个Page一般4k。
缓冲I/O对应:应用程序内存->用户缓冲区->内核缓冲区->磁盘 直接I/O对应:应用程序内存->内核缓冲区->磁盘
fflush和fsync的区别:
- fflush是缓冲I/O中的一个API,它只是把数据从用户缓冲区刷新到内核缓冲区而已。
- fsync是把数据从内核缓冲区刷新到磁盘里。
2.内存映射文件和零拷贝
拷贝是把数据从一块内存中复制到另外一块内存中;映射相当于只是持有了数据的一个引用(地址),数据本身只有一份。
3.网络I/O模型
- 同步阻塞I/O:linux系统的read和write函数,在调用的时候会被阻塞,直到数据读取完成,或者写入成功;
- 同步非阻塞I/O:和同步阻塞I/O的API一样,只是打开fd的时候带有O_NONBLOCK 参数。当调用read和write函数时,如果没有准备好数据,会立即返回, 不会阻塞,然后让应用程序不断去轮询。注意:fd是file descriptor,进程独有的文件描述符表的索引。
- I/O多路复用:如果fd很多(连接数可达到几十万甚至百万)。如果使用同步阻塞I/O,那么一个线程处理一个fd;如果使用同步非阻塞I/O,那么应用程序 轮询大规模的fd,都不可行。所以有了I/O多路复用。在linux系统,有三种I/O多路复用的方法:select、poll、epoll。
- 异步I/O:读写都是由操作系统完成的,然后通过回调函数或者某种其他通信机制通知应用程序。Linux系统中,异步I/O是由epoll实现的。
4.进程、线程、协程
- Java程序并不是直接运行在linux系统上,而是运行在JVM上。一个JVM实例是一个Linux进程,JVM之间相互独立,互不通信。
- 多线程主要是为了应对I/O密集型的应用。
- 多协程:单机可以开几万个协程,比线程并发度更高。但是不够成熟,java不支持。
5.无锁(内存屏障与CAS)
- 在多核CPU体系下,每个CPU有自己的缓存,改过的值可能还在CPU缓存里,没有刷新到内存里,内存屏障就是要强制把这个值刷新到内存里;内存屏障也起到保证 执行顺序的作用。
- CAS是在CPU层面提供的一个硬件原子指令。CAS是一条原子指令,不会造成所谓的数据不一致的问题。CAS 操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B)