PHP面试相关

1、php垃圾回收机制

垃圾回收机制是一种动态存储分配的方案。它会自动释放程序不再需要的已分配的内存块。php5.3之前只有引用计数 , 如果遇到循环引用的情况  , 会出现内存泄露;php5.3 之后的版本 , 有引用计数和同步周期回收算法;php7之后的版本 , 优化了引用计数部分,每个变量存在一个叫zval的变量容器中,这个变量容器,除了包含变量的类型和值外,还有两个字节的额外信息。一个是is_ref,标识这个变量是否属于引用集合。通过这个字节,php引擎可以把普通变量和引用变量区分开。另外一个字节是refcount,用来表示zval变量容器中变量的个数。
回收过程:当refcount减少到零,该变量容器将被清除,不属于垃圾;当refcount减少后还大于0,会被加入到缓冲区中,等这个缓冲区满了以后(10000个值)再统一处理。先遍历缓冲区,对当前变量的所有成员进行遍历,然后把成员的refcount减1(如果成员还包括子成员也会递归遍历,即深度优先遍历),最后再检查当前变量的引用,如果减至0则为垃圾被回收掉。

 

2、常用的设计模式有哪些了解依赖注入和反射吗

工厂模式:如果想要更改所实例化的类名等,则只需更改该工厂方法内容即可,不需逐一寻找代码中具体实例化的地方(new处)修改了。为系统结构提供灵活的动态扩展机制,减少了耦合。

单例模式:确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。主要应用场合就是应用程序与数据库打交道的场景,在一个应用中会存在大量的数据库操作,针对数据库句柄连接数据库的行为,使用单例模式可以避免大量的new操作。因为每一次new操作都会消耗系统和内存的资源。

注册模式:解决全局共享和交换对象。已经创建好的对象,挂在到某个全局可以使用的数组上,在需要使用的时候,直接从该数组上获取即可。将对象注册到全局的树上。任何地方直接去访问。

适配器模式:将各种截然不同的函数接口封装成统一的API。例如数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以memcache,redis,file,apc等不同的缓存函数,统一成一致。 首先定义一个接口(有几个方法,以及相应的参数)。然后,有几种不同的情况,就写几个类实现该接口。将完成相似功能的函数,统一成一致的方法。

观察者模式(Observer):当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新,实现了低耦合,非侵入式的通知与更新机制。

依赖注入:本质上是指对类的依赖通过构造器完成自动注入,例如在控制器架构方法和操作方法中一旦对参数进行对象类型约束则会自动触发依赖注入,由于访问控制器的参数都来自于URL请求,普通变量就是通过参数绑定自动获取,对象变量则是通过依赖注入生成。通俗来说,就是你当前操作一个类,但是这个类的某些方法或者功能不是单单只靠这个类就能完成的,而是要借助另一个类的才能完成的。

反射:运行状态中,扩展分析程序,导出或者提取出关于类、属性、方法、参数等的详细信息,包括注释。这种动态获取信息以及动态调用对象方法的功能,被称为反射API。

 

3、tp的生命周期

① 入口文件:定义应用目录、加载引导文件等

② 引导文件:变量常量的加载,自动加载机制等

③ 应用类:初始化操作

④ url检测:获取请求地址信息

⑤ 路由检测:将url与路由进行匹配

⑥ 请求分发:找到对应的控制器和方法

⑦ 响应输出:控制器处理完毕后response类会将返回的结果返回给客户端

⑧ 程序结束:日志在这个时候做记录,至此整个生命周期结束

 

4、nginx和php之间的工作原理

用户通过http将请求发送给nginx服务器,nginx对请求后缀加以解析,静态资源返回给用户,动态资源比如php文件,nginx会调用fastcgi接口,将请求转发给php-fpm,然后再转给PHP解析服务器wrapper,wrapper会新启一个线程来处理PHP请求,最后将处理后的结果返回给nginx,nginx返回给用户。

 

5、

1) Redis是单线程还是多线程

redis是单线程模型,执行redis命令的核心模块是单线程的,redis其他模块是有各自线程的。redis基于reactor模式开发了网络时间处理器,这个处理器被称为文件事件处理器,由四部分组成:多个套接字、IO多路复用、文件事件分派器、事件处理器。因为文件事件分派器的消费是单线程的,因此redis才叫单线程模型。redis的瓶颈并不在cpu,而在内存和网络。内存不够的话,可以加内存或者做数据结构优化和其他优化等,但网络的性能优化才是大头,网络 IO 的读写在 Redis 整个执行期间占用了大部分的 CPU 时间,如果把网络处理这部分做成多线程处理方式,那对整个 Redis 的性能会有很大的提升。

2) Redis为什么这么快?

  • 数据存储在内存中,绝大部份请求是纯粹的内存操作,非常快速。
  • 数据结构简单,对数据的操作也简单,redis中的数据结构是专门进行设计的。
  • redis是单线程模型,避免了不必要的上下文切换,也不存在多进程或者多线程导致的切换而对CPU进行的消耗,不用考虑各种锁的问题,不存在加锁释放锁等操作,不会出现因为可能出现死锁而导致的性能消耗。
  • 使用多路I/O复用模型,非阻塞IO。
  • redis自己构建了VM机制,在进行系统调用系统函数的时候,节约了一定的时间去移动和请求。

3) redis有哪几种数据类型分别有哪些运用场景

  • 字符串(string):简单键值对缓存,例如计数器等
  • 哈希(hash):结构化的数据,例如用户信息等
  • 列表(list):列表型的数据结构,例如粉丝列表、文章评论列表等
  • 集合(set):交集、并集、差集的操作,例如两个人的粉丝交集列表等
  • 有序集合(zset):去重并排序,例如排行榜列表等

4) redis持久化

  • RDB快照:将某个时间点上redis中的数据保存到一个RDB文件中,该文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时redis中的数据。载入规则:只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据;如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据。
  • AOF日志:通过保存redis服务器所执行的写命令来记录数据库数据。还原步骤:创建一个不带网络连接的伪客户端;从AOF文件中分析并读取出一条命令;使用伪客户端执行被读取出的写命令;一直执行以上两步操作,直到AOF文件中的所有写命令全部执行完

5) redis出现缓存雪崩穿透击穿的原因及解决方案

  • 缓存雪崩:缓存同一时间大面积失效,这个时候来了一波请求,导致所有的请求都到数据库上。给缓存的失效时间一个随机值,避免集体失效。
  • 缓存穿透:请求缓存中不存在的数据,导致所有的请求都到了数据库上。采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据将被拦截;如果一个查询返回的数据为空,将此空结果进行缓存,一定时间后将过期。
  • 缓存击穿:热点数据在缓存中查不到,在同一时刻被超高并发的请求,导致所有的请求都到了数据库上。设置分布式互斥锁,只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可;设置永不过期缓存

 

6、

1) mysql优化方案

建表规范、索引优化、sql优化、开启慢查询等

2) mysql索引优化原理有哪几种数据结构有几种索引为什么主键索引查询效率更快

索引是帮助mysql高效获取数据的排好序的数据结构:

二叉树:树的深度会越来越深而造成IO次数变多

Hash:等值查询效率较高,但是不支持范围和模糊查询

B-Tree:所有的键值和具体的数据分布在整颗树中,数据越来越多之后,效率也会变低

B+Tree:数据只存储在叶子节点中,非叶子结点可存放更多索引。叶子节点也包含索引字段,且用指针连接,能更好的处理范围查询。

mysql主要有普通索引、唯一索引、主键索引、组合索引、全文索引。

主键索引是整型,排序性能好,自增的插入效率高。

3) mysql常见的存储引擎及区别

Innodb:支持事务、支持外键、并发量较大、适合大量update、mysql8之后支持全文索引;不适合大量查询操作

Myisam:查询数据效率较高,适合大量的查询操作;但是不支持事务、不支持外键、并发量较小、不适合大量update

4) mysql事务特性及隔离级别事务并发一般会产生哪些问题应该如何解决

特性:原子性、一致性、隔离性、持久性

隔离级别:读未提交、读已提交、可重复读、串行化

事务产生的问题:

更新丢失(Lost Update):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题,最后的更新覆盖了由其他事务所做的更新;

脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务没有提交前, 这条记录的数据就一直处于不确定状态; 这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些脏数据,并据此做进一步的处理,就会产生未提交的数据依赖关系,这种现象被形象地叫做脏读。

不可重复读(Non-Repeatable Reads):一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读” 。

幻读(Phantom Reads): 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读” 。

解决方案:

以上问题都是数据库读一致性导致的,因此必须由数据库提供一定的事务隔离机制来解决。加锁:在读取数据前,对其加锁阻止其他事务对数据进行修改。例如,读的时候加共享锁,此时其他事务无法修改相应数据;写的时候加排他锁,禁止其他事务读写操作,这种做法性能较差。多版本并发控制(MVCC):不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照,并用这个快照提供一定级别的一致性读取,从用户角度来看,好像是数据库可以提供同一数据的多个版本。

 

7、docker的优点和应用场景

资源隔离:比如限制应用最大内存使用量,或者资源加载隔离等。

低消耗:虚拟化本身带来的损耗需要尽量的低。

Docker 很好的权衡了两者,即拥有不错的资源隔离能力,又有很低的虚拟化开销

 

8、高并发解决方案

① 数据库层面:数据库缓存、分表分库分区、读写分离、负载均衡

② 服务端层面:消息队列(描述具体实现流程)

③ web服务层面:nginx反向代理、lvs负载均衡等

 

9、说说自己接触过的es集群架构索引数据大小分片数量调优手段等

10、自动化构建工具jenkins和git仓库的部署

11、其他语言加成

 

posted @ 2022-03-03 14:04  乌乌丢丢  阅读(45)  评论(0编辑  收藏  举报