返回 登录
0

PHP各种各样的面试题目整理

服务器方面

1、nginx平滑重启

nginx 运行新的工作进程并从容关闭旧的工作进程,通知工作进程关闭监听套接字,但是继续为当前连接的客户提供服务。所有的客户端的服务完成后,旧的工作进程被关闭。如果新的配置文件应用失败,nginx 将继续使用旧的配置文件进行工作。
说简单点就是 nginx会继续处理之前的请求,并且启动一个新的进程来处理新的请求,旧的进程处理完成之后会被kill。

2、获取文件后10行。
tail -10 a.log

3、查看占用系统资源比较多的进程
top
ps:输完top命令之后,按1可以看内存以及cpu使用情况

3、查看关键字出现函数
grep -n ‘我是要查找的关键字’ a.txt | cut -d “:” - f1

统计文件中关键字分别出现的哪一行:
    grep -n "关键字"    “文件路径” | cut -d ":"  -f1

统计文件中关键字出现的最后一行行号:
grep -n “关键字” “文件路径” | tail -n 1 | cut -d “:” -f1

4、在/root/目录下搜索带有关键字“www”的文件,在终端下运行命令:
find /root/ –type f | xargs grep “www

5、统计文件 行数
wc -l a.txt

统计demo目录下,js文件数量:
    find demo/ -name "*.js" |wc -l
统计demo目录下所有js文件代码行数:
    find demo/ -name "*.js" |xargs cat|wc -l 
     wc -l `find ./ -name "*.js"`|tail -n1
统计demo目录下所有js文件代码行数,过滤了空行:
    find /demo -name "*.js" |xargs cat|grep -v ^$|wc -l

6、实时监控一个文件
tail -f a.log

7、nginx日志中访问最多的100个ip及访问次数
nginx日志中访问最多的100个ip及访问次数
awk ‘{print $1}’ /opt/software/nginx/logs/access.log| sort | uniq -c | sort -n -k 1 -r | head -n 100

8、在编译完成的php,添加新的扩展
-----------------------------------------
源码安装
1、找到php的源码目录
2、跳转到EXT目录下边
3、执行phpize生成configure文件
4、 ./configure –with-php-config=/usr/local/php/bin/php-config
5、编译 make
6、编译安装 make install
7、修改php.ini extension=/usr/local/*.so
8、重启php-fpm

YUM安装:

1、去PHP的官网下载源码 (htpp://pecl.php.net)
2、解压文件
3、执行phpize生成configure文件
4、 ./configure --with-php-config=/usr/local/php/bin/php-config
5、编译 make
6、编译安装 make install
7、修改php.ini extension=/usr/local/***.so
8、重启php-fpm

-----------------------------------------

php优化 nginx优化 mysql优化

php优化:
1、将类的方法定义为static。
2、尽量使用单引号。
3、修改php-fpm进程数。
4、修改单个脚本最大可使用内存。
5、大的数组使用完之后要及时释放。
6、循环的时候,制定最大循环次数
7、不使用@屏蔽错误
8、尽量采用大量的 PHP 内置函数
9、使用require代替require_once

nginx优化:
1、修改nginx的子进程数。 [ 最多65535 ]
2、开启静态缓存
3、修改主进程数。建议按照cpu 数目来指定,一般为它的倍数 (如,2个四核的cpu计为8)
4、开启gzip输出 [ 开启gzip,ob函数就不能用了 ]
5、keepalive_timeout 设置连接超时时间

mysql优化:
1、避免子查询
2、有顺序的读取
3、避免重复的读写
4、设置自增id
5、避免使用select *
6、合理设置字段类型
7、读写分离
8、分区、分表
9、建立合适的索引
10、避免使用耗费资源的操作 null
11、不要使用rand()
12、尽量不要使用 or 查询
13、查询一条数据的时候加上LIMIT 1
14、开启查询缓存
15、前期对数据进行合理的评估,进行分区、分表
16、避免使用 %前缀的模糊查询
17、避免使用mysql自带函数
18、使用多从解决查询慢的问题

秒杀如何实现?

我们做的秒杀并发量就是十几万、下边的版本是十几万的:

1、专门对秒杀服务器 [ps:量大的话这么说,如果小的话就不用了 ]
2、生成静态页面。 [ ps:如果还很大的可以把这个文件放在 cdn上 ]
3、倒计时以及库存从服务端获取 [ 一段时间内只获取一次,倒计时结束之后会请求下服务端,是否已经开始 ]
4、把要秒杀的数据库存放到redis中 [ key value ] stock=10
5、设置一个redis队列 [ 使用list做队列 ] lpop rpush
6、用户在请求的时候,判断用户是否参与过秒杀,没有参加过把用户数据写入队列中,同时库存减1 ,参加过就提示已经参加过
ps:这块用到了redid的原子性操作、以及事务 multi 和 watch
redis乐观锁 cas ==== 就是设置之前判断下这个值有没有改变
7、库存减0就不能进行秒杀
8、异步脚本处理队列数据 [ crontab + php文件 ]

如果你说是1-3万的话,就不用单独去租服务器了

如果问到业务相关的问题的话,就随机应变吧!!!!

比如说: 10 个用户买了都不支付怎么办?
第一种说法 :
就说当时的产品需求是不支付也没有问题,其它用户也不可以买了,当时在做的和产品讨论了,产品说正常的话用户都会支付,因为比较便宜
第二种说法:
会开启下一轮的秒杀。 比如说小米的 2小时之后还可以继续买!!
第三站说法:
会。。。。

怎么保证不超买 ?
减库存的时候是原子性操作,使用cas乐观锁。测试的时候没有出现过超买的情况

还有就是秒杀的时候就不用购物车了,点击的时候就排队了

Q1:防刷是怎么做的?一般抢购都有很大优惠。如果有人恶意刷,那正常的用户就失去了购买的机会。比如,抢购的商品数为1000,有人恶意刷了900,那只有 100 被正常用户抢到。等恶意抢到的 900 经过后面的支付环节验证后,可能已经过了抢购时间了。就算恶意抢到的 900 都支付成功,那对正常用户也是不公平的。
在这个业务场景中,我们做的是商品展示、商品的购买权的发放,真正产生消费是在第三方。那么,用户刷的问题,需要我们和第三方支付页面一起来控制。在用户通过排队机制,获得了购买名额后,跳转去第三方时候,我们按照和第三方约定的加密方式传递加密信息,第三方按照约定的解密方式解密成功后才允许用户支付,加密解密的过程中可以带具有生命周期的内容。这样,用户在高频请求支付页面获取商品时候,实际只有:1)加密对;2)第一次,才可能获得。不过,第三方都是为了销售出商品,所以这类合作的成功几率不大。恶意刷,的确会在我们的业务层面展示商品没量了。导致想买的用户没了机会,但可以保证第三方不受损。这种刷的情况,若想在我们业务层规避,我想这就是一个通用的防SPAM的问题了。这块自己真懂得不多。

Q2:要想准确的放刷,判断的维度就多,逻辑就复杂;与之矛盾的,抢购要求的是响应迅速。
对的,抢购业务因为请求压力大、热门商品抢购并发高,切忌增加过多逻辑,切忌过多后端依赖,越简单效果越好。我们在设计系统时候,很多事不是咱们一个系统能cover的,多少需要一些前置模块、能力的构建ready后,我们的系统才能run的不错。建议构建帐号体系、用户消费记录这两部分。
Q3:对账只是和第三方去对比商品的库存量吗,金额是否去对比?
对账,其实是对比的消费数据。避免出现我们统计今日产生了X件商品共价值Y的消费,第三方给出的是消费了N件共M价值的消费。避免金额不一致,造成结算、分成等问题的出现。我想你问题中的库存量的diff问题,还得靠第三方定期的通过我们数据层的接口来update他们提供的商品。其实在我们的商品库中,商品不一定只允许第三方提供,也可以允许第三方通过接口减少商品嘛,比如和一个卖水果的第三方合作,第三方上周发布说有100件,但这周线下热销,只剩20件了,我们也应该允许第三方来update到一个低值。但这样,我们的系统中就会复杂挺多。

Q4:防刷,避免第三方的推广效果达不到问题。
对的,用户ID维度、IP维度,都是有效办法。看具体场景。有帐号体系的业务,用用户ID维度效果最好,借助存储记录下每个用户的购买记录,来控制就好。市面上的电商网站,基本是抢购业务都需要登录,并且限制每件商品单人购买数量,其实就是通过存储记录用户的消费,并且再次产生消费前查询并增加代码逻辑来控制。

Q5:每次抢购活动的时候用一套新的验证码?
验证码这个东东,属于图灵测试嘛,只要测试方法好,并且尽可能保证每次产生的验证信息从未出现过且无规律,就是好的验证码啦。

比较好的秒杀系统架构:
http://www.csdn.net/article/2014-11-07/2822545
http://www.kuqin.com/shuoit/20141203/343669.html

算法题:

http://blog.csdn.net/frimish/article/details/48666485

怎么在海量数据中找出重复次数最多的一个

网站日志中记录了用户的IP,找出访问次数最多的IP

假设有1kw个身份证号,以及他们对应的数据。身份证号可能重复,要求找出出现次数最多的身份证号。

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

有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。

常见的排序:
http://www.php100.com/html/php/rumen/2013/1029/6333.html

冒泡排序:
原理:
把第一个数字和所有数字进行比较,然后遇到大的交换位置,这样第一次就把最大的放在了最后边,然后继续在比较,第二次比较的时候最后一个数字就不用比较了,因为已经确定它是最大的了,以此类推。

    1. 冒泡排序法 

* 思路分析:法如其名,就是像冒泡一样,每次从数组当中 冒一个最大的数出来。
* 比如:2,4,1 // 第一次 冒出的泡是4
* 2,1,4 // 第二次 冒出的泡是 2
* 1,2,4 // 最后就变成这样

时间复杂度:
    冒泡排序是一种用时间换空间的排序方法,最坏情况是把顺序的排列变成逆序,或者把逆序的数列变成顺序。

arr=array(1,43,54,62,21,66,32,78,36,76,39);functiongetpao(arr)
{
len=count(arr);
//设置一个空数组 用来接收冒出来的泡
//该层循环控制 需要冒泡的轮数
for(i=1;i<len;i++)
{ //该层循环用来控制每轮 冒出一个数 需要比较的次数
for(k=0;k<leni;k++)  
    {  
       if($arr[$k]>$arr[$k+1])  
        {  
            $tmp=$arr[$k+1];  
            $arr[$k+1]=$arr[$k];  
            $arr[$k]=$tmp;  
        }  
    }  
  }  
  return
arr;
}

2、选择排序:
http://jingyan.baidu.com/article/f3ad7d0f07516d09c3345b19.html
http://mmm2010.blog.163.com/blog/static/174230348201292273310140/

function select_sort(arr) {  
//实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数  
    //
i 当前最小值的位置, 需要参与比较的元素
for(i=0,len=count(arr);i<len1;i++) {
//先假设最小的值的位置
p=i;
//ji 后边的。
for(j=i+1; j<len; j++)//$arr[$p]if($arr[$p]>$arr[$j])//,//$p=$j;//p中。
//如果发现 最小值的位置与当前假设的位置iif(p != i) {  
            $tmp = $arr[$p];  
            $arr[$p] = $arr[$i];  
            $arr[$i] = $tmp;  
        }  
    }  
    //返回最终结果  
    return
arr;
}

3.快速排序法

function quick_sort(arr) {  
    //先判断是否需要继续进行
length = count(arr);if(length <= 1) {
return arr;  
    }  
    //如果没有返回,说明数组内的元素个数 多余1个,需要排序  
    //选择一个标尺  
    //选择第一个元素
base_num = arr[0];////left_array = array();//小于标尺的
rightarray=array();//for(i=1; i<length; i++)if($basenum>$arr[$i])//$leftarray[]=$arr[$i];else//$rightarray[]=$arr[$i];////,left_array = quick_sort(leftarray);right_array = quick_sort(rightarray);//returnarraymerge(left_array, array(basenum),right_array);
}

4、插入排序法
http://blog.csdn.net/hijiankang/article/details/9207735

情景描述:
  紧接冒泡排序,每次同学们都屡试不爽,但是学生越来越多了,老师发现每次排完队,就耽搁了大半节课时了,说道:“咱不用冒泡了,有点OUT了,今天来插入排序”。这时体育老师担任起了数学老师的职责,又给同学们讲了种排队方式–插入排序。
1. 开始以第一位同学为基准,由第二个同学开始向前和第一位同学比较,个头高了不动,低了换位
2. 第三个同学要先和自己前面的第二位同学比较,如果低了,和第二换位,然后再向前和第一比较,低了再换,否则阻断,不再比较
3. 从前往后依次执行步骤2,依次出来一位同学,每次和自己前面的同学进行比较,找到一个合适位置插入,其余学生后移
合适位置:前一位同学等于或低于自己身高,并且后一位同学高于自己身高
  按照这个方式,同学们一个个依次找准位置,再也不用每次相邻的都比较,而且找到位置后就不必再往前面比较了……

插入排序法思路:将要排序的元素插入到已经 假定排序号的数组的指定位置。
function insert_sort(arr) {  
    //区分 哪部分是已经排序好的  
    //哪部分是没有排序的  
    //找到其中一个需要排序的元素  
    //这个元素 就是从第二个元素开始,到最后一个元素都是这个需要排序的元素  
    //利用循环就可以标志出来  
    //i循环控制 每次需要插入的元素,一旦需要插入的元素控制好了,  
    //间接已经将数组分成了2部分,下标小于当前的(左边的),是排序好的序列  
    for(
i=1, len=count(arr); i<len; i++)//$tmp=$arr[$i];//for($j=$i1;$j>=0;$j)//$arr[$i];//;$arr[$j];//if($tmp<$arr[$j])////$arr[$j+1]=$arr[$j];//$arr[$j]=$tmp;else////break;////returnarr;
}

/**
* 插入排序,默认第一位已经排好序,从第二位开始依次向前比较,确定自己的位置后插入,即前一位小余或等于当前,且后一位大于当前。
* 插入后,自己新位置后面的元素依次向后移位, 完成一轮插入排序
* @param arr
* @return
*/
public static int[] insertSort(int[] arr) {
int len = arr.length;
for (int i = 1; i < len; i++) {
if (arr[i - 1] > arr[i]) {
int k = arr[i];
int j = i;
while (j > 0 && arr[j - 1] > k) {
arr[j] = arr[j - 1];
j–;
}
arr[j] = k;
}
}
return arr;
}

二分查找:

http://www.tuicool.com/articles/2MbAR3q
http://blog.csdn.net/xzjxylophone/article/details/4714326
1,2,3,4,5,6,7
我现在要查找7
我先取出中间数 4
判断下是不是要找的数字,发现小了
就去右边查找
然后取出右边的所有的数
取出她们几个的中间数 6
发现还小了
继续找右边的数组
找到7了 ok了!!!

最差的一种情况就是这个数字不存在 ====

1

评论