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

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

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. 不使用第三个变量来交换两个变量的值

  1. 两个为 数字时

    <?php
    /**
     *双方变量为数字时,可用交换方法,使用加减运算符,相当于数学运算了
     */
    $a = 1; //a变量原始值
    $b = 2;  //b变量原始值
    echo '交换之前 $a 的值:' . $a . ', $b 的值:' . $b, '<br>'; // 输出原始值
    
    $a = $a + $b; // $a $b和值
    $b = $a - $b; // 不解释..
    $a = $a - $b; // 不解释..
    echo '交换之后 $a 的值:' . $a . ', $b 的值:' . $b, '<br>'; // 输出结果值
  2. 两个为字符串时

    <?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>'; // 输出结果值
  3. 或者 str_replace 处理

<?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处理完手上的活就可以歇着了,通 过这种机制来平滑过度。

97ae4a8a4266527bcbf789475b0e0980.png

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 模式可 以保证通信的正确性和完整性,效率可以通过负载均衡等优化。

484af296286e88131e9e0ce42edf080a.png

一段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.如何保障数据的可用性,即使被删库了也能恢复到分钟级别。你会怎么做。

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

2021年最新大厂php+go面试题集(四)

2021年最新大厂php+go面试题集(三)

2021年最新大厂php+go面试题集(二)

2021年最新大厂php+go面试题集(1)

   面试官问:如何防超卖,有几种实现方式
 
posted @ 2022-10-20 23:42  码农编程进阶笔记  阅读(194)  评论(0编辑  收藏  举报
返回顶部 有事您Q我