文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PHP面试宝典2023

2023-09-07 21:57

关注

php面试时经常会问一些理论性的问题,给大家整理了些,很多都是网上找的,难免有不严谨的地方,望请大家指正,共勉

mysql

innodb和myisam是存储格式:
innodb和myisam引擎的区别:
b+树和b树的区别:

innodb和myisam都是b+树实现,只是底层innodb用的是主键,myisam用的是随机是生成的。b+树=聚簇索引+非聚簇索引

b+树的优点:
  1. 单一节点存储更多的元素,使得查询的IO次数更少。
  2. 所有查询都要查找到叶子节点,查询性能稳定。
  3. 所有叶子节点形成有序链表,便于范围查询。
如何优化这句sql :

原:select uid from user limit 7000000,10:
新:select uid from user where id>700000000 limit 10;(第一个要扫描700000行)

hash索引的特点:

在等值的情况下比btree效率更高(重复的不多的情况下),不支持排序,需要回表查询

聚集索引和非聚集索引:

在非聚集索引通过name取得性别,就需要先拿到叶上的主键id,再拿着id去主键b+树的聚集索引里找

什么是索引覆盖:

联合索引是一棵树上,数据"骷大人,29",两棵树的话肯定又要走一遍流程了,需遵从最左原则

  1. 比如我用户表有三个索引,一个id的聚簇索引,一个身份证的唯一索引,一个用户名的普通索引,那么会建立3棵索引树,
  2. 第一个树的叶上有id=1 idcard=123 name=kudaren 等全部数据·(主键的聚集索引),第二棵树 idcard=123,id=1,第三棵树name=kudaren id=1·(两个普通的非聚集索引),第一个数可以拿到全部数据,而其他的需要拿着id再查一次(拿id去索引树查)
  3. 如果解决普通索引二次查找的问题,建立联合索引,name,和age ,select name,age from tabe where name=‘xx’
如何实现索引覆盖:
索引的分类:

按类型:unique(唯一),normal(普通)
按方法:btree(b+树),hash(哈希)
普通索引,全文索引,联合索引
主键索引,唯一索引(区别是后者允许为空)

如何合适的使用索引:
  1. 给经常用到的字段,增加索引,然后使用的时候也要避免比如is null,<>,like啊等操作,in的话尽量用between代替。
  2. 经常用到的组合搜索可以增加联合索引,秉持最左原则,越常用的字段越前面。比如你加的是a,b 搜索的时候却搜了b,a
  3. 用explain来看一下这条sql的索引应用效果。
  4. 当字段操作大于读取的情况也不建议加索引,主键建议设置成自增。
  5. 重复性较高的,比如性别1,2也不建议加索引。
索引会失效的情况:

网上说的between替换成in是错的,事实是如果between 1 and 100 是可以的,但 1 and 100000000000就不走了,优化器的聪明之处

  1. 联合索引没有秉持最左原则。
  2. 索引只用到了一部分,因为联合索引从左到右执行到< 或者>的区间查询的时候停止,那么建立了a,b,c,d,然后c做了一个区间查询,那么d就用不到,可以吧索引改成a,b,d,c
  3. sql中用了mysql的内置函数
  4. 用了%like,or等操作
以下情况索引是否使用:

现有user表,建立了联合索引a,b,c

问:select * from user where c=4 and b=6 and a=3;
答:mysql的优化器很聪明,会在内部转换sql,所以会用到索引

问:select * from user where a=3 order by c;
答:a索引用到了,c没用到,explain看到filesort,如c改成b不会有

字段的数据类型:
  1. 新增字段你的时候选择合适的数据类型,字段大小估计一个合适的不要选的很大,
  2. 用内置的日期和时间类型存储时间,用整型存储ip地址
  3. 应尽量将字段设置成not null,null对索引不友好,用0或者空字符来替代。
聚合函数执行顺序:

SQL:SELECT age,count(age) as enum FROM people where age<>‘’ GROUP BY age HAVING enum>100 order by enum desc;
顺序: where group having order (先where运算,得到符合条件的数据,进行group操作,再having筛选group的值,最后排序)

数据库设计三大范式:
  1. 第一范式(1NF)(每一列都不可分割)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。
  2. 第二范式(2NF) (完全依赖于主键) 简而言之,第二范式就是属性完全依赖于主键。
  3. 第三范式(3NF) 任何字段不能由其他字段派生出来,它要求字段没有冗余
锁的分类:
  1. 通过锁定范围:行级锁(innodb)和表级锁(myisam)
  2. 通过锁定类型:排它锁和共享锁
    排他锁:[for update] innodb除select的操作都会排它锁]锁定后,用select还是能读取,但是无法再给数据加共享锁和排它锁(一行不能同时存在两个锁)
    select * from table where xxx for update
    共享锁:[ lock in share mode] 锁定后,除了排它锁,其他都可以加上
    select * from tb_test where id = 1 lock in share mode;
    (InnoDB 引擎中的四种隔离级别就是用 排他锁 + 共享锁 实现的)
mysql的执行过程:

server层

存储引擎层

垂直分表和水平分表:

垂直分表:
把不常用的字段单独放在一张表;
把text,blob等大字段拆分出来放在附表中;
经常组合查询的列放在一张表中;
实现方式:修改sql

水平分表:
比如原表有100万行数据,那么拆分成一行25万的四个表
实现方式:union all

sql中时间转换的函数:

redis

redis过期策略:
抢红包的大概思路:

类似使用队列防止超卖的思路。
比如一个10元,5个红包,那么push5次2到队列里(随机红包将2经过计算就好),后面抢的时候先pop就好。

你pop 了redis 列表里的数据之后进程挂了怎么办:
  1. 增加一个备用队列,主队列消息出队后加入备用队列,在消息被成功 消费后,从备用队列剔除。
  2. 通过使用专门的消息队列工具如rabbitmq,它有个消息确认机制(Acknowlege)。当消费者处理完消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。
    自动ACK:消息一旦被接收,消费者自动发送ACK(不太重要)
    手动ACK:消息接收后,不会发送ACK,需要手动调用(重要)
用 redis 实现的分布式锁不适合高并发情况,如何优化:

redis实现分布式锁

为什么redis是单线程:

因为cpu不是redis的瓶颈,有可能是内存,还可以避免不必要的上下文切换和竞争关系

memcached 与 redis 区别:

redis 支持持久化,字符类型更丰富,Memcached是多线程

redis使用场景
缓存失效的情况:
  1. 缓存击穿:
    原由:缓存中没有但数据库中有的数据
    解决办法:加锁或设置数据不过期

  2. 缓存穿透:
    原由:查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询。
    解决办法:布隆过滤或缓存空数据

  3. 缓存雪崩:
    原由:同一时间大批缓存过期,导致大量的请求进入mysql
    解决办法:缓存时间设置的长些的情况下,加一个随机值,防止同时大量过期

高并发抢购如何实现高可用,不会出现 502,不会出现超卖的情况:

redis防止超卖
redis防止超卖

使用锁的方式+mysql事务,如使用redis的sex配合nx ex来实现锁,然后走队列判断库存,事务减库存。

常用的使用场景:

简单的缓存
分布式锁
队列
发布/订阅
时间序列/排行榜
用户token
数据共享
接口限流
防超卖
布隆过滤
防超卖

redis过期和删除策略:
redis各命令如何实现原子性:

pipeline或lua脚本


其他

数组和对象的区别:
  1. 数组是普通变量,拷贝副本,只有引用传递后才会改变原先的值,而对象就是引用类型。
  2. 单纯存数据用数组,如果要进行自定义的操作,则对象。
API请求如何保证数据不被篡改:

使用https,或在URL上加上一个sign秘钥

GIT常用的命令:
restful接口规范:

在接口名里取消add,get等动词,转换成请求类型来表示,比如 post 创建数据、put修改数据、get获取数据、delete删除数据。

公钥私钥的原理:
  1. 持有公钥的一方(服务器)在收到持有私钥的一方(客户端)的请求时,甲会在自己的公钥列表中查找是否有乙的公钥,如果有则使用一个随机字串使用公钥加密并发送给乙。
  2. 乙收到加密的字串使用自己的私钥进行解密,并将解密后的字串发送给甲。
  3. 甲接收到乙发送来的字串与自己的字串进行对比,如过通过则验证通过,否则验证失败。
微信支付的实现方式:
  1. 先创建一个订单,然后拿着单号,appid,支付价格,回调地址等参数请求腾讯的接口,获得sign等信息。
  2. 将sign提供给前端唤醒支付功能
  3. 设置对应的回调地址,写上订单状态变更的逻辑代码,请求成功后会自动请求回调地址
redis队列数据丢失怎么办:

消费者把数据从队列取出来的时候,先放入备用队列,等业务都处理完后再从备用队列删除(备用队列一个单独的脚本判断过期时间,如过期则放回主队列)

http的状态码
错误级别:
cgi 和 fastcgi 区别:
跨域的解决方案:
什么是布隆过滤器:

是一种数据结构,用来判断一个元素是否在另一个元素中,相比hash表,他的有点是相对开销小,缺点就是有一定的误差,它说有那可能有,它说没有,那一定没有。
使用场景:网络过滤判断黑名单,缓存穿透的问题

拍下减库存和付款减库存的使用场景:
常见的加密:

单向全是通过hash,其特点不可逆,长度相等。password_hash函数默认使用使用bcrypt加密,password_verify函数比对是否一样

简述高并发网站解决方案:

A、前端优化(CND加速、建立独立图片服务器)
B、服务端优化(页面静态化、并发处理[异步|多线程]、队列处理)
C、数据库优化(数据库缓存[Memcachaed|Redis]、读写分离、分库分表、分区)
D、Web服务器优化(负载均衡、反向代理)

常见的提高服务安全性的方法:
  1. 错误日志直接打印出来了
  2. 某些页面比方说忘记密码被人恶意调用, 解决方法,增加验证码等机制
  3. 某些使用量特别高的功能高峰期拖垮服务器,增加缓存,或者拉出来放在单独的服务器
  4. 服务器弱密码,改成秘钥增加白名单
对于大并发业务的防护,有什么看法:

我觉得并发是防止单个时间大量流量涌入,导致服务器或者数据库挂掉,我觉得数据库比服务器更脆弱,(在服务端构建一个屏障)防止前端请求直接涌入数据库。

  1. 在web服务器优化端:做负载均衡,将图片放在cdn服务器。
  2. 在数据库端:做数据库缓存,读写分离。
  3. 服务端优化:页面静态化,数据做缓存(或参与的人太多了等,可直接用incr)
幂等性:

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用(不会出现两条)。

incluce和require的区别:
final和abstract

关键字final:
用于类、方法前,不可被继承,不可被覆盖(如果不想某个类或方法不想被继承)

抽象类abstract:
用于类,方法前
一个类中至少有一个抽象方法,有一个抽象方法整个就是抽象类
抽象方法前面必须加abstract
抽象方法不允许有{}
子类中所有的抽象类都必须重写定义一遍
只允许被继承,不能实例化
(上面两个是反过来的)

接口interface(抽象类的一种):
整个类都是只有名字的,比如put() get()后面通过继承来写入具体的操作代码(如架构师不想我们瞎起名字,定义好了规范,我们继承)
只能能通过implements继承
接口中定义的所有方法都必须是公有的,这是接口的特性。

solr 没有降低 db 压力的作用,它不是缓存,你怎么不用 redis?redis 更好?

我感觉redis适合做缓存系统,而solr更适合做搜索引擎,它支持的搜索条件会更多

常见的psr规范有哪些:

psr2代码标准(psr1的升级),psr3日志标准,psr4自动加载标准(替换psr0)

消息中间件的用途:

解耦、异步、削峰

大屏数据显示,需要聚合统计的数据量太大,mysql 查询太慢。有什么解决方案:
  1. 分析sql,增加合理的索引
  2. 需要统计的数据每次增加或减少时都给他算出来存好,
  3. 取巧,刷新页面时实际上不显示这个数,而是显示一个“点击显示数据”的按钮。
session和cookie的关系:

session和cookie之间是通过 C O O K I E [′ P H P S E S S I D′ ] 来联系的,通过 _COOKIE['PHPSESSID']来联系的,通过 COOKIE[PHPSESSID]来联系的,通过_COOKIE[‘PHPSESSID’]可以知道session的id,从而获取到其他的信息。

什么是OOP编程:

降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性

ORM代表什么:

ORM代表对象关系映射

array_map与array_walk区别:
Trait类的使用:
use App\Traits\Redis\RedisTrait;class FoolsDay2023Push{    use RedisTrait;   public function test(){        $this->redis->get('name');//这个方法实际在RedisTrait中,但可以直接$this->关键词调用    }

来源地址:https://blog.csdn.net/xiantianga6883/article/details/129392517

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯