过完年之后打算寻找新的工作机会,发现之前自己对于很多基础的面试理解和学习不够深刻,为了鼓励自己持续前进所以最近开始在论坛和搜索引擎上开始学习和总结相关知识,其中有一些题目时论坛里面一些前辈分享过的题目或者答案,还有一部分时自己最近面试遇到的问题,基于自己的理解和前辈们的分享归档了一部分,所以分享出来,希望对其他的小伙伴们也有帮助,同时也希望能收到大佬们对于理解有误的地方的指导,最近一段时间会持续更新
一、php 数组底层实现原理
1、底层实现是通过散列表(hash table) 双向链表(解决hash冲突)
-
hashtable:将不同的关键字(key)通过映射函数计算得到散列值(Bucket->h) 从而直接索引到对应的Bucket
-
hash表保存当前循环的指针,所以foreach 比for更快
-
Bucket:保存数组元素的key和value,以及散列值h
2、如何保证有序性
-
1. 散列函数和元素数组(Bucket)中间添加一层大小和存储元素数组相同的映射表。
-
2. 用于存储元素在实际存储数组中的下标
-
3. 元素按照映射表的先后顺序插入实际存储数组中
-
4. 映射表只是原理上的思路,实际上并不会有实际的映射表,而是初始化的时候分配Bucket内存的同时,还会分配相同数量的 uint32_t 大小的空间,然后将 arData 偏移到存储元素数组的位置。
3、解决hash重复(php使用的链表法):
-
1. 链表法:不同关键字指向同一个单元时,使用链表保存关键字(遍历链表匹配key)
-
2. 开放寻址法:当关键字指向已经存在数据的单元的时候,继续寻找其他单元,直到找到可用单元(占用其他单元位置,更容易出现hash冲突,性能下降)
4、基础知识
-
链表:队列、栈、双向链表、
-
链表 :元素 指向下一元素的指针
-
双向链表:指向上一元素的指针 元素 指向下一元素的指针
二、冒泡排序的时间复杂度和空间复杂度
1、代码实现
$arr = [2, 4, 1, 5, 3, 6];
for ($i = 0; $i < (count($arr)); $i ) {
for ($j = $i 1; $j < (count($arr)); $j ) {
if ($arr[$i] <= $arr[$j]) {
$temp = $arr[$i];
$arr[$i] = $arr[$j];
$arr[$j] = $temp;
}
}
}
result : [6,5,4,3,2,1]
2、计算原理
-
第一轮:将数组的第一个元素和其他所有的元素进行比较,哪个元素更大,就换顺序,从而冒泡出第一大(最大)的元素
-
第一轮:将数组的第二个元素和其他所有的元素进行比较(第一大已经筛选出来不用继续比较了),哪个元素更大,就换顺序,从而冒泡出第二大的元素
-
... 依次类推,冒泡从大到小排序的数组
平均时间复杂度:O(n^2)
;
最优时间复杂度:O(n)
,需要加判断,第一次循环如果一次都没有交换就直接跳出循环
空间复杂度:O(1)
,交换元素的时候的临时变量占用的空间
最优空间复杂度:O(1)
,排好序,不需要交换位置
3、时间复杂度和空间复杂度
时间复杂度:全程为渐进时间复杂度,估算对处理器的使用效率(描述算法的效率趋势,并不是指算法具体使用的时间,因为不同机器的性能不一致,只是一种效率计算的通用方法)
表示方法:大O符号表示法
复杂度量级:
-
常数阶O(1)
-
线性阶O(n)
-
平方阶O(n²)
-
立方阶O(n³)
-
K次方阶O(n^k)
-
指数阶(2^n)
-
对数阶O(logN)
-
线性对数阶O(nlogN)
时间复制类型:
-
最好时间复杂度
-
最坏时间复杂度
-
平均时间复杂度
-
均摊时间复杂度
空间复杂度:全程渐进空间复杂度,估算对计算机内存的使用程度(描述算法占用的存储空间的趋势,不是实际占用空间,同上)
参考:
三、网络七层协议及 TCP 和 TCP
应用层、表示层、会话层、传输层、网络层、(数据)链路层、物理层
记忆套路:
首字:应表会传(物链网)
第一个字:应用层(出现次数多,易忆)
前四个正向:应表 - 会传
后三个反向:物联网谐音比网链物更好记
四、TCP 和 UDP 的特点和区别
1、都是属于传输层协议
2、TCP
-
面向连接,所以只能一对一
-
面向字节流传输
-
数据可靠,不丢失
-
全双工通信
3、UDP(根据TCP特点反记)
-
无连接,支持一对一,一对多,多对多
-
面向保温传输
-
首部开销小,数据不一定可靠但是速度更快
五、TCP 的三次握手和四次挥手
1、三次握手:
-
1)第一次:客户端发送SYN = 1,seq = client_isn
作用:
客户端:无
服务端:确认自己的接收功能和客户端的发送功能
-
2)第二次:服务端发送SYN = 1,seq = server_isn,ACK =client_isn 1
作用:
客户端:确认自己发送和接收都正常,确认服务端的接收和发送正常
服务端:确认自己的接收正常,确认服务端的发送正常(这时候服务端还不能确认客户端接收是否正常)
-
3)第三次:客户端发送SYN = 0, ACK = server_isn 1,seq =client_isn 1
作用:双方确认互相的接收和发送正常,建立连接
2、四次挥手
-
1)第一次:客户端发送FIN
作用:告诉服务端我没有数据发送了(但是还能接收数据)
-
2)第二次:服务端发送ACK
作用:告诉客户端收到请求了,可能服务端可能还有数据需要发送,所以客户端收到进入FIN_WAIT状态,等服务端数据传输完之后发送FIN
-
3)第三次:服务端发送FIN
作用:服务端告诉客户端我发送完了,可以关闭连接了。
-
4)第四次:客户端发送ACK
作用:客户端收到FIN之后,担心服务端不知道要关闭,所以发送一个ACK,进入TIME_WAIT,等待2MSL之后如果没有收到回复,证明服务端已经关闭了,这时候客户端也关闭连接。
注意:
-
当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据
-
最后需要等待2MSL是因为网络是不可靠的,如果服务端没有收到最后一次ACK,服务端会重新放FIN包然后等客户端再次发送ACK包然后关闭(所以客户端最后发送ACK之后不能立即关闭连接)
六、HTTP 状态码
1、状态码分类
-
- 1xx:信息,服务器收到请求,需要请求者继续操作
-
- 2xx:成功
-
- 3xx:重定向
-
- 4xx:客户端错误
-
- 5xx:服务端错误
2、常用状态码
-
200:请求成功
-
301:永久重定向
-
302:临时移动
-
400 bad request:客户端请求语法错误
-
401 unauthorized:客户端没有权限
-
403 forbidden:服务器拒绝客户端请求
-
404 not found:客户端请求资源不存在
-
500 Internal Server Eerro:服务器内部错误
-
502 bad gateway:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
-
503 Service Unavailable 超载或系统维护
-
504 Gateway timeout:网关超时
3、502 的原因及解决方法
原因:nginx将请求提交给网关(php-fpm)处理异常导致
1)fastcgi 缓冲区设置过小
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
2)php-cgi的进程数设置过少
查看FastCgi进程数:netstat -anpo | grep "php-cgi"| wc -l
调整参数最大子进程数:max_children
一般按照单个进程20M计算需要需要设置的子进程数
3)max_requests(内存溢出或频繁重启)
参数指明每个children最多能处理的请求数量,到达最大值之后会重启children。
设置过小可能导致频繁重启children:
php将请求轮询给每个children,在大流量的场景下,每一个children 到达最大值的时间差不多,如果设置过小可能多个children 在同一时间关闭,nginx无法将请求转发给php-fpm,cpu降低,负载变高。
设置过大可