2020PHP面试热题(一)

1.请说出PHP的常用设计模式

单例模式:保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,同时这个类还必须提供一个访问该类的全局访问点。

工厂模式:定义一个创建对象的接口,但是让子类去实例化具体类。工厂方法模式让类的实例化延迟到子类中。

观察者模式:观察者模式有时也被称作发布/订阅模式,该模式用于为对象实现发布/订阅功能:一旦主体对象状态发生改变,与之关联的观察者对象会收到通知,并进行相应操作。

适配器模式:适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。

依赖注入模式:依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。要实现控制反转,通常的解决方案是将创建被调用者实例的工作交由 IoC 容器来完成,然后在调用者中注入被调用者(通过构造器/方法注入实现),这样我们就实现了调用者与被调用者的解耦,该过程被称为依赖注入。 门面模式:门面模式(Facade)又称外观模式,用于为子系统中的一组接口提供一个一致的界面。

2.redis 和 memache 缓存的区别
 

1.数据类型

Redis数据类型丰富,支持set list等类型

memcache支持简单数据类型,需要客户端自己处理复杂对象

2.持久性

redis支持数据落地持久化存储

memcache不支持数据持久存储

3.分布式存储

redis支持master-slave复制模式
memcache可以使用一致性hash做分布式
value大小不同

memcache是一个内存缓存,key的长度小于250字符,单个item存储要小于1M,不适合虚拟机使用

4.数据一致性不同

redis使用的是单线程模型,保证了数据按顺序提交。

memcache需要使用cas保证数据一致性。CAS(Check and Set)是一个确保并发一致性的机制,属于“乐观锁”范畴;原理很简单:拿版本号,操作,对比版本号,如果一致就操作,不一致就放弃任何操作
5.cpu利用redis单线程模型只能使用一个cpu,可以开启多个redis进程
总结二:

1.Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。

2.Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。

3.Redis支持数据的备份,即master-slave模式的数据备份。

4.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

最本质的不同是Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcached只是简单的K/V缓存

总结三:

redis和memecache的不同在于:

1、存储方式:

memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小

redis有部份存在硬盘上,这样能保证数据的持久性。

2、数据支持类型:

redis在数据支持上要比memecache多的多。

3、使用底层模型不同:

新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

4、运行环境不同:

redis目前官方只支持Linux 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上

memcache只能当做缓存,cache

redis的内容是可以落地的,就是说跟MongoDB有些类似,然后redis也可以作为缓存,并且可以设置master-slave
 

3.请说出http和https的区别

①端口: HTTP 80  |  HTTPS 443

②安全性: HTTP 明文传输 | HTTPS 加密传输

 ③证书申请方式: HTTP 免费申请 | HTTPS 需要到ca申请,一般需要交费。 

④连接方式: HTTP 无状态 | HTTPS SSL+ HTTP 可加密传输、身份认证等。 ( https 需要在http的基础上加上ssl 也就是 需要交换TCP的3个包的基础上还要交换SSL的9个包,所以HTTP比HTTPS快)

4.MySQL的隔离级别

① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

② Repeatable read (可重复读):可避免脏读、不可重复读的发生。

③ Read committed (读已提交):可避免脏读的发生。

④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

名词解释:

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

4.MySQL和NOSQL的区别和优缺点

简单来说MySQL是关系型数据库,体积小、速度快、成本低、结构稳定、便于查询,可以保证数据的一致性,但缺乏灵活性,nosql是非关系型数据库,高性能、高扩展、高可用,不用局限于固定的结构,减少了时间和空间上的开销,却又很难保证数据一致性。

MySQL的优点:事务处理—保持数据的一致性;由于以标准化为前提,数据更新的开销很小(相同的字段基本上只有一处);可以进行Join等复杂查询

NoSQL的优点:首先它是基于内存的,也就是数据放在内存中,而不是像数据库那样把数据放在磁盘上,而内存的读取速度是磁盘读取速度的几十倍到上百倍,所以NoSQL工具的速度远比数据库读取速度要快得多,满足了高响应的要求。即使NoSQL将数据放在磁盘中,它也是一种半结构化的数据 格式,读取到解析的复杂度远比MySQL要简单,这是因为MySQL存储的是经过结构化、多范式等有复杂规则的数据,还原为内存结构的速度较慢。NoSQL在很大程度上满足了高并发、快速读/和响应的要求,所以它也是Java互联网系统的利器。

NoSQL的缺点:大多数NoSQL数据库都不支持事务,也不像 SQL Server和Oracle那样能提供各种附加功能,比如BI和报表等; 不提供对SQL的支持 

5.HTTP请求过程

① 对网址进行DNS域名解析成IP地址 (浏览器DNS缓存、系统DNS缓存、host文件、dns域名服务器查询)

②根据这个IP,找到对应的服务器,发起TCP的三次握手,建立起链接状态

③服务器响应请求、浏览器获取响应结果。(具体到php项目的话 此步骤应该为 tcp建立了端口的连接后,将请求指定给监听80端口的nginx,nginx识别到php请求,不能直接与php通信,故将请求转发给了fastcgi模块,也就是实现程序php-fpm。php-fpm会有一个master进程管理着多个worker进程,多个worker进程通过争抢accept锁的方式获得这次请求的执行权,一系列的初始化后,zend引擎对被请求页面进行语法和词法解析,生成opcode,然后按顺序执行opcode,最终将处理结果返回给nginx,再由nginx返回给终端)

④浏览器根据响应结果渲染页面。

⑤服务器关闭关闭TCP连接

6.GET和POST的区别

url可见性  get可见,参数在url中。 post不可见,参数在http包内(request body)。

②数据长度限制。 get 受不同浏览器的url长度限制,基本上在2k-4k之间。 理论上post无长度限制,起限制作用的是服务器的处理程序的处理能力 ,可以修改服务器相关配置。

③安全性上, post比get安全稍微好一些,但是没什么用,抓包一样可见,防君子不防小人。

 ④编码方式上,get只支持url编码,post支持多种编码方式。 

⑤数据类型上,get只支持ASCII, post无限制,支持二进制数据。

 ⑥缓存上,get的数据可以缓存。 post的无法缓存  (GET请求会被浏览器主动cache,而POST不会,除非手动设置)

 ⑦后退按钮get参数还在,历史记录中也可追溯。  post的参数均丢失。 

⑧ get 的 效率 高!

7.cookie和session 的区别

session 是 服务端 保存的数据结构。 一般用来跟踪用户状态。 cookie 是 客户端 保存用户信息的一种机制。 用来记录用户信息。 一般大小不超过4k。 session 一般用session_id 来进行唯一性标识。  cookie是实现并传递session_id的一种方式, 也可以通过url和header传递。

8.如何理解3个范式

第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;

第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;

第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余

9.如何优化sql语句提高程序效率

(1)选择正确的存储引擎
以 MySQL为例,包括有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。但是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
(2)优化字段的数据类型
记住一个原则,越小的列会越快。如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。当然,你也需要留够足够的扩展空间。
(3)为搜索字段添加索引
索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么最好是为其建立索引,除非你要搜索的字段是大的文本字段,那应该建立全文索引。
(4)避免使用Select *从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。即使你要查询数据表的所有字段,也尽量不要用*通配符,善用内置提供的字段排除定义也许能给带来更多的便利。
(5)使用 ENUM 而不是 VARCHAR
ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。例如,性别、民族、部门和状态之类的这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。
(6)尽可能的使用 NOT NULL
除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。 NULL其实需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。
(7)固定长度的表会更快
如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理。
固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。
并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间。

①Where子句中:where表之间的连接必须写在其他Where条件之前,那些可以过滤掉最大数量记录的条件必须写在Where子句的末尾.HAVING最后。
②用EXISTS替代IN、用NOT EXISTS替代NOT IN。
③ 避免在索引列上使用计算
④避免在索引列上使用IS NULL和IS NOT NULL
⑤对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
⑥应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
⑦应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描

10.举例说出索引失效的情况

①.以%开头的like查询

②数据类型出现隐式转换的时候也不会使用索引,特别是当列类型是字符串,那么一定记得在where条件中把字符串常量值用引号引起来,否则即便这个列上有索引,MySQL也不会用到,因为MySQL默认把输入的常量值进行转换以后才进行检索

③复合索引的情况下,如果查询条件不包含索引列的最左边部分,即不满足最左前缀原则,则不会使用索引

④如果mysql估计使用索引扫描比全表扫描更慢,则不使用索引。(扫描数据超过30%,都会走全表) 

⑤用or分割开的条件,如果 or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到 

⑥字段使用函数,将无法使用索引

⑦Join 语句中 Join 条件字段类型不一致的时候 MySQL 无法使用索引

11.Mysql 的存储引擎,myisam和innodb的区别。

MyISAM 是非事务的存储引擎;适合用于频繁查询的应用;表锁,不会出现死锁;适合小数据,小并发
innodb是支持事务的存储引擎;合于插入和更新操作比较多的应用;设计合理的话是行锁(最大区别就在锁的级别上);适合大数据,大并发。

12.请写出冒泡排序的代码

// 冒泡排序法
Function mysort($arr){
 For($i=0; $i<count($arr); $i++){
  For($j=0; $j<count($arr)-1-$i; $j++){
   If($arr[$j] > $arr[$j+1]){
    $tmp=$arr[$j];
    $arr[$j]=$arr[$j+1];
    $arr[$j+1]=$tmp;
            }
        }
    }
 Return $arr;
}
$arr=array(3,2,1);
print_r(mysort($arr));

13.索引的优缺点

索引实现的原理:

 

优点:

①快速访问数据表中的特定信息,提高检索速度

②创建唯一性索引,保证数据库表中每一行数据的唯一性

③加速表和表之间的连接

④使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间

缺点:

①创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加;

②索引需要占用物理空间,不光是表需要占用数据空间,每个索引也需要占用物理空间;

③当对表进行增、删、改的时候索引也要动态维护,这样就降低了数据的维护速度。

14.防止SQL注入:

①开启配置文件中的magic_quotes_gpc和magic_quotes_runtime设置

②执行sql语句使用addslashes进行sql语句转换

③Sql语句书写尽量不要省略小引号和单引号

④过滤掉sql语句中的一些关键字:update、insert、delete、select、*

⑤提高数据库表和字段的命名技巧,对一些重要的字段根据程序的特点命名,取不易被猜到的。

⑥Php配置文件中设置register_globals为off,关闭全局变量注册

⑦控制错误信息,不要再浏览器上输出错误信息,将错误信息写到日志文件中。

15.请写出冒泡排序算法



Function mysort($arr){
 For($i=0; $i
  For($j=0; $j
   If($arr[$j] > $arr[$j+1]){
    $tmp=$arr[$j];
    $arr[$j]=$arr[$j+1];
    $arr[$j+1]=$tmp;
            }
        }
    }
 Return $arr;
}

$arr=array(3,2,1);
print_r(mysort($arr));

16.对于大流量的网站,您采用什么样的方法来解决访问量问题?

优化程序,优化数据库,如果程序和数据库已经最优化,使用以下解决方法:
①确定当前服务器设备是否满足流量需求。
②使用Memcache缓存技术,把动态内容缓存到文件中,动态网页直接调用这些文件,而不必再访问数据库。
③禁止外部盗链,图片和文件外部盗链会给服务器带来大量的负载压力,可以通过refer来禁止外部盗链,或者使用apache来配置禁止盗链。
④控制大文件的下载,大文件的下载对于非SCSI硬盘来说会占用大量的资源,导致服务器的响应能力下降。
⑤使用不同的主机分流主要流量,使服务器均衡负载。
⑥使用流量统计软件统计分析网站流量,可以知道哪些地方耗费了大量的流量,哪些页面需要再进行优化。

17.如何处理负载,高并发?

①HTML静态化(效率最高、消耗最小)
②图片服务器分离(把图片单独存储,尽量减少图片等大流量的开销,可以放在七牛云,阿里云oss上等)
③数据库集群和库表散列及缓存(数据库的并发连接为100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如memcache、redis。)
④镜像:减少大流量下载,可以把不同的请求分发到多个镜像端。
⑤负载均衡:Apache的最大并发连接为1500,只能增加服务器,可以从硬件上着手,如F5服务器。当然硬件的成本比较高,我们往往从软件方面着手。

18.请举例说出PHP7的新特性

① 性能提升:PHP7比PHP5.0性能提升了两倍(变量存储字节减小,减少内存占用,提升变量操作速度;改善数组结构,数组元素和hash映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率;改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率)

② 以前的许多致命错误,现在改成抛出异常。

③ PHP 7.0比PHP5.0移除了一些老的不在支持的SAPI(服务器端应用编程端口)和扩展。

④ PHP 7.0比PHP5.0新增了空接合操作符。

⑤ PHP 7.0比PHP5.0新增加了结合比较运算符。

⑥ PHP 7.0比PHP5.0新增加了函数的返回类型声明。

⑦ PHP 7.0比PHP5.0新增加了标量类型声明。

⑧ PHP 7.0比PHP5.0新增加匿名类。

⑨ 错误处理和64位支持

19.apche 和 nginx 的优缺

nginx轻量级,比apache占用更少的内存及资源,抗并发,nginx处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能。apache 相对于nginx 的优点:rewrite比nginx 的rewrite 强大,少bug,稳定。(需要性能用nginx,求稳定就apache)。

20.laravel有那些特点?

① .强大的rest router:用简单的回调函数就可以调用,快速绑定controller和router

② artisan:命令行工具,很多手动的工作都自动化

③ 可继承的模板,简化view的开发和管理

④ blade模板:渲染速度更快

⑤ ORM操作数据库

⑥ migration:管理数据库和版本控制

⑦ 测试功能也很强大

⑧ composer也是亮点

 

21.商城秒杀的实现?
  使用redis队列来完成,把要秒杀的商品放入到队列中,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,文件锁和事务在高并发下性能下降很快,当然还要考虑其他方面的东西,比如抢购页面做成静态的,通过ajax调用接口,其中也可能会出现一个用户抢多次的情况,这时候需要再加上一个排队队列和抢购结果队列及库存队列。高并发情况下,将用户进入排队队列,用一个线程循环处理从排队队列取出一个用户,判断用户是否已在抢购结果队列,如果在,则已抢购,否则未抢购,库存减1,写数据库,将用户入结果队列。

 

22.购物车的原理?

购物车的实现主要是通过cookie、session或结合数据库的方式

虽然cookie可用来实现购物车,但必须获得浏览器的支持,再加上它是存储在客户端的信息,极易被获取,所以这也限制了它存储更多,更重要的信息。所以一般cookie只用来维持与服务器的会话,例如国内最大的当当网络书店就是用cookie保持与客户的联系,但是这种方式最大的缺点是如果客户端不支持cookie就会使购物车失效。

Session能很好地与交易双方保持会话,可以忽视客户端的设置。在购物车技术中得到了广泛的应用。但session的文件属性使其仍然留有安全隐患。

结合数据库的方式虽然在一定程度上解决了上述的问题,但从上面的例子可以看出:在这种购物流程中涉及到对数据库表的频繁操作,尤其是用户每选购一次商品,都要与数据库进行连接,当用户很多的时候就加大了服务器与数据库的负荷。

23.redis消息队列先进先出需要注意什么?

答:通常使用一个list来实现队列操作,这样有一个小限制,所以的任务统一都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念,我们就可以优先处理高级别的任务,实现方式有以下几种方式:

1)单一列表实现:队列正常的操作是 左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush),这样,从队列头部(右侧)获取任务时,取到的就是高优先级的任务(rpop)

2)使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列,获取任务时也很简单,redis的BRPOP命令可以按顺序从多个队列中取值,BRPOP会按照给出的 key 顺序查看,并在找到的第一个非空 list 的尾部弹出一个元素,redis> BRPOP list1 list2 0

list1 做为高优先级任务队列

list2 做为普通任务队列

这样就实现了先处理高优先级任务,当没有高优先级任务时,就去获取普通任务

方式1最简单,但实际应用比较局限,方式3可以实现复杂优先级,但实现比较复杂,不利于维护

方式2是推荐用法,实际应用最为合适

24.PHP的垃圾收集机制是怎样的?

PHP可以自动进行内存管理,清除不再需要的对象。
PHP使用了引用计数(reference counting)这种单纯的垃圾回收(garbage collection)机制。每个对象都内含一个引用计数器,每个reference连接到对象,计数器加1。当reference离开生存空间或被设为NULL,计数器减1。当某个对象的引用计数器为零时,PHP知道你将不再需要使用这个对象,释放其所占的内存空间。

25.写一个函数,能够遍历一个文件夹下的所有文件和子文件夹


    function my_scandir($dir){

        $files = array();

        if(is_dir($dir)){

            if ($handle = opendir($dir)) {

                while (($flie = readdir($handle))!== false) {

                    if ($flie!="." && $file!="..") {

                        if (is_dir($dir."/".$file)) {

                            $files[$file] = my_scandir($dir."/".$file);

                        } else {

                            $files[] = $dir."/".$file;

                        }

                    }

                }

                closedir($handle);

                return $files;

            }

        }

    }

?>

26.swoole框架举例

swoft,easyswoole...

swoft框架首个基于 Swoole 原生协程的新时代 PHP 高性能协程全栈框架,内置协程网络服务器及常用的协程客户端,常驻内存,不依赖传统的 PHP-FPM,全异步非阻塞 IO 实现,以类似于同步客户端的写法实现异步客户端的使用,没有复杂的异步回调,没有繁琐的 yield, 有类似 Go 语言的协程、灵活的注解、强大的全局依赖注入容器、完善的服务治理、灵活强大的 AOP、标准的 PSR 规范实现等等,可以用于构建高性能的Web系统、API、中间件、基础服务等等。
 









-


 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值