[关闭]
@xxliixin1993 2017-03-28T09:15:19.000000Z 字数 11906 阅读 1295

Interview


php执行过程

php源码分析

变量

鸟哥php变量作用域分析
变量的值 类型 引用 放在zval中, 而变量名放在_zend_executor_globals结构中,symbol_table是定义在函数外的变量 key存名字 value存指向zval的指针, 函数中定义的变量会放在active_symbol_table

  1. struct _zend_executor_globals {
  2. ....
  3. HashTable *active_symbol_table;/*活动符号表*/
  4. HashTable symbol_table; /*全局符号表*/
  5. HashTable included_files;
  6. jmp_buf *bailout;
  7. int error_reporting;
  8. .....
  9. }

Nginx优化配置

  1. events {
  2. worker_connections 2048;
  3. multi_accept on;
  4. use epoll;
  5. }

worker_connections 设置可由一个worker进程同时打开的最大连接数。
multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的连接。
use [epoll|rtsig|select|poll] 设置用于复用客户端线程的轮询方法。如果你使用Linux 2.6+,你应该使用epoll。如果你使用*BSD,你应该使用kqueue。

  1. 假设一共有四颗cpu,表示方法,超过8颗使用更多的位数
  2. cpu10000 0001
  3. cpu20000 0010
  4. cpu30000 0100
  5. cpu40000 1000
  6. worker_cpu_affinity 00000001 00000010 00000100;

Nginx怎么与php交互

fastcgi相关配置

  1. fastcgi的相关配置:
  2. LNMPphp启用fpm模型;
  3. location ~ \.php$ {
  4. root /var/www/html;
  5. fastcgi_pass 127.0.0.1:9000;
  6. fastcgi_index index.php;
  7. # fastcgi_param SCRIPT_FILENAME $doucment_root$fastcgi_script_name;
  8. fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
  9. # fastcgi_params在/etc/nginx/下,若编译时没指定配置文件则在/usr/local/nginx/conf/下
  10. include fastcgi_params;
  11. }

apache acces.log统计前十个ip

awk -F' ' '{print $1}' /var/log/nginx/access.log |sort|uniq -c|sort -rn|head -10

Mysql优化

Mysql索引数据结构

http://www.uml.org.cn/sjjm/201107145.asp

B+树

事务的特性

ACID
原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

事务隔离级别

未提交读 READ UNCMMITTED

事务中的修改,即使没提交,对其他事务也都是可见的。
脏读:事务可以读取未提交的数据。

提交读 READ COMMITED

一个事务从开始知道提交之前,所做的修改对其他事务都是不可见的。避免脏读,但可以出现不可重复读和幻读。

可重复读 REPEATABLE READ

解决了脏读的问题,可以保证在同一事务中多次读取记录的结果是相同的。但是这样也会出现幻读的情况,是指当某个事务在读取某个范围内的记录时另一个事务又在该范围内插入了新的记录,当之前的事务再读取到该范围的记录时,会产生幻行。这是MySQL的默认事务隔离级别

可串行化 SERIALZABLE

在读取的每一行数据上都加锁,所以会避免脏读和幻读,但是会导致大量的超时和锁征用问题。

设计模式

工厂

  1. class Mysql {
  2. public function __construct() {}
  3. }
  4. class SqlServer {
  5. public function __construct() {}
  6. }
  7. class DataFactory {
  8. public static function create($database_type) {
  9. $type = ucfirst($database_type);
  10. switch ($type) {
  11. case 'Mysql':
  12. return new Mysql();
  13. break;
  14. case 'Sqlserver':
  15. return new SqlServer();
  16. break;
  17. default:
  18. return false;
  19. break;
  20. }
  21. }
  22. }

单例

  1. class A {
  2. private static $instance;
  3. private function __construct() {}
  4. private function __clone() {}
  5. public static function getInstance() {
  6. if (self::$instance instanceof self) {
  7. return self::$instance;
  8. } else {
  9. return new self();
  10. }
  11. }
  12. }

策略模式 一种动作根据传入不同的对象做不同的事

  1. interface BaseAgent {
  2. public function alert();
  3. }
  4. class IE implements BaseAgent {
  5. public function alert() {
  6. echo 'IE';
  7. }
  8. }
  9. class Chrome implements BaseAgent {
  10. public function alert() {
  11. echo 'Chrome';
  12. }
  13. }
  14. class Browser {
  15. public function call($anget_obj) {
  16. $anget_obj->alert();
  17. }
  18. }
  19. // $b = new Browser();
  20. // $b->call(new IE()); ====> IE $b->call(new Chrome()); ======> Chrome

观察者模式 有时被称作发布/订阅模式 观察者模式定义了一种一对多的依赖关系 当主程序发生变化时需要通知所有观察者进行更新

  1. interface Observerable {
  2. public function update();
  3. }
  4. //主程序
  5. class Game {
  6. private $_observers = array();
  7. public function register($sub) {
  8. /* 注册观察者 */
  9. $this->_observers[] = $sub;
  10. }
  11. public function trigger() {
  12. if (!empty($this->_observers)) {
  13. foreach ($this->_observers as $observer) {
  14. $observer->update();
  15. }
  16. }
  17. }
  18. }
  19. //第一关
  20. class RoundOne implements Observerable {
  21. public function update() {
  22. echo 'callback ';
  23. }
  24. }
  25. //第二关
  26. class RoundTwo implements Observerable {
  27. public function update() {
  28. echo 'callback ';
  29. }
  30. }
  31. //使用
  32. $ro = new RoundOne();
  33. $rt = new RoundTwo();
  34. $g = new Game();
  35. //注册
  36. $g->register($ro);
  37. $g->register($rt);
  38. //Game do something后 发生更新通知
  39. $g->trigger();

装饰模式 before after模式

  1. interface IComponent {
  2. public function display();
  3. }
  4. //待装饰对象
  5. class Controller implements IComponent {
  6. public function display() {
  7. echo 'this is Controller';
  8. }
  9. }
  10. //装饰器基类
  11. class Decoration implements IComponent {
  12. protected $_com;
  13. public function register(IComponent $com) {
  14. $this->_com = $com;
  15. }
  16. public function display() {
  17. if (!empty($this->_com)) {
  18. $this->_com->display();
  19. }
  20. }
  21. }
  22. //具体装饰器
  23. class AfterBefore extends Controller implements IComponent {
  24. public function display() {
  25. echo '+ before +';
  26. parent::display($this);
  27. echo '+ after +';
  28. }
  29. }
  30. $c = new Controller();
  31. $ab = new AfterBefore();
  32. $d = new Decoration();
  33. $d->register($ab);
  34. $d->display();

MVC优缺点

优点:
1、开发人员可以只关注整个结构中的其中某一层;
2、可以很容易的用新的实现来替换原有层次的实现;
3、可以降低层与层之间的依赖;
4、有利于标准化;
5、利于各层逻辑的复用。

缺点:
1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
2、增加了系统结构和实现的复杂性,有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。

empty和isset的区别

empty() 如果 var 是非空或非零的值,则 empty() 返回 FALSE。换句话说,""、0、"0"、NULL、FALSE、array()、var $var; 以及没有任何属性的对象都将被认为是空的,如果 var 为空,则返回 TRUE。
isset() 检测变量是否设置,并且不是 NULL。

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
    考虑到安全应当使用session。
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
    考虑到减轻服务器性能方面,应当使用COOKIE。
  4. 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

session禁用cookie后怎么办

TCP IP协议

OSI:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
IP协议在OSI网络层 TCP协议在传输层

3次握手4次断开

3次握手:
client请求连接->server确认连接并询问client是否确认->client确认

  1. 建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认
  2. 服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态
  3. 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK

4次断开

【注意】中断连接端可以是Client端,也可以是Server端。
假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

  1. A发送一个FIN,用来关闭A到B的数据传送,A进入FIN_WAIT_1状态。
  2. B收到FIN后,发送一个ACK给A,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),B进入CLOSE_WAIT状态。
  3. B发送一个FIN,用来关闭B到A的数据传送,B进入LAST_ACK状态。
  4. A收到FIN后,A进入TIME_WAIT状态,接着发送一个ACK给B,确认序号为收到序号+1,B进入CLOSED状态,完成四次挥手。

TCP协议的拥塞控制机制

TCP拥塞控制四个主要过程
慢启动阶段:早期开发的TCP应用在启动一个连接时会向网络中发送大量的数据包,这样很容易导致路由器缓存空间耗尽,网络发生拥塞,使得TCP连接的吞吐量急剧下降。由于TCP源端无法知道网络资源当前的利用状况,因此新建立的TCP连接不能一开始就发送大量数据,而只能逐步增加每次发送的数据量,以避免上述现象的发生。具体地说,当建立新的TCP连接时,拥塞窗口(congestion window,cwnd)初始化为一个数据包大小。源端按cwnd大小发送数据,每收到一个ACK确认,cwnd就增加一个数据包发送量,这样cwnd就将随着回路响应时间(Round Trip Time,RTT)呈指数增长,源端向网络发送的数据量将急剧增加。事实上,慢启动一点也不慢,要达到每RTT发送W个数据包所需时间仅为RTT×logW。由于在发生拥塞时,拥塞窗口会减半或降到1,因此慢启动确保了源端的发送速率最多是链路带宽的两倍。

拥塞避免阶段:如果TCP源端发现超时或收到3个相同ACK副本时,即认为网络发生了拥塞(主要因为由传输引起的数据包损坏和丢失的概率很小(<<1%))。此时就进入拥塞避免阶段。慢启动阈值(ssthresh)被设置为当前拥塞窗口大小的一半;如果超时,拥塞窗口被置1。如果cwnd>ssthresh,TCP就执行拥塞避免算法,此时,cwnd在每次收到一个ACK时只增加1/cwnd个数据包,这样,在一个RTT内,cwnd将增加1,所以在拥塞避免阶段,cwnd不是呈指数增长,而是线性增长。

快速重传和快速恢复阶段:快速重传是当TCP源端收到到三个相同的ACK副本时,即认为有数据包丢失,则源端重传丢失的数据包,而不必等待RTO超时。同时将ssthresh设置为当前cwnd值的一半,并且将cwnd减为原先的一半。快速恢复是基于“管道”模型(pipe model)的“数据包守恒”的原则(conservation of packets principle),即同一时刻在网络中传输的数据包数量是恒定的,只有当“旧”数据包离开网络后,才能发送“新”数据包进入网络。如果发送方收到一个重复的ACK,则认为已经有一个数据包离开了网络,于是将拥塞窗口加1。如果“数据包守恒”原则能够得到严格遵守,那么网络中将很少会发生拥塞;本质上,拥塞控制的目的就是找到违反该原则的地方并进行修正。

一次加密通信过程 ssl通信

发送者:

  1. 使用单向加密算法提取生成数据的特征码;
  2. 使用自己的私钥加密特征码附加在数据后面;
  3. 生成一个用于对称加密的临时密钥;
  4. 用此临时密钥加密数据和已经使用私钥加密后的特征码;
  5. 使用接收方的公钥加密此临时密钥,附加在对称加密后的数据后方;

接收方:

  1. 使用自己的私钥解密加密的临时密钥;从而获得对称密钥;
  2. 使用对称密钥解密对称加密的数据和私钥加密的特征码密文;从而获得数据和特征码密文;
  3. 使用发送方的公钥解密特征码密文,从而获得从计算生成的特征码;
  4. 使用与对方同样的单向加密算法计算数据的特征码,并与解密而来的进行比较

http和https的区别

php安全问题

如何定位服务器高负载的原因

redis持久化,数据类型,队列

持久化
AOF :相当于binlog,记录下所有命令
RDB :将数据直接写在磁盘文件中

五种数据类型:

list实现队列

memcached分布式算法 一致性hash

一致性 HASH 算法我的理解,简单来说就是 , 在一个大的数据范围内的构建一个虚拟的环,首( 0 )尾( Integer.MAXVALUE )相接的圆环,然后通过 某种 HASH 算法 增加虚拟节点的方式( 1 个实体节点可以虚拟 N 个虚拟阶段,如 160 , 200 , 1000 等)让节点更为均匀的分别在环上。 KEY 请求的时候,也通过相同的某种 HASH 算法 计算出 HASH 值,然后在到环上定位同向最接近的虚拟节点,最后通过虚拟节点与实体节点的对应关系找到服务的实体节点。

memcached优缺点

http://www.cnblogs.com/WuNaiHuaLuo/p/5225330.html
优点: Memcached 进程运行之后,会预申请一块较大的内存空间,自己进行管理,用完之后再申请,不是每次需要的时候去向操作系统申请。Memcached将对象保存在一个巨大的Hash表中,它还使用NewHash算法来管理Hash表,从而获得进一步的性能提升。所以当分配给Memcached的内存足够大的时候,Memcached的时间消耗基本上只是网络Socket连接了

缺点: 数据是保存在内存当中的,一旦服务进程重启,数据会全部丢失

Smarty优缺点

优点:缓存技术,编译型,速度快
缺点:浪费内存。如$_smarty_tpl_vars = $this->_tpl_vars;,两个变量,占用了两倍以上的内存(虽然使用后unset掉了)。
浪费处理器。smarty语法最后是要转换成php脚本供输出的。转换要浪费处理器资源。如果是编译好的缓存中的脚本,则浪费判断是否有编译好的脚本的处理器时间。

一个数组里的奇数全部排在偶数前面

用插入排序好 一次能排完

  1. $arr = array(3,2,4,5,1,6,7,8,10,9);
  2. function quick_sort($arr){
  3. $len = count($arr);
  4. if ($len <= 1) {
  5. return $arr;
  6. }
  7. $left = array();
  8. $right = array();
  9. //标尺
  10. $base = $arr[0];
  11. for ($i=1;$i<$len;$i++) {
  12. if ($arr[$i] > $base) {
  13. $right[] = $arr[$i];
  14. } else {
  15. $left[] = $arr[$i];
  16. }
  17. }
  18. $left = quick_sort($left);
  19. $right = quick_sort($right);
  20. return array_merge($left,array($base),$right);
  21. }
  22. function odd_even($arr){
  23. $left = array();
  24. $right = array();
  25. foreach ($arr as $key => $val) {
  26. if ($val & 1) {
  27. //奇数
  28. $left[] = $val;
  29. } else {
  30. $right[] = $val;
  31. }
  32. }
  33. return array_merge($left,$right);
  34. }
  35. var_dump(odd_even(quick_sort($arr)));

冒泡排序

  1. $arr=array(1,43,54,62,21,66,32,78,36,76,39);
  2. function getpao($arr)
  3. {
  4. $len=count($arr);
  5. //设置一个空数组 用来接收冒出来的泡
  6. //该层循环控制 需要冒泡的轮数
  7. for($i=1;$i<$len;$i++)
  8. { //该层循环用来控制每轮 冒出一个数 需要比较的次数
  9. for($k=0;$k<$len-$i;$k++)
  10. {
  11. if($arr[$k]>$arr[$k+1])
  12. {
  13. $tmp=$arr[$k+1];
  14. $arr[$k+1]=$arr[$k];
  15. $arr[$k]=$tmp;
  16. }
  17. }
  18. }
  19. return $arr;
  20. }

选择排序

  1. function select_sort($arr) {
  2. //实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数
  3. //$i 当前最小值的位置, 需要参与比较的元素
  4. for($i=0, $len=count($arr); $i<$len-1; $i++) {
  5. //先假设最小的值的位置
  6. $p = $i;
  7. //$j 当前都需要和哪些元素比较,$i 后边的。
  8. for($j=$i+1; $j<$len; $j++) {
  9. //$arr[$p] 是 当前已知的最小值
  10. if($arr[$p] > $arr[$j]) {
  11. //比较,发现更小的,记录下最小值的位置;并且在下次比较时,应该采用已知的最小值进行比较。
  12. $p = $j;
  13. }
  14. }
  15. //已经确定了当前的最小值的位置,保存到$p中。
  16. //如果发现 最小值的位置与当前假设的位置$i不同,则位置互换即可
  17. if($p != $i) {
  18. $tmp = $arr[$p];
  19. $arr[$p] = $arr[$i];
  20. $arr[$i] = $tmp;
  21. }
  22. }
  23. //返回最终结果
  24. return $arr;
  25. }

二分查找

  1. <?php
  2. #二分查找
  3. function binarySearch(Array $arr, $target) {
  4. $low = 0;
  5. $high = count($arr) - 1;
  6. while($low <= $high) {
  7. $mid = floor(($low + $high) / 2);
  8. #找到元素
  9. if($arr[$mid] == $target) return $mid;
  10. #中元素比目标大,查找左部
  11. if($arr[$mid] > $target) $high = $mid - 1;
  12. #重元素比目标小,查找右部
  13. if($arr[$mid] < $target) $low = $mid + 1;
  14. }
  15. #查找失败
  16. return false;
  17. }
  18. $arr = array(1, 3, 5, 7, 9, 11);
  19. $inx = binarySearch($arr, 1);
  20. var_dump($inx);
  21. ?>

shell遍历一个目录下的所有文件和子目录

  1. #!/bin/bash
  2. function list() {
  3. for file in `ls $1`
  4. do
  5. if [ -d $1"/"$file ]
  6. then
  7. echo 'this is dir: '$1"/"$file
  8. list $1"/"$file
  9. else
  10. echo $1"/"$file
  11. fi
  12. done
  13. }
  14. list $1

快速排序

  1. $arr = [3, 4, 5, 1, 2, 6, 9, 7, 10];
  2. function qs($arr) {
  3. $l = [];
  4. $r = [];
  5. if (count($arr) < 1) {
  6. return $arr;
  7. }
  8. for ($i = 1; $i < count($arr); $i++) {
  9. if ($arr[$i] < $arr[0]) {
  10. $r[] = $arr[$i];
  11. } else {
  12. $l[] = $arr[$i];
  13. }
  14. }
  15. $l = qs($l);
  16. $r = qs($r);
  17. return array_merge($l, (array) $arr[0], $r);
  18. }
  19. print_r(qs($arr));exit;
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注