一、计算机网络
TCP/UDP
- TCP/IP即传输控制协议,是面向连接的协议,发送数据前要先建立连接,TCP提供可靠的服务,也就是说,通过TCP连接传输的数据不会丢失,没有重复,并且按顺序到达。(类似于打电话)
- UDP它是属于TCP/IP协议族中的一种。是无连接的协议,发送数据前不需要建立连接,是没有可靠性的协议。因为不需要建立连接所以可以在在网络上以任何可能的路径传输,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。(类似于发微信)
TCP三次握手四次挥手
三次握手:
- 第一次握手:客户端向服务器发送请求,请求建立数据连接。
- 第二次握手:服务器收到请求后,向客户端发送确认信息,表示服务器已经收到请求并同意建立数据连接。
- 第三次握手:客户端收到确认信息后,再向服务器发送确认信息,表示客户端已经收到确认信息,数据连接建立成功。
四次挥手:
- 第一次挥手:客户端向服务器发送请求,请求断开数据连接。
- 第二次挥手:服务器收到请求后,向客户端发送确认信息,表示服务器已经收到请求并同意断开数据连接。
- 第三次挥手:客户端收到确认信息后,再向服务器发送确认信息,表示客户端已经收到确认信息,数据连接断开成功。
- 第四次挥手:服务器收到确认信息后,再向客户端发送确认信息,表示服务器已经收到确认信息,数据连接断开成功。
七层网络
- 物理层:主要负责传输数据的物理基础,如电缆、无线等。
- 数据链路层:负责在物理层的传输的基础上,建立通信链接,保证数据的正确传输(以太网、蓝牙、WIFI)。
- 网络层:负责实现数据的路由和传输,从而实现网络的连通性(IP、ICMP、ARP、RIP、OSPF 等)。
- 传输层:负责确保数据的可靠传输,如重传、检测丢包等(TCP、UDP 等)。
- 会话层:负责管理会话的建立、维护和终止。
- 表示层:负责处理数据的格式,以及对数据进行编码和解码。
- 应用层:负责实现应用程序的通信(HTTP、FTP、SMTP、DNS)。
HTTP:请求-响应通信协议
请求报文格式:请求行(url、端口、请求方式、HTTP版本)、请求头(编码、服务器地址)、请求体
响应报文格式:状态行、响应头部、响应体
HTTPS:非对称加密的采用SSL/TLS 协议的请求响应协议
WebSocket:双向通信协议,例如动态数据,如实时状态、聊天消息
IPV4/IPV6:32位/64位,并在数据包格式、协议特性、安全性方面做了改进
输入URL到渲染页面的过程:
- DNS域名解析ip地址、建立TCP连接、三次握手四次挥手、HTTP请求和响应、解析HTML及其他资源、渲染页面
状态码
滑动窗口协议
滑动窗口协议是一种用于在不可靠的网络上传输数据的协议。发送方将数据分成多个部分,并分配序号,接收方按照序号接收数据,并发送确认信息给发送方,以确保数据的正确传输。发送方会根据接收到的确认信息进行调整,以提高传输效率。滑动窗口协议的窗口大小是一个关键参数,它限制了发送方和接收方未确认数据的数量。
对称加密和非对称加密SSL/TLS协议
HTTPS使用了非对称加密算法和对称加密算法相结合的方式来实现数据加密。其中,非对称加密算法用于在客户端和服务器之间进行密钥交换,而对称加密算法则用于在数据传输过程中对数据进行加密和解密。
对称加密算法使用相同的密钥对数据进行加密和解密,因此密钥需要在客户端和服务器之间共享。这种方式的优点是加密和解密速度快,但缺点是密钥容易被窃取,从而导致数据泄露(AES)。
非对称加密算法则使用一对密钥,分别为公钥和私钥。公钥可以公开,任何人都可以使用它对数据进行加密,但只有持有私钥的人才能解密数据。这种方式的优点是密钥不需要共享,因此更安全,但缺点是加密和解密速度较慢(RSA)。
在HTTPS中,非对称加密算法用于在客户端和服务器之间进行密钥交换,以确保传输的密钥不被窃取。然后,使用对称加密算法对数据进行加密和解密,以保证数据传输的安全性和效率。
HTTP截获报文
- 代理服务器(Proxy Server)截获:代理服务器是客户端和目标服务器之间的中介,它可以截获客户端发送的HTTP请求和目标服务器返回的HTTP响应。代理服务器可以在不改变请求的情况下,记录请求和响应的内容。
- 网络分析工具(Network Sniffer)截获:网络分析工具可以在网络上截获所有通过该工具所在的网络接口的数据包,包括HTTP请求和响应。网络分析工具可以根据协议类型过滤HTTP请求和响应,以便分析和记录。
- 浏览器插件(Browser Extension)截获:浏览器插件可以截获浏览器发送的HTTP请求和接收的HTTP响应。例如,Chrome浏览器的开发者工具可以截获浏览器发送的HTTP请求和接收的HTTP响应,并提供详细的请求和响应报文的分析和调试功能。
HTTP的Header
- Accept:指定客户端可接受的MIME类型
- Accept-Encoding:指定客户端可接受的编码类型
- Authorization:包含用于身份验证的凭证,通常是用户名和密码的Base64编码
- Cache-Control:指定缓存机制
- Content-Length:指定请求或响应正文的长度
- Content-Type:指定请求或响应正文的MIME类型
- Cookie:包含客户端的Cookie信息
- Host:指定请求的主机名和端口号
- If-Modified-Since:指定上次修改时间,用于条件GET请求
- User-Agent:包含客户端的用户代理信息
TCP标志位
- SYN(Synchronize):SYN标志位被设置为1时,表示发送方请求建立连接。在三次握手中,客户端向服务器发送的第一个报文中,SYN标志位被设置为1,表示客户端请求建立连接。
- ACK(Acknowledgement):ACK标志位被设置为1时,表示接收方已经收到了发送方的数据。在三次握手和四次挥手中,ACK标志位用于确认收到对方的报文。
- FIN(Finish):FIN标志位被设置为1时,表示发送方要关闭连接。在四次挥手中,发送方向接收方发送FIN报文,表示发送方已经没有数据要发送了。
TIME_WAIT状态
主动关闭方在收到被动关闭方的FIN
包后并返回ACK
后,会进入TIME_WAIT
状态,TIME_WAIT
状态又称2MSL
状态,每个TCP连接都必须有一个最大报文段生存时间MSL,在网络传输中超过这个时间的报文段将被丢弃。当TCP连接发起一个主动关闭,并发出最后一个ACK时,必须在TIME_WAIT
状态停留两倍MSL时间,在2MSL
等待期间,定义这个连接的插口(客户端IP地址和端口号,服务器IP地址和端口号的四元组)将不能再被使用。2MSL
状态存在有两个理由:
1.允许老的重复报文分组在网络中消逝。
2.保证TCP全双工连接的正确关闭。
二、数据结构
栈与堆的区别
栈和堆都是计算机内存中的存储区域,但它们有以下不同之处:
- 存储方式:栈是一种后进先出(LIFO)的数据结构,它的存储方式类似于一摞盘子,新的数据存放在最顶部,取数据时也从顶部取出;堆则是一种动态分配内存的机制,它的存储方式是将数据存储在不连续的内存空间中。
- 内存分配方式:栈的内存分配方式是由编译器自动管理的,它会在程序运行时自动分配和释放内存空间,不需要手动控制;堆的内存分配则需要由程序员手动申请和释放内存空间,否则可能会出现内存泄漏等问题。
- 访问速度:由于栈的内存结构是连续的,所以访问速度较快;而堆的内存结构是不连续的,访问速度较慢。
- 分配大小:栈的内存大小固定,通常比较小,一般在几 MB 左右;堆的内存大小不固定,可以根据需要动态分配,可以分配更大的内存空间。
- 生命周期:栈上的变量的生命周期与其所在函数的生命周期相同,函数执行结束后,它们就会被自动释放;堆上的变量则可以在程序的任意位置被使用和访问,并且只有在程序显式地释放它们时才会被释放。
- 适用场景:栈通常用于存储程序执行期间的临时数据,比如函数的局部变量、函数参数、函数调用的返回地址等。由于栈的存储方式是后进先出(LIFO),所以它非常适合用于函数调用和返回等场景,能够高效地管理函数的局部变量和临时数据。堆则通常用于存储动态分配的数据,比如数组、对象、指针等。由于堆的内存大小不固定,程序可以根据需要动态分配和释放内存空间,所以它非常适合用于动态数据结构和数据存储等场景。但是,由于堆的内存分配需要由程序员手动管理,所以在使用堆时需要注意内存泄漏等问题。
红黑树
红黑树是一种自平衡二叉查找树,它的特点是:
- 每个节点要么是红色,要么是黑色。
- 根节点是黑色的。
- 每个叶子节点(NIL节点,空节点)是黑色的。
- 如果一个节点是红色的,则它的两个子节点都是黑色的。
- 从任意一个节点到其每个叶子节点的所有路径都包含相同数目的黑色节点。
红黑树的应用场景很广泛,例如在C++ STL中的map、set、multimap、multiset等容器中都使用了红黑树来实现。红黑树的时间复杂度比较稳定,可以保证在最坏情况下的查找、插入、删除操作的时间复杂度都是O(log n)。
B+树
B+树是一种多路平衡查找树,它的特点是:
- 每个节点最多有M个子节点。
- 除根节点和叶子节点外,每个节点至少有M/2个子节点。
- 所有叶子节点都在同一层,且包含了全部关键字的信息。
- 非叶子节点只存储索引信息,不存储数据信息。
B+树的应用场景主要是在数据库系统中,用于索引和排序。B+树的特点是能够快速地进行范围查询和顺序访问,因为所有的叶子节点都在同一层,并且采用了顺序访问的方式存储数据。B+树的时间复杂度也比较稳定,可以保证在最坏情况下的查找、插入、删除操作的时间复杂度都是O(log n)。
B+树和B-树
- 节点结构不同:B+树的非叶子节点只存储键值信息,不存储数据,而叶子节点存储了所有数据,以及指向下一个叶子节点的指针。而B-树的所有节点都存储数据和键值信息。
- 叶子节点的指针不同:在B+树中,叶子节点之间形成一个有序链表,可以通过叶子节点的指针遍历整棵树。而在B-树中,每个节点都有指向相邻节点的指针,因此不需要像B+树那样维护一个链表。
- 查询性能不同:由于B+树的非叶子节点只存储键值信息,可以存储更多的节点信息,因此B+树的查询性能相对于B-树更好。而B-树的查询性能相对较差,因为每个节点都存储数据和键值信息,导致树的高度较低,但每个节点能够存储的信息也较少。
- 适用范围不同:B+树适用于大型数据集合的存储和管理,因为它可以存储更多的节点信息,提高查询性能。而B-树适用于小型数据集合的存储和管理,因为它的节点能够存储的信息较少,但树的高度较低,查询性能相对较好。
跳表
跳表全称为跳跃列表,它允许快速查询,插入和删除一个有序连续元素的数据链表。跳跃列表的平均查找和插入时间复杂度都是O(logn)。快速查询是通过维护一个多层次的链表,且每一层链表中的元素是前一层链表元素的子集(见右边的示意图)。一开始时,算法在最稀疏的层次进行搜索,直至需要查找的元素在该层两个相邻的元素中间。这时,算法将跳转到下一个层次,重复刚才的搜索,直到找到需要查找的元素为止。
Hash冲突
拉链法:每个哈希桶维护一个链表,发生冲突是添加到链表当中
开放寻执法:线性侦测、二次侦测、双重散列
三、操作系统
进程和线程
- 进程(Process): 进程是操作系统分配资源和执行代码的基本单位。每个进程都有自己的独立内存空间、代码和数据。不同进程之间不能直接共享数据,通信需要使用进程间通信(IPC)机制。由于进程之间的资源相互隔离,进程间的切换开销较大。每个进程都有自己的执行状态,如运行、就绪、阻塞等。
- 线程(Thread):线程是进程内的执行单元,一个进程可以包含多个线程。线程共享进程的代码和数据,但拥有独立的栈空间。因为线程共享内存空间,它们之间的通信和数据共享相对容易。线程之间的切换开销较小,但由于共享内存,需要注意线程安全问题。
- 协程(Coroutine): 协程是一种轻量级的线程,也被称为用户态线程。与操作系统线程不同,协程的调度和切换是由程序员自己控制的,而不是由操作系统。协程可以在同一个线程中切换执行,因此不需要像线程那样频繁的上下文切换。协程通常用于处理高并发、异步任务和IO密集型操作,因为它们可以更高效地处理大量任务的切换和调度。
地址空间
- 代码段:存储程序的代码,一般只读。
- 数据段:存储程序的数据,可读写。
- 栈:存储程序的函数调用栈,存储函数调用过程中的局部变量等数据。
- 堆:动态内存分配区域,用于动态分配内存。
进程和线程
线程状态:就绪、运行、阻塞、等待、终止
悲观锁、乐观锁
乐观锁:是一种不加锁的并发控制策略,在更新数据时,先判断数据是否被修改,如果没有被修改,则更新,否则不更新。乐观锁的思想是相信数据一般不会被其他事务修改,所以不加锁,从而提高效率。
悲观锁:是一种加锁的并发控制策略,在读取数据前,先加锁,在更新数据时也需要加锁,更新完数据后再释放锁。悲观锁的思想是相信数据一定会被其他事务修改,所以对数据加锁,从而保证数据的完整性。
调度算法:先来先服务、最短作业优先、最短剩余时间优先、轮询算法(RR)
页面置换算法:LRU、FIFO、NRU
如何预防死锁
死锁:在多线程环境下,多个线程竞争有限的资源造成的僵局
ex:A占有资源1,同时申请资源2;而B占有资源2,同时申请资源1;
1、互斥条件
2、请求和保持条件:阻塞时释放已经获得的资源
3、不剥夺条件:不能获得全部资源则等待
4、环路等待条件:资源编号,进程获得编号小的资源才能获取到大的
线程安全
线程安全指的是多线程环境下,对共享资源的访问是安全的,不会出现数据不一致、数据丢失等问题。在多线程环境中,由于多个线程共同操作一个资源,可能会出现多个线程同时对一个资源进行读写的情况,这就会导致线程安全问题。常见的线程安全问题包括数据竞争、死锁、饥饿等。
为了确保线程安全,开发人员通常采用以下几种方式:
- 加锁:使用同步机制来控制对共享资源的访问,保证同一时间只有一个线程可以访问共享资源。
- 原子操作:原子操作指的是不能被中断的操作,保证其执行的完整性。
- 使用线程安全的数据结构:使用线程安全的集合类,例如Vector、ConcurrentHashMap等。
- 避免共享资源:尽量避免多个线程共同操作同一个资源,避免线程安全问题的出现。
线程同步的方法
- 互斥锁:互斥锁是一种最常用的线程同步方式,它可以保证在同一时刻只有一个线程可以访问共享资源。当一个线程需要访问共享资源时,它会尝试获取互斥锁,如果锁已经被其他线程占用,则该线程会被阻塞,直到锁被释放。
- 条件变量:条件变量是一种线程同步机制,它可以让一个线程等待另一个线程的通知。当一个线程需要等待某个条件满足时,它会通过条件变量通知其他线程等待,然后自己进入等待状态。当条件满足时,另一个线程会通过条件变量通知等待线程,使其重新开始执行。
- 信号量:信号量是一种计数器,用于控制多个线程对共享资源的访问。当一个线程需要访问共享资源时,它会尝试获取信号量,如果信号量的值为0,则该线程会被阻塞,直到另一个线程释放信号量。
- 屏障:屏障是一种同步机制,它可以让多个线程在某个点上等待,直到所有线程都到达该点后再继续执行。屏障可以用于处理多个线程之间的依赖关系,例如计算任务中的数据依赖关系。
- 原子操作:原子操作是一种特殊的操作,它可以保证在同一时刻只有一个线程可以访问共享资源。原子操作可以用于处理一些简单的数据结构,例如计数器和标志位等。
以上是几种常用的线
四、数据库
ACID
原子性(Atomicity):事务是数据库的逻辑工作单位, 事务中包括的诸操作要么都做,要么都不做(数据库日志和锁)
一致性(Consisency): 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态
隔离性(Isolation):一个事务的执行不能被其他事务干扰(MVCC版本控制)
持久性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该 是永久性的。
事物隔离级别
InnoDB默认隔离级别:可重复读
- 读未提交(Read Uncommitted):在该隔离级别下,一个事务可以读取其他事务未提交的数据,可能导致脏读、不可重复读和幻读的情况。
- 读已提交(Read Committed):在该隔离级别下,一个事务只能读取已经提交的数据,可以避免脏读,但仍有不可重复读和幻读的情况。
- 可重复读(Repeatable Read):在该隔离级别下,一个事务在执行过程中所读取的数据不会被其他事务修改,但可能存在幻读的情况。
- 串行化(Serializable):在该隔离级别下,每个事务都是独占的,不会有其他事务干扰,可以避免脏读、不可重复读和幻读的情况,但效率较低。
- 脏读:是指一个事务读取到了另一个事务未提交的修改数据,这种情况下,如果另一个事务回滚了,那么当前事务读到的数据就是不正确的。不可重复度:是指一个事务读取同一数据多次,但是每次读取的结果不同。这是由于在读取之间,另一个事务修改了这个数据,导致读取的结果不同。幻读:是指一个事务读取到了不存在的数据,或者读取到了已经删除的数据,因为另一个事务在读取期间插入了数据或者删除了数据。这种情况对于数据的完整性和一致性造成了严重影响。
数据库引擎
innoDB(支持事物)、MyISAM(锁、索引、备份和迁移)、Memory(内存引擎)
数据库日志
redolog:重做、undolog:回滚、binlog:二进制
MySQL索引
- PRIMARY KEY 索引:是唯一索引,可以用来标识表中的每一行数据。
- UNIQUE 索引:是唯一索引,但不同于 PRIMARY KEY 索引,可以有空值。
- INDEX 索引:是普通索引,可以允许多个相同的值。
- FULLTEXT 索引:是全文索引,用于搜索关键字和短语。
- SPATIAL 索引:是空间索引,用于处理空间数据。
B+索引和Hash索引:B+ 索引的优点在于,它提供了快速查询的能力,同时还支持区间查询和排序。
数据库调优
创建索引、避免在索引上使用计算、调整where连接顺序(过滤掉最大数量记录)、使用where调换having、使用表的别名、避免使用游标、使用varchar替换char、用具体的字段代替*、update尽量不要更改全部、使用select into替代insert
慢查询优化:
- 定期清理无用索引:无用索引的存在会影响查询性能,因此需要定期清理无用索引。可以通过查询information_schema库中的表统计信息,找出未使用的索引并进行清理。
- 优化查询语句:优化查询语句可以改进查询性能。一般可以从以下几个方面入手:优化SQL语句结构、增加索引、避免使用复杂查询、减少重复查询等。
聚簇索引和非聚簇索引
- 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据
- 非聚簇索引:将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因
B+树索引
相邻叶子节点是通过指针连起来的,并且是关键字大小排序的。
数据库的锁机制
- 共享锁:允许多个事务同时对同一数据进行读取操作,但不允许写操作,保证数据的一致性。在事务读取数据时,会先申请共享锁,如果该数据未被排他锁占用,则可获取共享锁并进行读取,如果该数据被排他锁占用,则需要等待排他锁的释放才能获取共享锁。
- 排他锁:一次只允许一个事务对数据进行修改或删除操作,保证数据的完整性。在事务修改或删除数据时,会先申请排他锁,如果该数据未被其他锁占用,则可获取排他锁并进行修改或删除,如果该数据被其他锁占用,则需要等待其他锁的释放才能获取排他锁。
- 记录锁(Record Lock):仅锁定一行记录(如固定)间隙锁(Gap Lock):锁定一个范围,但不包含记录本身临键锁:锁定一个范围,并且锁定记录本身
主要有以下类型:
- 行级锁:锁定数据行,只对单行数据进行加锁,其他行数据不受影响,适用于高并发场景,但可能会增加锁冲突的概率和锁开销。
- 表级锁:锁定整张表,适用于并发量较小的场景,但可能会导致锁等待时间过长、锁冲突较多等问题。
- 页级锁:锁定数据页,每个数据页可以包含多行数据,对一页数据进行加锁,适用于中等并发量的场景,可以减少锁开销和锁冲突。
- 数据库级锁:锁定整个数据库,对整个数据库进行加锁,适用于并发量很小的场景,但可能会导致大量锁等待和锁冲突。
索引的优缺点
索引的优点:① 建立索引的列可以保证行的唯一性,生成唯一的rowId
② 建立索引可以有效缩短数据的检索时间
③ 建立索引可以加快表与表之间的连接
④ 为用来排序或者是分组的字段添加索引可以加快分组和排序顺序
索引的缺点:① 创建索引和维护索引需要时间成本,这个成本随着数据量的增加而加大
② 创建索引和维护索引需要空间成本,每一条索引都要占据数据库的物理存储空间,数据量越大,占用空间也越大(数据表占据的是数据库的数据空间)
③ 会降低表的增删改的效率,因为每次增删改索引需要进行动态维护,导致时间变长
缓存问题
缓存穿透:数据本来就不存在,但是疯狂请求;
缓存雪崩:大量key值在同一个时间段过期;
缓存击穿:大量查询集中于一个或者几个key,突然这个key过期了;
CAS实现乐观锁
CAS 算法是一种原子操作,可以在不使用锁的情况下更新共享变量。它通过比较内存中的值与预期值,如果相等则更新,否则不更新。CAS 的操作过程可以分为三个步骤:
- 读取共享变量的当前值;
- 比较共享变量的当前值与预期值;
- 如果相等,则更新共享变量的值,否则不更新。
在 MySQL 中实现乐观锁通常可以通过以下步骤:
- 在表中添加一个版本号(version)字段,用于记录每次修改的版本号;
- 在更新数据时,通过查询当前版本号是否与预期版本号相等来判断是否有其他并发事务修改了数据;
- 如果版本号相等,则执行更新操作并将版本号加 1,否则返回更新失败。
MVCC实现事物隔离
在MVCC中,每个数据行都有一个版本号或时间戳。当一个事务开始时,它会读取该时刻的数据库状态,并在执行期间只看到在该时刻之前提交的版本。如果其他事务在这个事务执行期间修改了同一行数据,那么这个事务会看到该行的旧版本,而不会看到其他事务修改后的新版本。
在实现MVCC时,需要考虑以下几个方面:
- 版本的创建和维护:每个数据行需要创建多个版本,并在事务提交时删除旧版本。同时,需要维护每个版本的时间戳或版本号,以便事务可以读取正确的版本。
- 事务的启动和提交:在事务启动时,需要记录该事务的开始时间戳或版本号。在事务提交时,需要删除该事务创建的所有版本,并更新其他事务可以看到的版本号。
- 并发控制:为了保证事务的隔离性,需要对并发访问进行控制。通常使用锁或CAS(比较-交换)操作来控制并发访问。
MySQL的QPS从1-10000变化:
- 当QPS从1到10时,MySQL的性能变化不太明显。这是因为MySQL的默认配置可以轻松处理这个级别的负载。
- 当QPS从10到100时,MySQL的性能开始有所下降。这是因为随着查询数量的增加,MySQL需要处理更多的连接和查询请求,可能会出现性能瓶颈。
- 当QPS从100到1000时,MySQL的性能下降更为明显。这是因为MySQL需要处理更多的连接和查询请求,可能会出现锁竞争、磁盘I/O瓶颈等问题,需要对MySQL的配置和硬件进行优化。
- 当QPS从1000到10000时,MySQL的性能可能会达到极限。这是因为MySQL需要处理大量的连接和查询请求,可能会出现CPU、内存、磁盘等多个方面的瓶颈,需要对MySQL的配置和硬件进行深度优化。
五、Linux基础
Linux命令
- ls:列出目录中的文件和子目录。
- cd:切换当前目录。
- pwd:显示当前目录的路径。
- mkdir:创建新目录。
- rmdir:删除空目录。
- rm:删除文件或目录。
- cp:复制文件或目录。
- mv:移动或重命名文件或目录。
- cat:查看文件内容。
- grep:在文件中查找匹配的字符串。
- top:实时显示系统的进程状态。
- ps:列出当前系统中的进程信息。
- kill:终止指定的进程。
- tar:打包或解压文件或目录。
- chmod:修改文件或目录的权限。
- chown:修改文件或目录的所有者。
- ssh:远程登录到另一台计算机。
- scp:安全地复制文件或目录到远程计算机。
- ping:测试网络连接。
- ifconfig:显示网络接口信息
- netstat:查看端口信息
- df:磁盘使用情况
- tail:查看日志信息
Linux调优
- 内存调优:可以通过修改内核参数、调整虚拟内存、使用swap分区等方法来优化系统的内存使用。例如,可以通过修改swappiness参数来控制系统在何时使用swap分区。
- 磁盘调优:可以通过使用SSD硬盘、调整磁盘调度程序、使用RAID等方法来优化系统的磁盘性能。
- CPU调优:可以通过使用多核CPU、调整CPU频率、调整系统调度程序等方法来优化系统的CPU性能。
- 网络调优:可以通过调整TCP缓冲区、使用高效的网络协议、优化网络拓扑结构等方法来优化系统的网络性能。
- 应用程序调优:可以通过优化应用程序的代码、使用高效的算法、优化数据库等方法来提高应用程序的性能。
Epoll
Epoll(事件轮询)是一种在Linux操作系统中用于高效处理大量文件描述符(sockets、文件、设备等)的I/O事件的机制。它是一种异步事件驱动的I/O模型,用于监视多个文件描述符上的事件,并在这些事件发生时通知应用程序。Epoll的设计目标是提供高性能的事件通知机制,以减少I/O操作的开销,适用于高并发的网络编程。
Epoll的主要优点包括:
- 高效性能: Epoll采用了基于事件驱动的模式,使得应用程序不需要通过轮询来等待I/O事件的发生,从而减少了系统调用的次数,提高了系统的性能。
- 支持大量文件描述符: Epoll使用红黑树(Red-Black Tree)和链表数据结构来存储文件描述符,使其能够有效地管理大量的I/O事件。
- 边沿触发和水平触发模式: Epoll支持两种触发模式。在边沿触发模式下,只有当状态发生变化时(如socket从不可读变为可读),Epoll才会通知应用程序。而在水平触发模式下,只要文件描述符处于可读或可写状态,Epoll就会通知应用程序。
- 内存映射: Epoll允许应用程序将内核空间的一部分内存映射到自己的地址空间,从而可以直接操作这些内存,提高了I/O操作的效率。
六、设计模式
六大原则
- 单一职责原则(Single Responsibility Principle,SRP): 一个类应该仅有一个引起它变化的原因,即一个类只负责一项职责。这样可以使类的设计更加简洁,易于理解和维护。
- 开放封闭原则(Open-Closed Principle,OCP): 软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。即在不修改现有代码的情况下,通过扩展来实现新的功能或变化。
- 里氏替换原则(Liskov Substitution Principle,LSP): 子类对象应该能够替换父类对象,并且程序的行为不会受到影响。子类应该保持父类的行为规范,而不是改变原有的行为。
- 依赖倒置原则(Dependency Inversion Principle,DIP): 高层模块不应该依赖于低层模块,它们应该共同依赖于抽象接口。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。
- 接口隔离原则(Interface Segregation Principle,ISP): 客户端不应该依赖于它不需要的接口。一个类不应该强迫其子类实现不需要的方法。
- 迪米特法则(Law of Demeter,LoD): 一个对象应该对其他对象保持最少的了解,只与直接朋友进行交流。直接朋友指的是该对象本身、该对象所创建的对象、该对象所依赖的对象以及位于成员变量、方法参数等地方的对象。