后端工程师史上最强面试题集锦

通识逻辑
语言
数据结构
计算机网络
MySQL数据库
算法
Nginx
[Linux](# Linux)
其他
前端

通识逻辑

1、给你四个坐标点,判断它们能不能组成一个矩形,如判断([0,0],[0,1],[1,1],[1,0])能组成一个矩形

(y1-y2/x1-x2) * (y2-y3/x2-x3)=-1 //通过斜率

2、小明和小张刚与小红成为朋友,他们想知道小红的生日日期,于是小红给了他们10个可能的日期:5月15日、5月16日、5月19日、6月17日、6月18日、7月14日、7月16日、8月14日、8月15日、8月17日。  小红把她的生日月份告诉了小明,把日子告诉小张,小明听过后表示:‘我不知道小红的生日,但我肯定小张也不知道。’小张于是说:‘最初我也不知道小红的生日,但我现在知道了。’然后小明道:‘那我也知道了。’请问小红的生日是何时

7月16

语言

PHP相关,纯记忆,部分题目比较奇葩

1、使用下面哪个语句包含文件时可能会包含一个致命错误

requrie

2、进一取取整

ceil

3、将数组开头的单元移出的函数

array_shift

4、哪个函数可从结果集中取出一行作为关联数组,或数字数组,或二者兼有

mysql_fetch_array

5、哪个函数返回结果集中行的数目,且仅对 SELECT 语句有效

msyql_num_rows

6、PHP5 中,默认的权限控制是

public

7、哪个是对类本身的一个引用,常用来指向类中的静态成员

self::

8、返回路径中的文件名部分的函数是

basename

可以替换成其他语言的基础考核,但这种考核我个人觉得没意义,纯记忆,略感奇葩。

9、PHP的垃圾回收机制

10、PHP的APC

11、isset(null) isset(false) isset(0) isset([]) empty(0) empty(null) empty(false) empty([])输出

bool(false)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)
bool(true)

12、echo、print、print_r的区别

echo 不是函数,没有返回值,仅用于打印信息,如果只是输出echo会更快
print 有返回值,是函数,还能格式化输出
print_r 则是打印复合类型如数组 对象

13、PHP的数组和C语言的数组结构上有何区别?

C语言数组的定义:一个数组类型描述了连续分配的非空的具有特定元素对象类型的对象集合。这些元素对象的类型称为元素类型。数组类型由元素类型与元素数目确定。
PHP数组的数据结构是采用HashTable来实现的,而它的hash冲突的解决方式使用的是拉链法,PHP7的HashTable本身的结构与5又不同

14、PHP的的这种弱类型变量是怎么实现的?

zval联合体

15、PHP中发起http请求有哪几种方式?它们有何区别?

curl
stream流的方式
socket方式

16、有两个文件文件,大小都超过了1G,一行一条数据,每行数据不超过500字节,两文件中有一部分内容是完全相同的,请写代码找到相同的行,并写到新文件中。PHP最大允许内内为255M

好像又是一个大文件处理,面试官出题的意图并不希望你两层for循环进行遍历,这种答案肯定是不会要的,看64题的连接,专门讲处理大数据的各种方式。
那借用文章的方案,这道题目我的解法思路是:
    顺序读取两个文件的的全部记录,将每条记录经过hash->转换为10进制->%n后存到10个文件中,这样一共2G的数据分成10份,每份就是204.8M,低于内存限制,
    我可以一次读取一个文件,并用hash桶的方式得到单个文件中的内容是否有重复,因为每条记录都经过hash处理的,所以相同的记录肯定会在同一个文件中。
    
    下面是伪代码:
    
    /**
     * 将两个文件中的每条记录通过hash求余后分别存入10个文件中
     * 如果某个文件太大,超过限制内存大小,则可以对其再次hash求余
     */
    $handler = fopen('file_a_AND_file_b', 'r');
    
    while ($line = fgetc($handler)) {
        $save_to_file_name = crc32(hash('md5', $line)) % 10;
        file_put_contents($save_to_file_name, $line);     
    }
    
    /**
     *
     */
    $files = [ '10个文件的路径' ];
    foreach ($files as $file) {
    
        $handler = fopen($file, 'r');
        $tmp_arr = [];
        while($line = fgetc($handler)) {
            if(isset($tmp_arr[$line])) {
                file_put_contents('common_content.txt', $line);
            } else {
                $tmp_arr[$line] = true;
            }
        }
    
    }

17、请写出自少两个支持回调处理的PHP函数,并自己实现一个支持回调的PHP函数

array_reduce();
array_map();
array_filter();

function callBack($parameter, $fn) {
    return $fn($parameter);
}

var_dump(callBack(5, function ($n){
    return $n * $n;
}));

18、请写出自少两个获取指定文件夹下所有文件的方法(代码或思路)。

//递归
function readDirDeep($path,$deep = 0)
{
    $handle = opendir($path);
    while(false !== ($filename = readdir($handle))){
        if($filename == '.' || $filename == '..') continue;
        echo str_repeat('&nbsp;',$deep*5) . $filename.'<br>';
            //str_repeat(str,n) 重复一个str字符串n次
        if(is_dir($path.'/'.$filename)){
            readDirDeep($path.'/'.$filename,$deep+1);
            }
        }
        //闭关
        closedir($handle);
}

//队列
队列的方式就是遇到目录就放入队列,非目录打印就好
function readDirQueue($dir)
{
    $dirs = [$dir];

    while ($path = array_shift($dirs)) {
        if (is_dir($path) && $handle = opendir($path)) {
            while (false !== ($filename = readdir($handle))) {
                if ($filename == '.' || $filename == '..') continue;
                $real_path = $path . DIRECTORY_SEPARATOR . $filename;

                if(is_dir($real_path)) {
                    $dirs[] = $real_path;
                }else {
                    echo $real_path . '<br/>';
                }
            }
            //闭关
            closedir($handle);
        }
    }

}

19、请写出自少三种截取文件名后缀的方法或函数(PHP原生函数和自己实现函数均可)

$file = 'x.y.z.png';
$ext = substr(strrchr($file, '.'), 1);
$ext = pathinfo($file)['extension'];
$ext = array_pop(explode('.', $file));

20、PHP如何实现不用自带的cookie函数为客户端下发cookie。对于分布式系统,如何来保存session值。

1、可以使用页面直接输出cookie,客户端js写入,如:
<?php 
    $cookie = 'abcd...';
    "<script> setcookie($cookie); </script>"
?>
2、通过JSON数据传递,JS前端保存,如:
<?php
    json_encode(['cookie'=>'abcd...']);
?>
<html><body><script>
    ajax{
        success: function(data){
            var cookie = data.cookie;
        }
    }
</script></body></html>

2、分布式系统session保存:mysql、redis、memcache、文件,主要方式是就是所有app应用都操作同一个位置的session,存哪都行,具体还要看业务量,比如业务量大,可能会采用缓存集群,业务量小可能单台机器的文件就能存了
具体的实现方案可以google/baidu搜索,有很多案例

20、$a=[0,1,2,3]; $b=[1,2,3,4,5]; $a+=$b; var_dump($a)等于多少?

考的是数组+和array_merge的区别
当下标为数值时,array_merge()不会覆盖掉原来的值,但array+array合并数组则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉(不是覆盖). 
当下标为字符时,array+array仍然把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉,但array_merge()此时会覆盖掉前面相同键名的值.

21、$a=[1,2,3]; foreach($a as &$v){} foreach($a as $v){} var_dump($a)等于多少

前者1,2,3
后者1,2,2

22、10g文件,用php查看它的行数

来自网络: 它的方式是一次读取一部分数据,计算这部分数据中有多少个换行符,不断循环,效率会比顺序读取内容高
/*
 * 高效率计算文件行数
 * @author axiang
*/
function count_line($file)
{
    $fp = fopen($file, "r");
    $i  = 0;
    while (!feof($fp)) {
        //每次读取2M
        if ($data = fread($fp, 1024 * 1024 * 2)) {
            //计算读取到的行数
            $num = substr_count($data, "\n");
            $i += $num;
        }
    }
    fclose($fp);
    return $i;
}

23、php进程模型,php是怎么支持多个并发的

24、rand与mt_rand的区别

1.int rand(void) / int mt_rand(void)
2.int rand(int $min, int $max) / int mt_rand($min, $max)
 
对第一种形式:
     rand()产生的随机数为0到getrandmax()之间
     mt_rand()产生的随机数为0到mt_getrandmax()之间
 
对第二种形式:
     rand()产生从$min到$max之间的随机数
     mt_rand()产生从$min到$max之间的随机数    
 
对比:
     mt_rand()是更好地随机数生成器,因为它跟rand()相比播下了一个更好地随机数种子;而且性能上比rand()快4倍,mt_getrandmax()所表示的数值范围也更大

25、Trait优先级

26、=的区别,写出以下输出:"aa"==1,"bb"0,1"1"

27、'$var'和"$var"的区别

28、self和static的区别

29、PHP的协程以及用途

30、描述autoload的机制

31、PHP反射类

32、使用PHP过框架的优缺点

https://blog.csdn.net/Just_shunjian/article/details/78469929

33、foreach使用引用需要注意的问题

https://segmentfault.com/a/1190000008514110

34、手写遍历目录程序

glob

35、php深复制,浅复制

https://www.cnblogs.com/taijun/p/4208008.html

36、PHP底层:写时复制,浅复制/深复制

http://www.php-internals.com/book/?p=chapt06/06-06-copy-on-write

数据结构

1、哈希表是什么?hash表中的hash冲突后,数据怎么存?

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
hash冲突后的解决方式:
    开放寻址法
    再散列法
    链地址法(拉链法)
    建立一个公共溢出区

2、B+Tree是怎么进行搜索

https://blog.csdn.net/hguisu/article/details/7786014

3、数组和hash表的区别是什么?

数组是编程语言提供的一种数据类型,即用一组连续的内存空间来存放数据,可以通过一个首地址,和一个数组下标,直接访问这组内存空间中的任意位置。
哈希表是数据结构这门学科中的概念,是以数组为存储方式,实现的一种可以快速查找数据的数据结构。它是将数据的值通过一个映射函数,求出一个结果,然后把数据放在这个结果对应的数组下标的位置。

4、什么是B+数,请画b+树的结构

计算机网络

1、HTT,1.0中,状态码403的 含义是

Forbidden

2、OSI七层网络

物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

TCP/IP四层模型

网络接口层、网际互连层、传输层、应用层

3、http的状态码阐述概念

200 请求成功。一般用于GET与POST请求
201 已创建。成功请求并创建了新的资源
301 已接受。已经接受请求,但未处理完成
400 客户端请求的语法错误服务器无法理解
403 服务器理解客户端的请求,但是拒绝执行此请求
404 服务器无法根据客户端的请求找到资源(网页
500 服务器内部错误,无法完成请求
502 充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
503 由于超载或系统维护,服务器暂时的无法处理客户端的请求

4、http与https的主要区别

http工作在应用层,https是建立在SSL信道上的http,而SSL属于模型中的传输层,所以是传输层的协议;如果是基于TCP/IP模型的话:HTTP和SSL都是工作在应用层,那么HTTP和HTTPS同属应用层协议

http是明文传输
https是加密传输

超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息。HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此HTTP协议不适合传输一些敏感信息,比如信用卡号、密码等。
为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS。为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
HTTPS和HTTP的区别主要为以下四点:
一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

5、对称加密和非对称加密的区别

对称加密:指的就是加、解密使用的同是一串密钥,所以被称做对称加密。对称加密只有一个密钥作为私钥。 
常见的对称加密算法:DES,AES等。

非对称加密:指的是加、解密使用不同的密钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。反之,私钥加密的信息,只有公钥才能解密。 

6、http协议的header中哪些key及含义

General
	Request URL: http://localhost
	Request Method: GET
	Status Code: 200 OK
	Remote Address: 127.0.0.1:80
	Referre Policy: no-referrer-when-downgrade
Response Headers
	Connection: keep-alive
	Content-Encoding: gzip
	Content-Type: text/html; charset=UTF-8
	Date: Mon, 07 May 2018 10:05:43 GMT
	Server: nginx/1.10.1
 	Transfer-Encoding: chunked
  	X-Powered-By: PHP/7.0.8
Request Headers:
	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
	Accept-Encoding: gzip, deflate, br
	Accept-Language: zh-CN,zh;q=0,9;q=0.8
	Cache-Control: no-cache
	Connection: keep-alive
	Host: localhost
	Pragma: no-cache
	Referer: http://localhost
	Upgrade-Insecure-Requests: 1
	User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Mobile Safari/537.36

7、从用户在浏览器中输入网址并回车,到看到完整的页面,中间都经历了哪些过程

 浏览器->url->dns->ip->port->tcp->nginx->server name->php-fpm/fast cgi->php
   ^  <-  client ip:port  <- ^ <-  ^  

8、什么是CSRF攻击?XSS攻击?如
何防范?

CSRF
跨站请求攻击,简单地说,是通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作。简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
防范方式: CSRF TOKEN, 即提交表单时同时提交一段由服务端渲染表单时生成的token,通过校验token来防范csrf攻击

XSS
简单来说,XSS就是正常页面执行了用户或黑客提交的前端代码,比如你用了eval('这里执行了用户提交的代码'),
或者你的页面正常解析了用户提交的html代码,如用户提交的个人信息是:<img src="广告连接"><script>window.href="恶意网站连接"</script>,
而你不加过滤转义就入库,然后页面正常解析html代码,最终用户访问这个页面就会跳转到恶意网站 ,这就是XSS
防范方式: 过滤&&转义用户输入(如htmlentities、htmlspecialchars),永久不要信任客户端

9、在HTTP通讯过程中,是客户端还是服务端主动断开连接?

http1.0  

带content-length,body长度可知,客户端在接收body时,就可以依据这个长度来接受数据。接受完毕后,就表示这个请求完毕了。客户端主动调用close进入四次挥手。

不带content-length ,body长度不可知,客户端一直接受数据,直到服务端主动断开

 

http1.1

带content-length                       body长度可知     客户端主动断开

带Transfer-encoding:chunked       body会被分成多个块,每块的开始会标识出当前块的长度,body就不需要通过content-length来指定了。但依然可以知道body的长度 客户端主动断开

不带Transfer-encoding:chunked且不带content-length        客户端接收数据,直到服务端主动断开连接。

10、http协议具体的定义

11、哪些属性唯一确定一条TCP连接

12、断开TCP连接时,timewait状态会出现在发起分手的一端还是被分手的一端

发起分手

13、HTTP协议 跟 网络层TCP/UDP是否同一层。

不是
https://www.zhihu.com/question/38648948

14、TCP与UDP基本区别

https://www.zhihu.com/question/20583641

MySQL数据库

1、应用中我们经常会遇到在user表随机调取10条数据来展示的情况,简述你如何实现该功能。

select * from user where rand() limit 10;

2、为了管理学生的选课信息,建立了3个表:
S (SID, SName )
SID, SName 分别代表学号、学员姓名

C (CID, CName )
CID, CName 分别代表课程编号、课程名称

SC (SID, CID )
SID, CID,分别代表学号、所选的课程编号

请写出实现如下查询的SQL语句:
1)查询选修了课程的学员总人数

2)查询不选课程编号为C1的学员学号和姓名

3)查询选择课程超过5门的学员学号和姓名

select count(distinct sid) from sc
select sid,sname from s where sid in (select sid from sc where cid!=c1)
select sid,sname from s where sid in (select sid,count(sid) from sc having count(sid)>5)

3、SQL注入的原理是什么?如何防止SQL注入

1、转义4用户输入(htmlentities/htmlspecialchars),用mysql_real_escape_string方法过滤SQL语句的参数
2、预编译sql (最佳方式)

4、MySQL优化方法

硬件层面
	采用高配Sass硬盘,上磁盘阵列
架构层面
	分库、分区、分表、主从(主主)、多服务器集群、vip+keepalive等(可能会问到具体实现,所以在回答前要把这些实现细节搞得差不多懂)
应用层面(下面只要你提到,面试官都可能会问细节,比如有哪些存储引擎,各有什么区别和应用场景,innodb的主键索引和非主键索引有何区别,数据结构,叶子节点存放什么?)
	存储引擎的选择
	字段的选择
		越短越快
		定长类型快于变长类型
		整型的处理速度快于字符串类型
	索引
		MySQL支持的索引类型(讲到这肯定会问你具体定义)
		索引的使用条件
		索引的实现结构
			聚集索引,非聚集索引,B+Tree
			Hash索引
	慢查询日志
		可帮助找到问题语句
	通过explain来优化语句

5、数据库中的事务是什么?

事务的特征:ACID
原子性Atomicity 一组DML语句要么全部成功要么全部失败
一致性Consistency 事务必须由一个状态到另一个状态
隔离性Isolation 多个事务之间能够根据事务的隔离级别表现不同
持久性Durability 提交后的事务,一旦提交,它对数据库中的数据修改是永久性的

Q:当没有事务的情况会出现什么问题?
A:当在控制台,操作mysql数据库时候,如果没有事务控制,误操作就会造成数据的永久损失。
脏读:当某个客户端查询出了另外一个事务还没有提交的修改数据,即为脏读。
不可重复读:[同一查询]在[同一事务]中多次进行,由其它提交事务所做的修改或删除,每次返回不同的的结果集,此时发生非重复读。
幻读:[同一查询]在[同一事务]中多次进行,由于其它提交事务(事务可能没提交)所做的插入操作,每次返回不同的结果集,此时发生幻读。

6、聚集索引、聚族索引与非聚集索引的区别

聚集索引
	表数据按照索引的顺序来存储的,也就是说索引项的顺序与表中记录的物理顺序一致。对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。在一张表上最多只能创建一个聚集索引,因为真实数据的物理顺序只能有一种
仅仅出现在innodb引擎的主键索引上
聚簇索引
	innodb的主键索引关键字,与记录是存储在一起的
	导致结果,记录依据主键顺序排序,记录的真实位置会改变,随着主键索引关键字的改变而改变,那么innodb表上的非主键索引(二级索引)存储的是关键字与主键值的对应关系(而不是关键字与记录位置的对应关系),导致innodb的非主键索引:都是二次查找。
	1关键字确定主键值
	2主键值确定记录
	
	在数据结构层面上:
	在原来的B-Tree结构上,做了一定的改动,改动后的这个聚簇(聚集)结构称之为 B+Tree
非聚集索引: 
    表数据存储顺序与索引顺序无关。对于非聚集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,其行数量与数据表行数据量一致
    
更新表数据:
    向表中插入新数据行
       如果一张表没有聚集索引,那么它被称为“堆集”(Heap)。这样的表中的数据行没有特定的顺序,所有的新行将被添加到表的末尾位置。而建立了聚簇索引的数据表则不同:最简单的情况下,插入操作根据索引找到对应的数据页,然后通过挪动已有的记录为新数据腾出空间,最后插入数据。如果数据页已满,则需要拆分数据页,调整索引指针(且如果表还有非聚集索引,还需要更新这些索引指向新的数据页)。而类似于自增列为聚集索引的,数据库系统可能并不拆分数据页,而只是简单的新添数据页。
    从表中删除数据行
       对删除数据行来说:删除行将导致其下方的数据行向上移动以填充删除记录造成的空白。如果删除的行是该数据页中的最后一行,那么该数据页将被回收,相应的索引页中的记录将被删除。对于数据的删除操作,可能导致索引页中仅有一条记录,这时,该记录可能会被移至邻近的索引页中,原索引页将被回收,即所谓的“索引合并”。
    
聚集索引是一种稀疏索引,数据页上一级的索引页存储的是页指针,而不是行指针。而对于非聚集索引,则是密集索引,在数据页的上一级索引页它为每一个数据行存储一条索引记录

这里重点解释一下 MySQL非主键索引回表问题,二次查询造成顺序查和乱序查的问题,这时联合索引和索引最左匹配解决这两个问题

7、mysql数据库中innodb和myisam引擎的区别

InnoDB:
支持事务处理等
不加锁读取
支持外键
支持行锁
不支持FULLTEXT类型的索引
不保存表的具体行数,扫描表来计算有多少行
DELETE 表时,是一行一行的删除
InnoDB 把数据和索引存放在表空间里面
跨平台可直接拷贝使用
InnoDB中必须包含AUTO_INCREMENT类型字段的索引
表格很难被压缩

MyISAM:
不支持事务,回滚将造成不完全回滚,不具有原子性
不支持外键
不支持外键
支持全文搜索
保存表的具体行数,不带where时,直接返回保存的行数
DELETE 表时,先drop表,然后重建表
MyISAM 表被存放在三个文件 。frm 文件存放表格定义。 数据文件是MYD (MYData) 。 索引文件是MYI (MYIndex)引伸
跨平台很难直接拷贝
MyISAM中可以使AUTO_INCREMENT类型字段建立联合索引
表格可以被压缩

重点:
MYSQL5.7之后,原先INNODB不具有的功能已经全部完善,也就是MYISAM的优点INNODB全部都有,并且在即将到来的MYSQL8.0版本myisam将被废弃InnoDB: 支持事务处理等 不加锁读取 支持外键 支持行

8、如何分析一条sql语句的性能

熟悉explain分析语句后响应的各个属性

9、MYSQL主从服务器,如果主服务器是innodb引擎,从服务器是myisam引擎,在实际应用中,会遇到什么问题?

事务,索引查询

10、mysql事务隔离是怎么实现的

https://www.linuxidc.com/Linux/2018-01/150610.htm
https://liuzhengyang.github.io/2017/04/18/innodb-mvcc/

11、mysql的锁怎么实现的

之前看过一篇文章,但找不到连接了,后面找到再贴

跟存储的结构有关,会在索引上加锁(就跟文件锁一样,有个锁标志),如果没有锁引,那就会锁表
另外锁会有一个范围,间隙锁

https://www.cnblogs.com/luyucheng/p/6297752.html

12、数据库如果出现了死锁,你怎么排查,怎么判断出现了死锁?

13、主从复制,从服务器会读取到主服务器正在回滚的数据吗?主数据库写成功,从服务器因为一些原因写失败,最后会出现什么情况?主从复制如果键冲突怎么办?

14、事务有几种隔离级别?事务的隔离级别是怎么实现的?

15、mysql中的字符集,客户端与数据库不一致,怎么办? MYSQL中字符串到显示到界面,字符转换的过程是怎样的?数据库中的字符集是latin1,你现在将utf8的字符串存到latin1字符集的数据库表,你能将utf8的字符串存进去吗?假如你说能存,追问:能否恢复?假如能,那怎么恢复?

16、mysql中字段类型各占几个字节:smallint、int、bigint、datetime、varchar(8)

17、.MYSQL相关索引有多少种,分别是什么,结构是什么

https://cloud.tencent.com/developer/article/1004912

18、Mysql 的复合索引最左原则

https://cloud.tencent.com/developer/article/1004912

19、Mysql 覆盖索引的理解

https://yq.aliyun.com/articles/62419

20、Mysql 非聚集索引的查询方式

https://cloud.tencent.com/developer/article/1054706

21、mysql连接池

https://juejin.im/entry/58fb03220ce4630061233c98

22、MYSQL主从架构,加索引怎么加

https://klionsec.github.io/2017/10/27/mysql-master-slave/

23、队列高可用

https://tech.meituan.com/mq-design.html

算法

1、写一段代码判断单向链表中有没有形成环,如果形成环,请找出环的入口处,即P点

2、数组a[N],存放了1 至N-1 个数,其中某个数重复一次。写一个函数,找出被重复的数字.时间复杂度必须为o(N)函数原型空间复杂度为o(0),也就是不能再新建变量 $N = 7; $array = [1,2,3,4,5,5,6];

int do_dup(int a[],int N){  
    int temp;  
    //a[0]为监视哨  
    while (a[0]!=a[a[0]])  
    {  
        temp=a[0];  
        a[0]=a[temp];  
        a[temp]=temp;  
    }  
    return a[0];  
}  
  
void main(){  
    int a[5]={1,2,3,2,0};  
    cout<<do_dup(a,5);  
    system("pause");  
} 

3、找出一个数组里面不重复的数

hash桶

$res = [];
foreach ($data as $item) {
    if(array_key_exists($item, $res)) {
        ++$res[$item];
    } else {
        $res[$item] = 1;
    }
}

foreach ($res as $k=>$v) {
    if($v == 1) {
        echo $k;
    }
}

4、手写找到一个数组中相加为特定数值的两个元素

hash桶

5、找出出现次数超过一半的数字

hash桶

时间复杂度是多少?有的情况下,你写了个算法,然后面试官会让你把你的算法的时间复杂度表达式写出来

6、从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是连续的,JQK用11、12、13表示

function eatDuck(array $arr)
{
    $count = count($arr);
    if (count(array_unique($arr)) != $count) {
        return false;//对子
    }
    if (max($arr) - min($arr) != $count - 1) {
        return false;
    }
    return true;
}

7、遍历一个多维数组

$data = [
    1, 2, 4, 6,
    [
        2, 5, 6, 7,
        [
            9, 12, 55, 66, 77
        ]
    ],
];

function eatArr(array $arr)
{
    foreach ($arr as $item) {
        if (is_array($item)) {
            eatArr($item);
        } else {
            echo $item . ' ';
        }
    }
}

eatArr($data);

8、有这样一个字符串abcdefgkbcdefab......随机长度,写一个函数来求bcde在这个字符串中出现的次数

$str = "abceeedefdsafujdsklgjmrj89gu89eeefiodsaflkjdsafjhuigbeeejhndfiofgidsafndyeeeubhngihaf;odsa";
$tag = "eee";

function search($str, $need)
{
    $res      = [];
    $str_len  = strlen($str);
    $need_len = strlen($need);
    for ($i = 0; $i < $str_len; ++$i) {
        for ($n = 0; $n < $need_len; ++$n) {
            if (isset($str[$i + $n]) && $need[$n] != $str[$i + $n]) {
                break;
            }
            if ($n == $need_len - 1) {
                $res[] = $i;
            }
        }
    }
    return $res;
}

var_dump(search($str, $tag), count(search($str, $tag)));

这里对比了三种方法,还是遍历最快:https://blog.csdn.net/yxtyxt3311/article/details/599492

9、有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16个字节,内存限制大小是1M。返回频数最高的100个词

讲得很好:https://blog.csdn.net/zzran/article/details/8443655

10、十道海量数据处理面试题与十个方法大总结(我加的)

https://blog.csdn.net/v_JULY_v/article/details/6279498

11、10瓶水,其中一瓶有毒,小白鼠喝完有毒的水之后,会在24小时后死亡,问:最少用几只小白鼠可以在24小时后找到具体是哪一瓶水有毒。

用二进制表示10,最多需要几位。2^A>=10,A=4

12、写一个一个程序来查找最长子串

13、写一段代码,找到所有子集合,如[a,b,c]的子集合有{},{a},{b},{c},{ab},{ac},{abc}

15、['a'=>200,'b'=>100,'c'=>100],写一个自定义排序函数,按值降序,如果值一样,按键排序

16、一个排序好的数组,将它从中间任意一个位置切分成两个数组,然后交换它们的位置并合并,合并后新数组元素如:20,21,22,25,30,1,2,3,5,6,7,8,15,18,19,写一个查询函数来查找某个值是否存在。

2分查找的优化版本
先找到中间数数字将数据分成2段,
判断最左边值是否小于最右值(两段数据分别做判断,先右后左,命中则不用判断)
    如果为真,表示这一部分数据是顺序的,如果数据处于这一区间段,则仍然按2分算法继续查找
    如果为假,表示这一部分数据不是顺序的,那么继续切成2段,重复直到只有最后一个元素或者找不到为止

17、设计一个树形结构,再写一个函数对它进行层序遍历

Nginx

1、nginx的log_format配置如下

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                       '$upstream_response_time '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';

从今天的nginx log文件 access.log中:

  • a、列出"request_time"最大的20行?

  • b、列出早上10点访问量做多的20个url地址?

a: cat /usr/local/var/log/nginx/access.log|sort -nrk9|head -2

b: grep "07/May/2018:10:" /usr/local/var/log/nginx/access.log|awk '{print $12}'|sort -rn|uniq -c|head -20

2、nginx的进程模型,怎么支持多个并发

3、php-fpm各配置含义,fpm的daemonize模式

static - 子进程的数量是固定的(pm.max_children)
ondemand - 进程在有需求时才产生(当请求时,与 dynamic 相反,pm.start_servers 在服务启动时即启动
dynamic - 子进程的数量在下面配置的基础上动态设置:pm.max_children,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers

4、nginx和php-fpm的相关配置,随便问里面各种参数啥意思

https://www.baidu.com/s?wd=nginx%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3
https://www.baidu.com/s?wd=php-fpm%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3

5、nginx与php怎么交互通信,端口是什么

https://zhuanlan.zhihu.com/p/20694204

6、正向代理、反向代理分别是什么,如何配置

https://juejin.im/entry/586e6835ac502e12d63ecd5c 、http://blog.51cto.com/freeloda/1288553

7、nginx跟apache的区别

https://www.zhihu.com/question/19571087 
nginx支持50000个并发连接数

8、如果php-fpm挂了,访问nginx会提示什

badgateway 状态码502

9、php-fpm相关FastCGI 与 PHP-CGI 是什么,两者之间的关系

https://www.zhihu.com/question/30672017

10、2G内存可以开启多少php-fpm

一个fpm占据20-30m
https://blog.csdn.net/u010837612/article/details/78493949

11、nginx,php-fpm,进程监控,php-fpm进程数和核数

http://blog.oneapm.com/apm-tech/412.html
https://www.kancloud.cn/digest/php-src/136260

12、负载均衡,除了LVS还有什么手段

haproxy

Linux

1、linux中怎么查看系统资源占用情况,同时会问到怎么查看TCP端口,TCP连接状态

top         //可能会问得更深,比如显示出来有哪些信息、你关心哪些信息、查看某个进程等
iostat      //磁盘cpu
vmstat/sar      //监控系统CPU
free        //内存剩余
df          //磁盘使用情况
du          //文件占用信息

ps              //查看进程信息
netstat -anptol //查看端口占用情况,参数细节建议查文档,小心被问倒

2、ping一个服务器ping不通,用哪个命令跟踪路由包?

linux:traceroute,windows:tracert

3、linux中进程信号有哪些?


$kill -l
1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD
18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN
22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO
30) SIGPWR      31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1
36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4  39) SIGRTMIN+5
40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8  43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6  59) SIGRTMAX-5
60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2  63) SIGRTMAX-1
64) SIGRTMAX

我只记得一个:kill -9 进程ID ...$kill -l 1) SIGHU

4、根据access.log文件统计最近5秒的qps,并以如下格式显示,01 1000(难点在01秒数)

awk '{print $4}' /usr/local/var/log/nginx/access.log | cut -c9-21 | awk '{a[$1]++}END{for(i in a){print i" "a[i]}}' | sort -nrk2|head -20|cut -c12-

5、进程间通信方式有哪些

6、AWK各种数据分析考得非常多,要多练习,题目不再一一写了

https://segmentfault.com/a/1190000009745139
http://wiki.jikexueyuan.com/project/awk/

7、查看端口使用情况

netstat -an | grep 22  、lsof -i:22

8、查看进程

http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/ps.html 
ps -A

9、查看服务器CPU内存负载

http://www.infoq.com/cn/news/2015/12/linux-performance

10、软链接和硬链接

https://www.jianshu.com/p/dde6a01c4094

Redis

1、Redis中的有序集合是怎么实现的,它的数据结构是怎么样的

https://www.cnblogs.com/paulversion/p/8194966.html

2、数据库中的存放了用户ID,扣费很多行,redis中存放的是用户的钱包,现在要写一个脚本,将数据库中的扣费记录同步到redis中,每5分钟执行一次。请问要考虑哪些问题?

首先,本人没有实际做过此项目,我来做的话会这样:

用户的余额我会存为整数型,比如1元用100分表示
MYSQL中的扣费记录会有一个更新数据的时间

先拿到每一个待处理的用户:
   select uid from 扣费记录表 where update_time='0000-00-00 00:00:00' group by uid;
   
顺序处理每一个用户:    
    开事务
        处理在MYSQL中的扣费记录
            $time = date('Y-m-d H:i:s'); //当前时间
            update 扣费记录表 set status='已经处理状态码',update_time=$time where uid=单个用户ID;
            {
                这里可以优化成一次更新完全部用户的5分钟的数据,然后再一个一个处理:
                update 扣费记录表 set status='已经处理状态码',update_time=$time where update_time='0000-00-00 00:00:00'
            }
        
            select sum(扣费金额列) from 扣费记录表 where uid=单个用户ID and update_time=$time;    //时间点是关键
        
        对REDIS钱包进行处理:
            DECRBY 递减给定数值
            decrby key number 
    结束事务(确保redis,扣费成功,则提交)

3、redis是如何进行同步的,同步的方式,同步回滚怎么办,数据异常怎么办,同时会问MYSQL的同步方式和相关异常情况

4、redis中集合、有序集合、hyperLog、hash的数据结构是啥样的

5、数据结构+使用场景

http://www.runoob.com/w3cnote/redis-use-scene.html

6、默认连接数是多少

http://www.runoob.com/redis/redis-conf.html
10000

7、怎样实现去重100万个key中,根据模糊key名找到key

https://my.oschina.net/VASKS/blog/392775

8、rdb和aof的理解和优缺点

https://juejin.im/post/5ab5f08e518825557f00dfac

9、Redis hash里面的一个key可不可以设置过期

不可以,需要单独设置expires

其他

1、写一个函数,获取一篇文章内容中的全部图片,并下载

function downImagesFromTargetUrl($url, $target_dir = null) {
    if(!filter_var($url, FILTER_VALIDATE_URL)){
        return false;
    }
    if(!$target_dir) {
        $target_dir = './download';
    }

    $root_url = pathinfo($url);

    $html = file_get_contents($url);            //主要
    preg_match_all('/<img[^>]*src="([^"]*)"[^>]*>/i',$html, $matchs);   //主要

    $images = $matchs[1];

    foreach ($images as $img) {
        $img_url = parse_url($img);
        if(! array_key_exists('host', $img_url)) {
            $img_url = $root_url['dirname'] . DIRECTORY_SEPARATOR . $img;
        } else {
            $img_url = $img;
        }

        $img_path = array_key_exists('path', $img_url) ? $img_url['path'] : $img;
        $save = $target_dir . DIRECTORY_SEPARATOR . $img_path;
        $save_path = pathinfo($save);

        if(!is_dir($save_path['dirname'])) {
            mkdir($save_path['dirname'], 0777, true);
        }

        file_put_contents($save,file_get_contents($img_url));   //主要
    }
}

2、获取当前客户端的IP地址,并判断是否在(1.1.1.1,255.255.255.254)


function getip()
{
    $unknown = 'unknown';
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], $unknown)) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], $unknown)) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    /*
    处理多层代理的情况
    或者使用正则方式:$ip = preg_match("/[\d\.]{7,15}/", $ip, $matches) ? $matches[0] : $unknown;
    */
    if (false !== strpos($ip, ','))
        $ip = reset(explode(',', $ip));
    return $ip;
}

$client_ip = getip();
$client_ip = sprintf('%u', ip2long($client_ip));   //64位系统无压力

/**
 * plan A
 */
$range_min = sprintf('%u', ip2long('1.1.1.1'));
$range_max = sprintf('%u', ip2long('255.255.255.255'));

/**
 * plan B
 */
$range_min = bindec(decbin(ip2long('1.1.1.1')));
$range_max = bindec(decbin(ip2long('255.255.255.255')));


if ($client_ip >= $range_min and $client_ip <= $range_max) {
    echo 'true';
} else {
    echo 'false';
}
function getip() {     $unknown = 'unknown';  

3、写一个函数,尽可能高效的从一个标准URL中取出文件的扩展名

$ext = array_pop(explode('.',parse_url($url)['path']));

4、参数为多个日期时间的数组,返回离当前时间最近的那个时间

$data = [
    '2015-02-02 11:11:11',
    '2012-02-02 11:55:11',
    '2019-12-02 11:33:11',
    '2017-12-02 11:22:11',
];

$near = array_reduce($data, function($a, $b){
   return abs((time() - strtotime($a))) < abs((time() - strtotime($b))) ? $a : $b;
});

echo $near;

5、写个函数,判断下面扩号是否闭合,左右对称即为闭合: ((())),)(()),(()))),(((((()),(()()),()()

function checkClose($str)
{
    $stack = [];

    for ($i = 0; $i < strlen($str); ++$i) {
        if ($str[$i] == "(") {
            $stack[] = "(";
        }

        if ($str[$i] == ")") {
            $border = array_pop($stack);

            if(!$border) {
                return false;
            }
        }
    }

    if (count($stack) == 0) {
        return true;
    }
    return false;
}

6、请用SHELL统计5分钟内,nginx日志里访问最多的URL地址,对应的IP是哪些?

暂时没答案

7、写一段shell脚本实现备份mysql指定库(如test)到指定文件夹并打包,并删除30天前的备份,然后将新的备份推送到远端服务器,完成后送邮件通知。

暂时没答案

8、异步模型

https://tech.youzan.com/yi-bu-wang-luo-mo-xing/

9、什么是锁,怎么解决锁的问题

锁是怎么形成的呢?
比如有两个文件:a.php和b.php
a.php的操作是:先锁定A记录,然后再锁定B记录,只有锁住B记录才会释放A记录的锁
b.php的操作是:先锁定B记录,然后再锁定A记录,只有锁住A记录才会释放B记录的锁

此时a.php锁定了A记录、b.php锁定了B记录
当a.php处理完A记录后,想去锁定B记录,结果发现B记录被锁了,所以无法释放加在A记录上的锁
b记录也因为无法锁定A记录而无法释放B记录的锁
这样就形成了死锁

怎么解决:
a.php和b.php都要改成一样的加锁顺序
a.php先锁A再锁B,那b.php也要先锁A再锁B

10、分析一个问题:php-fpm的日志正常,但客户端却超时了,你认为可能是哪里出了问题,怎么排查?

11、swoole的进程模型

https://wiki.swoole.com/wiki/page/163.html

12、画出标准的公司服务器架构

https://www.zhihu.com/question/20657269

13、Swoole一直长链接会有什么问题

14、服务高可用监控,swoole监控,PHP-FPM监控, 除了查看进程,还有什么其他手段

查看nginx连接数状态(有stat模块),php-fpm连接数状态(php-fpm有status接口)

15、swoole有哪些函数不能用

sleep,die,register_shutdown_handler有梗

16、PHP5 升级 PHP7,有哪些需要注意的

http://php.net/manual/zh/migration70.php

17、信号处理;死循环能不能检测信号

http://rango.swoole.com/archives/123
https://www.jianshu.com/p/c3fb535ecd8b
https://blog.csdn.net/hustxiaoxian/article/details/78720776

18、一致性哈希算法,除了用在redis,也可以分表

http://www.cnblogs.com/zhjh256/p/6634138.html

业务设计

1、有10亿条订单数据,属于1000个司机的,请取出订单量前20的司机

对方希望要的思路: 
1、先顺序读取10亿条数据,统计每个司机各点多少订单量
2、构建一个最大堆,顺序过滤1000个司机,找到前20个司机
伪代码:
$order_data = [];
foreach(10亿条订单 as $order_info) {
    if(isset($order_data[$order_info]) {
        $order_data[$order_info] ++;
    } else {
        $order_data[$order_info] = 1;
    }
}

$map = [];
foreach ($order_data as $num) {
    if (count($map) < 20) {
        $map[] = $num;
        continue;
    }
    $min = min($map);
    if ($num > $min) {
        for ($i = 0; $i < count($map); ++$i) {
            if ($map[$i] == $min) {
                $map[$i] = $num;    //将最小值替换
                break;  //跳出循环,只替换一次
            }
        }
    }
}

2、设计一个微信红包的功能(从代码、服务器架构、数据库、性能等详细实现细节)

微信红包系统设计分享,如何扛住100亿次请求:http://www.woshipm.com/pd/232838.html
知乎有一些算法:https://www.zhihu.com/question/22625187
QA:https://www.zybuluo.com/yulin718/note/93148

注意:比如让你写两个接口,一个抢红包接口,一个发红包接口,让你设计整套的存储系统、代码实现,你怎么来做?

3、让你实现一个简单的架构,并保持高可用,两个接口,一个上传一条文本,一个获取上传的内容,你怎么来设计?要避免单机房故障,同时要让代码层面无感。

4、两台mysql服务器,其中一台挂了,怎么让业务端无感切换,并保证正常情况下讲台服务器的数据是一致的

5、设计一个缓存系统,可以定期或空间占满之后自动删除长期不用的数据,不能使用用遍历。

我当时的答案是用链表来存,缓存命中就将该缓存移到链表头,然后链表尾就都是冷数据了。
我记得之前是在哪里看过这个设计,但我忘记在连接了,请知道朋友的把连接贴上来。

前端

1、js相关跨域问题,怎么解决

https://segmentfault.com/a/1190000000718840

2、ajax jsonp 实现的区别

https://www.jianshu.com/p/fce33a35a0b6

3、CDN找不到资源是怎么办

https://blog.csdn.net/lunhui1994_/article/details/74177934
http://www.qingpingshan.com/jb/javascript/263549.html
https://xianyunyh.gitbooks.io/php-interview/

题目来自我遇到的面试和网络上各位同仁遇到的,参考下面各位,强烈推荐最后一个链接

https://github.com/hookover/php-engineer-interview-questions
http://coffeephp.com/articles/4?utm_source=laravel-china.org
https://laravel-china.org/articles/6844/a-php-interview-for-a-16-year-old-graduate
https://todayqq.gitbooks.io/phper/content/
https://xianyunyh.gitbooks.io/php-interview/
Show Comments