【精讲】2022年PHP中高级面试题(二)

2022-04-08 14:15:59 浏览数 (1)

1.Iptolong long2ip 注意转换成整形的时候负数问题

代码语言:javascript复制
 function IP2Long($ip) {
 $ips = explode('.', $ip); 
  if(count($ips) != 4) {
   return false;
  }
   return ($ips[0] << 24)   ($ips[1] << 16)   ($ips[2] << 8)   $ips[3];
 }

 function Long2IP($int) {
 $ip1 = $ipint >> 24;
 $ip2 = ($ipint >> 16) & 255;
 $ip3 = ($ipint >> 8) & 255;
 $ip4 = $ipint & 255;
 return $ip1.'.'.$ip2.'.'.$ip3.'.'.$ip4; 
 }

2.php链式调用:

1 使用魔法函数__call结合call_user_func来实现 2 使用魔法函数__call结合call_user_func_array来实现

3 不使用魔法函数__call来实现,修改 __call() 为 trim重点在于,返回$this指针,方便调用后者函数。

3. 不使用第三个变量来交换两个变量的值

两个为 数字时

两个为字符串时

代码语言:javascript复制
<?php
/**
 * 双方变量为字符串或者数字时,可用交换方法四
 * 使用异或运算
 */
$a = "This is A"; // a变量原始值
$b = "This is B"; // b变量原始值
echo '交换之前 $a 的值:' . $a . ', $b 的值:' . $b, '<br>'; // 输出原始值
/**
 * 原始二进制:
 * $a:010101000110100001101001011100110010000001101001011100110010000001 000001
 * $b:010101000110100001101001011100110010000001101001011100110010000001 000010
 * 下面主要使用按位异或交换,具体请参照下列给出的二进制过程,
 */
$a = $a ^ $b; // 此刻 $a:000000000000000000000000000000000000000000000000000000000000000000 000011
$b = $b ^ $a; // 此刻 $b:010101000110100001101001011100110010000001101001011100110010000001 000001
$a = $a ^ $b; // 此刻 $a:010101000110100001101001011100110010000001101001011100110010000001 000010
echo '交换之后 $a 的值:' . $a . ', $b 的值:' . $b, '<br>'; // 输出结果值

或者 str_replace 处理

代码语言:javascript复制
<?php
$a = "This is A"; // a变量原始值
$b = "This is B"; // b变量原始值
echo '交换之前 $a 的值:' . $a . ', $b 的值:' . $b, '<br>'; // 输出原始值
$a .= $b; // 将$b的值追加到$a中
$b = str_replace($b, "", $a); // 在$a(原始$a $b)中,将$b替换为空,则余下的返回值为$a
$a = str_replace($b, "", $a); // 此时,$b为原始$a值,则在$a(原始$a b)中将$b(原始$a)替换为空,则余下的返回值则为原始$b,交换成功
echo '交换之后 $a 的值:' . $a . ', $b 的值:' . $b, '<br>'; // 输出结果值

4.Strtoupper/strtolower 遇到中文会乱码

  1. 需要手动分割字符串,然后 ord 函数判断是否是单词,是则大小写转换,中文则不处 理
  2. mb_convert_case 函数中有可选参数,直接能处理这种情况

5.Php-fpm 和 NGINX 通信机制

  1. CGI:是 Web Server 与 Web Application 之间数据交换的一种协议。
  2. FastCGI:同 CGI,是一种通信协议,但比 CGI 在效率上做了一些优化。
  3. PHP-CGI:是 PHP (Web Application)对 Web Server 提供的 CGI 协议的接口程 序。
  4. PHP-FPM:是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口 程序,额外还提供了相对智能一些任务管理。

CGI就是规定要传哪些数据,以什么样的格式传递给后方处理这个请求的协议,例如 URL、查询字符串、POST数据、HTTP header,缺点是每次请求都有启动和退出操 作,不适合并发场景 Fastcgi 是常驻类型的,不需要每次去激活了 FastCGI程序会 先启动一个master,解析配置环境,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请 求。

首先要说的是:fastcgi是一个协议,php-fpm实现了这个协议。

大家都知道,PHP的解释器是php-cgi。php-cgi只是个CGI程序,他自己本身只能解析 请求,返回结果,不会进程管理,所以就出现了一些能够调度php-cgi进程的程序,php-fpm就是这样的一个东西。它克服了php-cgi变更php.ini配置后,需重启php-cgi才能让新的php-ini生效,不可以平滑重启,直接杀死php-cgi进程,php就不能运行了 的问题。修改php.ini之后,php-cgi进程的确没办法平滑重启的。php-fpm对此的处理 机制是新的worker用新的配置,已经存在的worker处理完手上的活就可以歇着了,通 过这种机制来平滑过度。

6.Explain 后需要关注的信息

列名

备注

type

本次查询表联接类型,从这里可以看到本次查询大概的效率

key

最终选择的索引,如果没有索引的话,本次查询效率通常很差

key_le n

本次查询用于结果过滤的索引实际长度,参见另一篇分享(FAQ系列-解读EXPLAIN执行计划中的key_len)

rows

预计需要扫描的记录数,预计需要扫描的记录数越小越好

Extra

额外附加信息,主要确认是否出现 Using filesort、Using temporary 这 两种情况

首先看下 type 有几种结果,分别表示什么意思:

类型

备注

ALL

执行full table scan,这是最差的一种方式

index

执行full index scan,并且可以通过索引完成结果扫描并且直接从索引中 取的想要的结果数据,也就是可以避免回表,比ALL略好,因为索引文件通 常比全部数据要来的小

range

利用索引进行范围查询,比index略好

index_sub query

子查询中可以用到索引

unique_su bquery

子查询中可以用到唯一索引,效率比 index_subquery 更高些

index_mer ge

可以利用index merge特性用到多个索引,提高查询效率

ref_or_null

表连接类型是ref,但进行扫描的索引列中可能包含NULL值

fulltext

全文检索

ref

基于索引的等值查询,或者表间等值连接

eq_ref

表连接时基于主键或非NULL的唯一索引完成扫描,比ref略好

const

基于主键或唯一索引唯一值查询,最多返回一条结果,比eq_ref略好

system

查询对象表只有一行数据,这是最好的情况

上面几种情况,从上到下一次是最差到最好。再来看下Extra列中需要注意出现的几种情况:

关键字

备注

Using filesort

将用外部排序而不是按照索引顺序排列结果,数据较少时从内存排序, 否则需要在磁盘完成排序,代价非常高,需要添加合适的索引

Using temporary

需要创建一个临时表来存储结果,这通常发生在对没有索引的列进行GROUP BY时,或者ORDER BY里的列不都在索引里,需要添加合适 的索引

Using index

表示MySQL使用覆盖索引避免全表扫描,不需要再到表中进行二次查 找数据,这是比较好的结果之一。注意不要和type中的index类型混淆

Using where

通常是进行了全表引扫描后再用WHERE子句完成结果过滤,需要添加 合适的索引

Impossible WHERE

对Where子句判断的结果总是false而不能选择任何数据,例如where 1=0,无需过多关注

Select tables optimized away

使用某些聚合函数来访问存在索引的某个字段时,优化器会通过索引直 接一次定位到所需要的数据行完成整个查询,例如MIN()MAX(),这 种也是比较好的结果之一

7.Php-fpm 运行的三种模式:

  1. Static模式最简单,直接启动配置的固定数量的进程,但是灵活性不够高
  2. ondemand 模式相对 static 模式比较复杂,会根据请求量的增加动态增加,但是处理完请求后不会立即释放,而是由定时事件定时的检测空闲到一定时间的进程才会释放
  3. Dynamic 模式类似于 ondemand 模式,但进程的回收机制不同于 ondemand 模式, 会根据 idle 数量进行增加和减少worker数量

8.Php-fpm 运行的逻辑:

Fpm 的实现就是创建一个 master 进程,在 master 进程中创建 worker pool 并监听 socket,然后 fork出多个子进程(work),这些 worker 在启动后阻塞在 fcgi_accept_request() 上,各自 accept 请求,有请求到达后 worker 开始读取请求数 据,读取完成后开始处理然后再返回,在这期间是不会接收其它请求的,也就是说 fpm 的子进程同时只能响应一个请求,只有把这个请求处理完成后才会 accept 下一个请 求,所以有多少子进程就能同时处理多少请求。

10.Fpm 工作流程:

  1. FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程,并等待来自 Web Server 的连接。
  2. Web 服务器与 FastCGI 进程管理器进行 Socket 通信,通过 FastCGI 协议发 送 CGI 环境变量和标准输入数据给 CGI 解释器进程。
  3. CGI 解释器进程完成处理后将标准输出和错误信息从同一连接返回 Web Server。
  4. CGI 解释器进程接着等待并处理来自 Web Server 的下一个连接。

11.Nginx 与 php-fpm 有两种通信方式:

tcp socketunix socket,unix 不需要经过 网络协议栈,不需要打包拆包,计算校验和,维护序号和应答,只是将应用层数据从一 个进程拷贝到另一个进程,减少不必要的 tcp 开销,高并发时性能不稳定,tcp 模式可 以保证通信的正确性和完整性,效率可以通过负载均衡等优化。

一段PHP代码会经过词法解析、语法解析等阶段,会被翻译成一个个指令 (opcode),然后 zend 虚拟机会顺序执行这些指令。PHP 本身是用C语言实现的,因 此最终调用的也是C语言的函数,实际上我们可以把 PHP 看做一个C语言开发的软 件。Opcode 是php执行的最基本单位

12.数据库连接池实现原理

连接池的作用就是为了提高性能,将已经创建好的连接保存在池中,当有请求来时,直 接使用已经创建好的连接对 Server 端进行访问。这样 省略了创建连接和销毁连接的过 程,从而提高性能。

13.Redis 常见应用场景

首页热点新闻/商品,避免频繁读取数据库 bitmap 用来记录连续签到/登录情况 新 闻阅读量的计数器 最新新闻列表 lpush 就行,然后读取 简单的消息发布系统 pubsub sortedset 来做 排行榜

14.负载均衡的几种实现方式及原理

1 ip负载均衡,相当于多一到N次重定向,过程 2 DNS 负载均衡,DNS支持一个域名多个ip地址了 3 反向代理负载均衡,NGINX 根据一定规则进行请求分发 4 F5硬件级别 6 CDN 对于静态文件的负载均衡 负载均衡构建在原有网络结构之上,它提供了一种透明且廉价有效的方法扩展服务器和 网络设备的带宽、加强网络数据处理能力、增加吞吐量、提高网络的可用性和灵活性。

15.数据库主从复制的原理,会不会延迟,会该怎样解决

三个要点:网络延迟,master 负载 slave 负载 slave 对数据安全性的要求

原理

  1. master 将数据改变记录到 binlog 中
  2. slave 启动一个io线程,从指定位置开 始同步 binlog
  3. 读取到 master 数据的更新,slave 写入到 replaylog 中,然后开始重 放数据

Tps 是事务数/秒 qps 是每秒查询率

延迟原因:主库的 tps 并发较高时,产生的 ddl 超过 slave 的执行,或者网络延迟较 大,也有可能是从库性能很差

解决:减少网络延迟,关闭 slave 的 sync_binlog 设置成大点就行,累计多次事务之后 刷盘 innodb_flush_log_at_trx_commit = 2 事务提交之后刷盘,slave 上也可以关闭 这个,缺点是意外断电了会丢失数据

16.如何保障数据的可用性,即使被删库了也能恢复到分钟级别。你会怎么做。

数据库集群方案就行,删掉主库了会自动选举从库,业务保持稳定,然后就是精细化的 备份

0 人点赞