php面试题-2020年7月7日

1.写程序交换x,y交换两个变量的值 不使用中间变量

list($x,$y) = [$y,$x];

2.请描述一下链接www.a.com/test.php?id=1是如何被解析的(nginx服务器)

www.example.com   Nginx
路由到 www.example.com/index.php
加载nginx的fast-cgi模块
fast-cgi监听127.0.0.1:9000地址 .
www.example.com/index.php请求到达127.0.0.1:9000
php-fpm 监听127.0.0.1:9000
php-fpm 接收到请求,启用worker进程处理请求
php-fpm 处理完请求,返回给nginx
nginx将结果通过http返回给浏览器

3.你用什么方法检测php脚本的执行效率和数据库sql的效率  并定位脚本执行和数据库查询的瓶颈

一般是在你要检查的代码开头记录一个时间,结尾记录一个时间。取差值,
数据库SQL的效率
sql的explain(mysql),启用slow query log记录慢查询。
通常还要看数据库设计是否合理,需求是否合理等。

4.分析sql语句 select * from product where price=100慢的原因

1、数据量大 加上limit 一定数量的限制
2、字段可以写出只要需要的字段 seletc id, name 等

5.php5中的魔术方法  请说明用途

__construct():  实例化对象时被调用;
__destuct():    当删除一个对象或者对象操作终止时被执行;
__call():      调用对象不存在方法时被调用;
__get():       调用对象不存在的属性时被调用;
__set():       设置对象不存在的属性时被调用;
__toString():  打印一个对象时被调用,比如echo $obj,print($obj);
__clone():      克隆对象时被调用,比如$t = new Test();$tt = clone $t;
__sleep():      serialize之前被调用,若对象比较大,想做一些删除在序列化,可以考虑使用该方法;
__wakeup():    unserialize之前被调用,做些对象的初始化;
__isset():     检测对象是否存在属性的时候被调用,如 isset($c->name);
__unset():      unset一个对象属性时被调用,如:unset($c->name);
__set_state(): 调用var_export时被调用,用__set_state的返回值作为 var_export的返回值;
__autoload():  实例化一个对象时,如果对应的类不存在,在该方法被调用.

6.php后端如何解决跨域问题

header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:GET, POST, OPTIONS, DELETE");
header("Access-Control-Allow-Headers:DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Accept-Language, Origin, Accept-Encoding");

7.redis实现锁

1. 第一种锁命令INCR

这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。
然后其它用户在执行 INCR 操作进行加一时,如果返回的数大于 1 ,说明这个锁正在被使用当中。
    1、 客户端A请求服务器获取key的值为1表示获取了锁 
    2、 客户端B也去请求服务器获取key的值为2表示获取锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求的时候获取key的值为1表示获取锁成功
    5、 客户端B执行代码完成,删除锁
    6、 设置有效期
    $redis->incr($key);
    $redis->expire($key, $ttl); //设置生成时间为1秒
2.第二种锁SETNX

这种加锁的思路是,如果 key 不存在,将 key 设置为 value
如果 key 已存在,则 SETNX 不做任何动作

    1、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
    2、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求设置key的值,设置成功
    5、 客户端B执行代码完成,删除锁
    6、 设置有效期
    $redis->setNX($key, $value);
    $redis->expire($key, $ttl);
3.上面两种方法都有一个问题,会发现,都需要设置 key 过期。那么为什么要设置key过期呢?如果请求执行因为某些原因意外退出了,导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新。于是乎我们需要给锁加一个过期时间以防不测。
但是借助 Expire 来设置就不是原子性操作了。所以还可以通过事务来确保原子性,但是还是有些问题,所以官方就引用了另外一个,使用 SET 命令本身已经从版本 2.6.12 开始包含了设置过期时间的功能。

    1、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
    2、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
    3、 客户端A执行代码完成,删除锁
    4、 客户端B在等待一段时间后在去请求设置key的值,设置成功
    5、 客户端B执行代码完成,删除锁
$redis->set($key, $value, array('nx', 'ex' => $ttl)); //ex表示秒

 

 

 

你可能感兴趣的:(php)