PHP奥义

来源:互联网 发布:亿文网络 编辑:程序博客网 时间:2024/05/17 01:05

一、PHP基础篇
1、浮点数的精度:
浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。
此外,以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118…。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数(比如bcadd)或者 gmp 函数,可以先赋值给变量(自动给个精确值)再运算。

2、echo与print区别:
echo 是语法结构,也就是关键字,不是函数。使用的时候不用加括号,加上也可以。显示多个值的时候可以用逗号隔开。只支持基本类型,布尔型除外,echo true的时候显示1,echo false的时候啥都没有。

3、变量的生命周期:
a.局部变量的生命周期为其所在函数被调用的整个过程。当局部变量所在的函数结束时,局部变量的生命周期也随之结束。
b.全局变量的生命周期为其所在的”.php”脚本文件被调用的整个过程。当全局变量所在的脚本文件结束调用时,则全局变量的生命周期结束。
c、静态变量的作用范围与局部变量相同,但是生命周期与全局变量相同。

二、PHP函数篇
http://php.net/manual/zh/ref.array.php
1、call_user_func — 把第一个参数作为回调函数调用,其余参数是回调函数的参数
call_user_func_array — 把第一个参数作为回调函数调用,并把一个数组参数作为回调函数的参数
2、匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。闭包函数也可以作为变量的值来使用,闭包可以从父作用域中继承变量,任何此类变量都应该用 use 语言结构传递进去。
3、__autoload()函数只能存在一次,spl_autoload_register()当然能注册多个函数,SPL函数很丰富,提供了更多功能,如spl_autoload_unregister()注销已经注册的函数、spl_autoload_functions()返回所有已经注册的函数等。_autoload 方法在 spl_autoload_register 后会失效,因为 autoload_func 函数指针已指向 spl_autoload 方法可以通过下面的方法来把 _autoload 方法加入 autoload_functions list :spl_autoload_register( ‘__autoload’ );
4、array_merry与运算符+合并数组的区别:
a.array_merge()将两个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面。返回作为结果的数组。
如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值。然而,如果数组包含数字键名,后面的值将不会覆盖原来的值,而是附加到后面。
b.对于使用+,如果数组中有相同的key,则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值“抛弃”掉(注意:不是覆盖而是保留最先出现的那个值)

三、特性篇
1、PHP使用了引用计数(reference counting)这种单纯的垃圾回收(garbage collection)机制。 unset() 只是断开这个变量对它原先指向的内存的引用,使变量本身成为没有定义过空引用,所在调用时发出了 Notice ,并且使那块内存在符号表中引用计数 减 1,并没有影响到其他指向这块内存的变量,当一块内存在符号表中的引用计数为 0 时, PHP 引擎才会将这块内存回收, 赋值 null 操作是相当猛的,它会直接将变量所指向的内存在符号号中的引用计数置 0。

四、面向对象篇
1、OOP小常识:
a.静态方法中只能调用静态变量(原因:静态成员属于类,不需要生成对象就存在了.而非静态需要生成对象才产生,所以静态成员不能直接访问. )。

2、PHP中对象传值都是引用传值:
例如:objb=obj_a;改了objbobj_a的也会变;可以使用objb=cloneobj_a;来复制objaobj_a 的备份。

3、PHP中static关键字以及与self关键字的区别:
self调用的就是本身代码片段这个类,而static调用的是从堆内存中提取出来,访问的是当前实例化的那个类,那么 static 就是调用的当前调用的类.

<?php     class Boo {        protected static $str = "This is class Boo";         public static function get_info(){                      echo get_called_class()."<br>";            echo self::$str; //下面函数调用结果:This is class Boo          //echo static::$str; //下面函数调用结果:This is class Foo      }        }    class Foo extends Boo{        protected static $str = "This is class Foo";        }     Foo::get_info();   ?>

五、框架篇
1、MVC模式:
Model(模型)是用于处理应用程序数据逻辑的部分。
View(视图)是应用程序中处理数据显示的部分。
Controller(控制器)是应用程序中处理用户交互的部分,接收视图的请求传到Model层处理并返回结果数据在视图显示。

2、MVC、smarty、框架区别
MVC是model、controller、view 的缩写,是一种非常实用的网站开发框架,通过合理的逻辑处理以及任务分配,使得网站开发变得非常快速。
smarty是一种模板引擎,主要是用来处理网页模板视图(MVC中的V)的,可以替换网页中的元素或者实现基于模板的网页输出。而且非常容易操作,效率也是非常快。
ThinkPHP是之后基于MVC的框架,用来开发网站。是国人自己的框架,用起来还是很好的,注释非常详细。目前的3.2.2版本还是很稳定的。

六、服务篇
1、守护进程:
在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件(不会因任何终端的关闭所打断)。

2、消息队列:
原理:把消息按照产生的顺序加入队列,而由另外的处理程序/模块将其从队列中取出,并加以处理,从而形成基本的消息队列。
应用场景:
a、传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈,引入消息队列,在不影响业务流程前提下,异步处理
b、用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单失败,订单系统写入消息队列实现订单系统与库存系统的应用解耦
c、秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列,秒杀业务根据消息队列中的请求信息,再做后续处理,假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面,此为流量削锋
d、日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题;日志采集客户端,负责日志数据采集,定时写受写入Kafka队列,Kafka消息队列负责日志数据的接收、存储和转发,日志处理应用订阅并消费kafka队列中的日志数据;
e、消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯,比如实现点对点消息队列,或者聊天室等。

3、负载均衡:系统的扩展可分为纵向(垂直)扩展和横向(水平)扩展。纵向扩展,是从单机的角度通过增加硬件处理能力,比如CPU处理能力,内存容量,磁盘等方面,实现服务器处理能力的提升,不能满足大型分布式系统(网站),大流量,高并发,海量数据的问题。因此需要采用横向扩展的方式,通过添加机器来满足大型网站服务的处理能力。解决访问统一入口问题,我们可以在集群前面增加负载均衡设备,实现流量分发。
Nginx的负载均衡模块目前支持4种调度算法,下面分别进行介绍,其中后两项属于第三方调度算法:
a.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端的某个服务器宕机,故障系统被自动剔除,使用户的访问不受影响,weight 指定轮询的权值 weight值越大,分配的访问的机率越高 主要用于后端的每个服务器性能不均的情况下
b.ip_hash:每个请求按访问Ip的hash结果分配,这样来自同一个Ip的访客固定访问到一个后端服务器,有效的解决了动态网页存在的session共享问题
c.fair:这是个比上面两个更加智能的负载均衡算法,此算法可以依据页面的大小和加载时间长短智能的进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块
d.url_hash:按访问的url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率,Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx的hash软件包。

常见问题篇

nginx与PHP工作原理

nginx作为前端服务器,解析HTTP请求,通过配置文件找到server服务器,匹配合适的location,在location中的命令会启动不同的模块(nginx中模块是编译后自动加载的,比apache速度上有提升)完成工作;通过location指令,将所有以php为后缀的文件都交给 127.0.0.1:9000 来处理,而这里的IP地址和端口(127.0.0.1:9000)就是fastcgi(fastcgi是一个可伸缩地、高速地在http server和动态脚本语言间通信的接口)进程监听的IP地址和端口,主进程php-fpm主要是管理fastcgi子进程,监听9000端口,fastcgi子进程等待请求;php-fpm选择并连接到一个fastcgi子进程,并将环境变量和标准输入发送到fastcgi子进程;fastcgi子进程完成处理后将标准输出和错误信息返回,当fastcgi子进程关闭连接时,请求便告处理完成,等待下次处理。
FastCGI:是对CGI的改进,它随着Nginx服务一同启动并驻留内存,当请求到达时,处理之,处理完之后并不结束这个进程,而是继续等待下一次连接。
PHP-fpm:是PHP一个实现了FastCGI的管理器,常驻内存,负责管理各PHP-cgi进程,可以提升运行效率,并实现平滑重启。

post与get区别:(HTTP协议中两种发送请求的方法)

最直观的是get将参数包含在url中,post通过request body传递参数。
get传输数据长度2KB,POST没有长度限制。
get产生一个TCP数据包,post产生两个TCP数据包。

MySQL主从复制和读写分离:

MySQL读写分离基本原理是让master数据库处理写操作,slave数据库处理读操作。master将写操作的变更同步到各个slave节点。MySQLProxy实际上是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy,然后经由MySQLProxy进行相应的分析,判断出是读操作还是写操作,分发至对应的MySQLServer上。对于多节点Slave集群,也可以起做到负载均衡的效果。
MySQL读写分离能提高系统性能的原因在于:
物理服务器增加,机器处理能力提升。拿硬件换性能。
主从只负责各自的读和写,极大程度缓解X锁和S锁争用。
slave可以配置myisam引擎,提升查询性能以及节约系统开销。
master直接写是并发的,slave通过主库发送来的binlog恢复数据是异步。
slave可以单独设置一些参数来提升其读的性能。
增加冗余,提高可用性。

session与cookie:

①存在的位置:
cookie 存在于客户端,临时文件夹中
session:存在于服务器的内存中,一个session域对象为一个用户浏览器服务
②安全性
cookie是以明文的方式存放在客户端的,安全性低,可以通过一个加密算法进行加密后存放
session存放于服务器的内存中,所以安全性好
③网络传输量
cookie会传递消息给服务器
session本身存放于服务器,不会有传送流量
④生命周期(以20分钟为例)
(1)cookie的生命周期是累计的,从创建时,就开始计时,20分钟后,cookie生命周期结束。
(2)session的生命周期是间隔的,从创建时,开始计时如在20分钟,没有访问session,那么session生命周期被销毁;但是,如果在20分钟内(如在第19分钟时)访问过session,那么,将重新计算session的生命周期
(3)关机会造成session生命周期的结束,但是对cookie没有影响
⑤访问范围
session为一个用户浏览器独享
cookie为多个用户浏览器共享

多服务器共享session的方法:

a.基于NFS的Session共享:将共享目录服务器mount到各频道服务器的本地session目录即可,缺点是NFS依托于复杂的安全机制和文件系统,因此并发效率不高,尤其对于session这类高并发读写的小文件,会由于共享目录服务器的io-wait过高,最终拖累前端WEB应用程序的执行效率。
b.基于数据库的Session共享:首选当然是大名鼎鼎的Mysql数据库,并且建议使用内存表Heap,提高session操作的读写效率。这个方案的实用性比较强,它的缺点在于session的并发读写能力取决于Mysql数据库的性能,同时需要自己实现session淘汰逻辑,以便定时从数据表中更新、删除 session记录,当并发过高时容易出现表锁,虽然我们可以选择行级锁的表引擎,但不得不否认使用数据库存储Session还是有些杀鸡用牛刀的架势。
c.基于Cookie的Session共享:原理是将全站用户的Session信息加密、序列化后以Cookie的方式,统一种植在根域名下(如:.host.com),利用浏览器访问该根域名下的所有二级域名站点时,会传递与之域名对应的所有Cookie内容的特性,从而实现用户的Cookie化Session 在多服务间的共享访问(cookie长度4K,对存储数据的长度有限制)。
d.基于Memcache的Session共享:Memcache的内存hash表所特有的Expires数据过期淘汰机制,正好和Session的过期机制不谋而合,降低了过期Session数据删除的代码复杂度,对比“基于数据库的存储方案”,仅这块逻辑就给数据表产生巨大的查询压力。

PHP实现单点登录

a.以http://a.com作为主域名,不论http://b.com还是http://c.com登录时请求都提交到http://a.com,所有的存储都在http://a.com,其他域名不允许访问。在http://a.com登录成功后,将登录信息存放在http://a.com域下的cookie中。此时发起广播,由client端通知http://b.com和http://c.com,说用户已经登录(仅仅是告诉他们已经登录),此时用户访问http://b.com或者http://c.com时有server端向http://a.com请求获取用户信息,并将非敏感信息存储到自己的存储当中。同理,登出时也是向http://a.com发起登出请求,http://a.com将用户cookie清掉,http://b.com和http://c.com再次向http://a.com请求验证用户身份时,则验证失败。

数据加密

a.数据表中敏感数据加密一般可采用aes+base64加密,先进行aes对称加密(明文会被分割成16字节逐个进行加密,最后一块若不足16字节, 则会被补齐到16字节,基本保证相同字段下数据长度一样),加密后的密文是二进制不能正常显示,需要进行base64编码。
b.平常的密码加密:https://www.laravist.com/blog/post/php-password-hash-in-the-right-way

redis与memcache的区别:

a.存储方式:memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小;redis有部份存在硬盘上,这样能保证数据的持久性,支持数据的持久化。
b.数据支持类型:memcache只支持简单地k/v类型,redis在数据支持上要比memecache多的多。
c.分布式存储:redis支持master-slave复制模式,memcache可以使用一致性hash做分布式。
d.redis目前官方只支持LINUX 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化。

网站高并发、大访问量问题解决:

a.确认服务器硬件是否足够支持当前的流量,普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 那么必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么优化都不可能彻底解决性能问题。
b.前台实现完全的静态化最好,可以完全不用访问数据库。
c.防止盗链。
d.图片服务器分离,大文件的下载会占用很大的流量,并且对于非SCSI硬盘来说,大量文件下载会消耗 CPU,使得网站响应能力下降,建议将大文件放在另外一台服务器上。
e.缓存技术就是另一个解决方案,就是将动态数据存储到缓存文件中,动态网页直接调用 这些文件,而不必再访问数据库。
f.优化数据库:主从分离;利用分表技术;合理设计索引;使用高效查询语句。
g.负载均衡:它是根据某种负载策略把请求分发到集群中的每一台服务器上,让整个服务器群来处理网站的请求。

HTTP状态码:

100 (继续) 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
200 (成功) 服务器已成功处理了请求。
400 (错误请求) 服务器不理解请求的语法。
401 (未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
403 (禁止) 服务器拒绝请求。
404 (未找到) 服务器找不到请求的网页。
500 (服务器内部错误) 服务器遇到错误,无法完成请求。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。

TCP、UDP区别:

  • TCP协议可靠;UDP协议不可靠。
  • TCP协议是面向连接;UDP协议采用无连接。
  • TCP协议的发送方要确认接收方是否收到数据段(3次握手协议)。
  • TCP适合传输大量数据,UDP适合传输少量数据。
  • TCP速度慢,UDP速度快
1 0
原创粉丝点击