一、PHP&CodeIgniter框架基础(岗位硬性必考点)
1. 请简述PHP7相较PHP5核心性能、语法层面的关键优化
答案
-
- 性能:引入Zend引擎第7代,优化变量存储结构(zval重构),降低内存占用,常规场景性能提升2~4倍,大幅降低对象、数组内存开销;
-
- 语法:新增标量类型声明、返回值类型声明、空合并运算符
??、太空船运算符<=>、匿名类;移除老旧废弃扩展、mysql原生扩展,强制使用mysqli/pdo;
- 语法:新增标量类型声明、返回值类型声明、空合并运算符
-
- 错误处理:将多数致命错误转为可捕获异常,适配try-catch;
-
- 异步支持:更好兼容Swoole等常驻内存框架。
2. 单例、工厂、观察者三种设计模式的适用业务场景,结合PHP举例
答案
- • 单例:保证一个类全局仅创建一个实例,常用于数据库连接、Redis客户端、配置管理器,避免重复创建连接浪费资源;CI底层数据库驱动就使用单例管理连接。
- • 工厂模式:封装对象创建逻辑,调用方无需关心类实例化细节;比如封装不同支付渠道类,统一工厂方法获取支付实例,新增支付方式无需修改上层业务代码。
- • 观察者:定义事件与订阅者,事件触发时批量通知多个订阅逻辑;例如订单完成后,同时触发发券、短信通知、统计埋点多个逻辑,实现业务解耦。
3. 讲解CI框架MVC架构、路由执行流程,请求从进入框架到返回响应完整链路
答案
-
- MVC分工:
- • Model:封装数据库读写、数据校验逻辑;
- • View:页面模板渲染,接口开发可省略视图层,直接返回JSON;
- • Controller:接收请求、调度模型、组装返回数据。
-
- 执行流程:
1)访问入口index.php,初始化框架环境、加载全局配置;
2)路由解析:读取URL/自定义路由配置,匹配对应的控制器、方法、URL参数;
3)实例化控制器,调用目标方法;
4)控制器调用Model查询数据,可借助Library自定义扩展封装通用逻辑;
5)数据组装后直接输出JSON或渲染View模板,返回响应。
- 执行流程:
4. CI如何自定义扩展、二次开发,举例两种常用扩展方式
答案
-
- 自定义Library库:把通用逻辑(鉴权、OSS上传)封装成库,控制器内通过
$this->load->library()加载调用;
- 自定义Library库:把通用逻辑(鉴权、OSS上传)封装成库,控制器内通过
-
- 自定义Model基类:新建基础Model封装通用分页、软删除方法,业务Model继承该基类复用逻辑;
-
- 使用钩子Hooks:在框架生命周期各个节点植入自定义逻辑,例如请求前置校验、全局日志记录,不用修改框架内核代码。
5. RESTful API设计规范是什么?JWT做接口鉴权的实现思路、优缺点
答案
RESTful规范
- • 使用HTTP动词代表操作:GET查询、POST新增、PUT修改、DELETE删除;
- • URL使用名词,不用动词,例
/users代表用户资源; - • 通过状态码标识请求结果:200成功、401未授权、403权限不足、404资源不存在;
- • 请求、响应统一JSON格式。
JWT鉴权思路
用户登录成功后,生成包含用户id、过期时间的三段式令牌(头部、载荷、签名)返回前端;前端后续请求请求头携带token;后端校验签名、有效期,确认身份。
优缺点
优点:无服务端会话存储,适合分布式部署;跨服务、跨端适配性好;
缺点:令牌签发后未到期无法主动作废;载荷不能存放敏感信息;一般搭配Redis黑名单实现强制下线。
6. Composer作用是什么?autoload自动加载原理
答案
Composer是PHP依赖包管理工具,可以引入第三方开源库、管理版本、处理依赖冲突;
自动加载基于PSR-4规范,注册自动加载函数,调用类时根据命名空间映射文件路径,自动require引入对应php文件,无需手动写大量include语句;CI4原生适配Composer自动加载。
二、MySQL数据库专项(JD核心考点)
1. 数据库范式、反范式分别适用什么场景,做表设计如何取舍?
答案
- • 三大范式核心:字段原子性、主键唯一、消除非主键字段传递依赖,优点减少数据冗余,保证数据一致性;适合订单流水、财务这类强一致性写入场景。
- • 反范式:刻意冗余部分字段,多表查询无需关联;适合读多写少、高并发查询场景,例如商品列表冗余分类名称,避免频繁联表查询,牺牲少量写入性能换取查询速度。
取舍:写入频繁、对一致性严格遵循范式;查询压力大、报表类业务采用反范式加冗余字段。
2. SQL慢查询优化完整流程,Explain关键字段含义
答案
优化流程:开启慢查询日志抓取慢SQL → Explain分析执行计划 → 新增/调整索引 → 改写SQL(拆分大分页、减少联表) → 压测验证性能。
Explain关键字段:
-
type:访问类型,最优system/const,日常需要达到range/ref,all全表扫描必须优化;
-
key:实际命中使用的索引;
-
rows:预估扫描行数,数值越大性能越差;
-
Extra:出现Using filesort(文件排序)、Using temporary(临时表)代表需要优化。
3. MySQL四种事务隔离级别,分别解决什么并发问题?死锁产生条件、常规解决手段
答案
四个隔离级别从低到高:
-
- 读未提交:可读取其他事务未提交数据,会出现脏读、不可重复读、幻读;
-
- 读已提交:解决脏读,存在不可重复读、幻读,MySQL InnoDB默认隔离级别;
-
- 可重复读:解决脏读、不可重复读,通过MVCC降低幻读影响;
-
- 串行化:所有事务串行执行,彻底解决三类并发问题,并发性能极差。
死锁四大必要条件:互斥、请求保持、不可剥夺、循环等待;
解决手段:统一SQL锁表顺序、降低事务粒度缩短事务执行时间、添加死锁检测、设置超时自动回滚。
- 串行化:所有事务串行执行,彻底解决三类并发问题,并发性能极差。
三、Redis专项高频面试题
1. Redis五种基础数据结构业务使用场景
答案
-
- String:缓存用户基础信息、计数器、接口限流计数;
-
- Hash:存储用户详情、商品属性这类结构化字段,无需序列化整个对象;
-
- List:简单消息队列、最新消息列表;
-
- Set:去重场景,点赞、共同好友;
-
- Sorted Set:排行榜、延时队列,依靠分值排序。
2. 缓存雪崩、穿透、击穿分别是什么?对应解决方案
答案
-
- 缓存雪崩:大量key同一时间过期,大量请求打到数据库;方案:过期时间加随机偏移、搭建Redis集群、服务限流降级。
-
- 缓存穿透:请求查询数据库不存在的数据,绕过缓存反复查库;方案:布隆过滤器、空结果短期缓存。
-
- 缓存击穿:热点key过期,海量并发请求直达数据库;方案:热点key永不过期、互斥分布式锁控制单线程重建缓存。
3. Redis RDB、AOF两种持久化区别;主从、哨兵架构作用
答案
- • RDB:定时生成二进制快照文件,恢复速度快,可能丢失最近一段时间数据;适合冷备份。
- • AOF:记录每一条写命令,数据安全性高,文件体积大,恢复慢;日常生产两者混合开启。
主从复制:主库写入,从库分担查询压力,读写分离;
哨兵:监控主节点状态,主库故障自动选举新主库,实现故障转移,保障高可用。
4. 基于Redis实现分布式锁(Redlock)核心思路
答案
-
- 使用
set key value NX EX 过期时间原子指令加锁,防止死锁;
- 使用
-
- 锁value存入当前请求唯一标识,解锁时校验归属避免误删其他线程锁;
-
- Redlock部署多独立Redis节点,超过半数节点加锁成功才算获取锁,规避单节点故障导致锁失效,适配分布式集群场景。
四、Linux、Nginx、PHP-FPM、Docker运维部署类
1. LNMP架构请求完整链路,Nginx、PHP-FPM各自职责
答案
请求链路:用户请求抵达Nginx → Nginx判断静态资源直接返回;PHP请求转发给PHP-FPM → PHP-FPM调配子进程执行PHP代码,查询MySQL/Redis → 结果原路返回Nginx再返回客户端。
Nginx:负责请求转发、负载均衡、静态资源缓存、限流;
PHP-FPM:管理PHP进程池,执行PHP脚本,管控进程数量、请求超时。
2 PHP-FPM常用调优参数以及调优思路
答案
核心参数:
pm进程管理模式:日常用dynamic动态模式;
pm.max_children最大子进程数,依据服务器CPU、内存配置;
pm.start_servers启动常驻进程;
pm.max_requests单个进程处理请求上限,到达后销毁重建,规避内存泄漏;
调优思路:内存充足就上调进程数;接口慢就调高请求超时时间;观察进程内存占用,设置合理max_requests。
3 Docker、CI/CD给PHP项目带来什么收益?简述自动化部署流程
答案
Docker打包运行环境,开发、测试、生产环境一致,解决环境不一致问题;容器资源隔离,扩容便捷。
CI/CD流程:代码提交Git触发流水线 → 执行代码静态检测、单元测试 → 构建PHP镜像推送仓库 → 测试环境部署验证 → 生产环境灰度发布。
五、加分项高阶面试题
1 Swoole/Workerman常驻内存框架对比传统PHP-FPM优势
答案
传统PHP-FPM每次请求初始化销毁进程,重复加载框架,性能损耗大;Swoole常驻内存,框架、数据库连接只初始化一次;支持协程、异步任务、websocket;适合秒杀、长连接这类高并发场景。
2 RabbitMQ/Kafka/Redis Streams消息队列适用场景,PHP如何消费消息
答案
- • Redis Streams:轻量级,小规模异步任务、订单通知;
- • RabbitMQ:可靠性高,支持死信队列、重试,适合订单、支付关键业务;
- • Kafka:吞吐量极高,日志、大数据埋点采集场景;
PHP消费方式:常驻脚本通过Swoole/CLI轮询队列,异步执行发短信、统计等任务,削峰填谷,抵御流量洪峰。
六、业务场景实操面试题(模拟工作真实需求)
场景题1:商品查询接口流量上涨,数据库CPU打满,请给出完整优化方案
参考答案
-
- 接入Redis缓存商品列表、详情,设置合理过期时间,拦截大部分查询请求;做好缓存穿透、雪崩防护;
-
- 优化MySQL:给查询条件建立联合索引,改写低效SQL、深分页;读写分离,查询走从库;
-
- Nginx层面做静态化、限流;热点商品页面静态缓存;
-
- 大促峰值接入消息队列削峰,延后非核心统计逻辑。
场景题2:基于CI框架开发一套JWT登录接口,简述实现步骤
参考答案
-
- 封装JWT工具库,放入CI的library目录;
-
- 登录控制器接收账号密码,校验数据库用户信息;验证通过后生成JWT令牌;
-
- 封装全局钩子,接口请求前校验请求头内token合法性、有效期;校验失败直接返回401;
-
- 强制下线场景将token存入Redis黑名单,钩子校验黑名单拦截失效令牌。
场景题3:线上出现慢查询,业务频繁报错数据库死锁,排查优化手段
参考答案
-
- 抓取死锁日志,查看互相锁住的SQL;统一业务更新数据的锁顺序;
-
- 缩小事务范围,把非数据库操作移出事务;降低事务执行时长;
-
- 为更新条件建立索引,避免行锁升级为表锁;
-
- 极端场景增加重试机制,捕获死锁异常后重试事务。