Skip to content

will2zuo/interview

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PHP

PHP 是什么

PHP("PHP:Hypertext Preprocessor",超文本预处理器),基于服务端创建动态网站的脚本语言

PHP数据类型

  1. 基本类型
    • 布尔型(boolean):true 和 false 两个值
    • 整型(integer)
    • 浮点型(float)
    • 字符串(string)
  2. 复合类型
    • 数组(array)
    • 对象(object)
  3. 特殊类型
    • 资源(resource):存放 PHP 外部数据,比如数据库、文件等
    • Null 类型:只有一个值 null,不能运算

常用的全局变量 $_SERVER

// 目录根目录
	$_SERVER['DOCUMENT_ROOT']
// 请求头部
	$_SERVER['HTTP_HOST']
// 用户 ip 地址
	$_SERVER['REMOTE_ADDR']
// 服务器的 ip 地址
	$_SERVER['SERVER_ADDR']
// 服务器主机名称
	$_SERVER['SERVER_NAME']
// 当前页面的前一页
	$_SERVER['HTTP_REFERER']
// 判断接收的数据是 post 还是 get
	$_SERVER['REQUEST_METHOD']

PHP 常用的超全局变量

// get 传送方式
	$_GET
// post 传送方式
	$_POST
// 可以接收到 get 和 post 两种方式的值
	$_REQUEST
// 引用全局作用域中可用的全部变量
	$_GLOBALS
// 上传文件使用
	$_FILE
// 系统环境变量
	$_SERVER
// 用于会话控制
	$_COOKIE
// 用于会话控制
	$_SESSION
// 服务器环境变量
	$_ENV

比较 include 和 require

  • include 引用不存在的文件会产生一个警告但是程序会继续执行;require 引用不存在的文件会导致一个致命的错误,程序停止执行
  • include 执行时文件每次都要进行读取;require 文件只处理一次,所以在引用的文件较大时,require 的效率更高

比较 get 和 post 两种传输方式(常规答案)

  • 数据传输大小: get 传输数据的大小是 2kb,而 post 一般是没有限制的,但是会受内存大小影响,一般通过修改 php.ini 配置文件来修改
  • 数据传输方式: get 是通过 url 传递参数的,在 url 中可以看到参数;post 是在表单中使用 post 方法提交
  • 数据安全性:get 参数可见,容易被攻击
  • 缓存: get 可以被缓存, post 不能被缓存

echo、print、print_r 的区别

  • echo 可以输出一个或者多个变量
  • print 只能打印一个变量
  • print_r 是一个函数,打印的是复合类型的变量,比如 数组、对象

传值赋值和引用赋值的区别

  • 传值赋值是将变量里的内容赋值一份,被赋值的变量不会被影响
  • 引用赋值是将两个变量指向同一个内存空间,只要其中一个变量改变就会影响到另一个变量

将 1234567890 改为 1,234,567,890

<?php
	$str = '1234567890';
	$strrev = strrev($str);
	$chunk = chunk_split($strrev, 3, ',');
	$result = strrev($chunk);
	$result = substr($result, 1);
	echo $result;

session 和 cookie 的区别

  • cookie 的数据存放在客户端,session 的数据存放在服务器
  • cookie 安全性较差,别人可以分析放在本地的 cookie 进行 cookie 欺骗(CSRF,跨站伪造请求攻击)
  • session 会在一定时间内保存在服务器上,当大量的 session 存在,会影响服务器的性能
  • 单个 cookie 保存的数据长度不能超过 4kb ,很多浏览器都限制一个网址最多能保存 20 个 cookie

如何设置 session 的过期时间

session_set_cookie_params()

PHP 常见的设计模型

  1. 策略模式
    • 是对象的行为模式,是对一组算法的封装,动态的选择需要的算法使用
  2. 工厂模式
    • 最常用的实例化对象模式,是用工厂的方法代替 new 操作的一种方式
  3. 单例模式
    • 保证某个类只有一个实例,而且自动实例化并向整个系统提供这个实例
    • 只实例化一次,避免大量的 new 操作,消耗系统和内存资源
    • 饿汉模式:在类初始化就自行实例化
    • 懒汉模式:只是在第一次调用的时候进行实例化
  4. 适配器模式
    • 将各种截然不同的函数接口封装成一个统一的 API
  5. 注册模式
    • 解决全局共享和交换对象
  6. 观察者模式
    • 当一个对象发生变化时,依赖它的对象都会收到消息,并自动更新(比如 事件)

数组常用的函数

array_merge(); // 合并数组
array_push(); // 往数组后追加
array_unique(); // 去重
array_keys(); // 获取数组的 key 值
array_values(); // 获取数据的 value 值
array_filter(); // 去空
in_array(); // 数组包含
count(); // 计算数组的长度

面对对象的特征

  1. 封装:只需要知道这个类是做什么的,不需要关心怎么实现
  2. 继承:子类可以继承父类的属性和方法,也可以重写或者新增属性和方法,增加了代码的可重用
  3. 多态:同一个类的不同对象使用同一个方法可以得到不同的结果,增加了灵活性和重用性

面对对象的五大原则

  1. 单一职责原则:一个类的功能单一
  2. 开放封闭原则:在扩展上是开放的,在更改性能方面是封闭的
  3. 替换原则:子类可以替换父类出现在父类可以出现的地方
  4. 依赖原则:具体依赖抽象,上层依赖下层
  5. 接口隔离原则:模块间要通过接口隔离开,而不是通过具体的类强耦合

PHP7 比 PHP5 性能高

  1. 变量存储字节看小,减少内存占用,提升变量的操作速度
  2. 改善数组结构,数组元素和 hash 映射表分配在同一内存,降低内存占用,提高了 cpu 的缓存命中率
  3. 改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高了执行效率

PHP7 和 PHP5 的区别

  1. 性能提升了 2
  2. 全面一致的支持 64 位
  3. 之前出现的致命错误,现在改为抛出异常
  4. 增加了空结合操作符
  5. 增加了函数返回类型声明
  6. 增加了标量类型声明
  7. 增加了匿名函数
  8. 移除了一些老的不再支持的SPAI(服务器端应用编程端口)和扩展(mysql mssql)
  9. 可以定义常量数组

php.ini 的优化

  1. 内存分配
  2. zend opcache 缓存操作码
  3. 设置文件上传大小
  4. 设置进程超时时间
  5. 处理会话(将会话存入缓存中而不是数据库)
  6. 缓冲输出(用最少的块输出最多的数据)

抽象和接口的区别

  1. 接口的访问控制必须是 public,抽象三种都可以
  2. 继承接口用 implement,继承抽象用 extends
  3. 声明接口用 interface,声明抽象用 abstract
  4. 接口没有构造函数
  5. 一个类可以继承多个接口,只能继承一个抽象

抽象

  1. 里面至少有一个抽象方法 abstract
  2. 只声明了方面,没有具体实现
  3. 被继承时,子类必须实现继承的所有方法
  4. 子类的访问控制必须比父类更加宽松

接口

  1. 定义的所有方法必须是公有的
  2. 用 interface 来定义接口,用implement 来继承接口
  3. 实现接口必须实现接口里的所有方法
  4. 可以继承多个接口,用逗号分隔

final 关键字

  1. 类声明 final 关键字,不能被继承
  2. 方法声明 final 关键字,不能被重写

yield 生成器

及时计算并产出后续值,不占用宝贵的内存,简单的迭代器

访问修饰符

public/protected/private

PHP 常用的魔术常量

1. __FILE__ // 完整文件路径或文件名
2. __LINE__ // 当前行号
3. __DIR__ // 文件所有目录
4. __FUNCTION__ // 函数名称
5. __CLASS__ // 类名称
6. __METHOD__ // 方法名称
7. __NAMESPACE__ // 当前命名空间

PHP 常用的魔术方法

1. __construct()
2. __destruct()
3. __isset()
4. __toString()
5. __get()
6. __set()
7. __unset()
8. __clone()
9. __debugInfo()

单点登录

session 共享来实现

权限系统设计

  • 用户
  • 角色
  • 权限
  • 用户角色
  • 角色权限

MySQL

Sql 语句应该考虑哪些安全性

  1. 防止 sql 注入,对特殊字符进行转义和过滤
  2. 用最小权限原则,最好不用 root 连接数据库
  3. 当 sql 运行出错时,不要把错误信息展示给用户

Sql 索引

  1. 普通索引
  2. 唯一索引
  3. 主键索引
  4. 复合索引

MySQL 索引的优缺点

  1. 优点
    • 加快查询速度
    • 可以加速表与表之间的连接
    • 在使用分组和排序进行检索的时候,可以减少查询中分组和排序的时间
    • 减少服务器对数据的扫描
    • 帮助服务器避免排序和临时表
    • 将随机 I/O 变成顺序 I/O
  2. 缺点
    • 占用磁盘空间
    • 对于写的操作,会降低速度
    • 创建和维护索引要消耗时间,这种时间随着数据量的增加而增加

MySQL 什么时候会产生临时表

  1. union 查询
  2. order by 和 group by 子句不一样
  3. distinct 加上 order by 查询
  4. from 中的子查询
  5. 表连接中,order by 的列不是驱动表中的

什么时候应该创建索引

  1. 经常需要搜索的列上,可以加快搜索的速度
  2. 做为主键的列上
  3. 经常用在 where 子句上的列
  4. 经常用做排序和分组的列
  5. 经常用在连接的列上,主要是一些外键,可以加快连接的速度

什么时候不需要创建索引

  1. 查询中很少使用的列
  2. 只有很少数据值的列
  3. 经常进行增删改的列,频繁更新的列
  4. 数据重复且平均分布的列,比如 男女

什么时候索引失效

  1. 条件中带有 or
  2. like 模糊查询中以 % 开头
  3. 如果列是字符串,没有用引号引用起来
  4. 使用函数或者四则运算
  5. 判断索引不是某个值 !=
  6. not in 查询

char 和 varchar 的区别

  • char 是定长,不管存储是否达到设定的值,都按设定的值存储,效率较高
  • varchar 是变长,存储的字符要比 char 长
  • char 的效率比 varchar 要高

优化 SQL 语句

  1. 尽量选择较少的列查询
  2. 在 where 后面频繁使用的字段加上索引
  3. 避免是用 select * 查询
  4. 避免在索引列上做运算,使用 not in 和 <> 等操作
  5. 合理的使用 limit
  6. 合适表分割,在查询较慢的地方使用 explain 分析查询语句

MySQL 中的事务(ACID)

  1. 原子性(A):一组 sql 要么全部成功要么全部失败
  2. 一致性(C):一致的从一种状态改变为另一种状态
  3. 隔离型(I):一个事务未完成之前不会被另一个事务读取
  4. 持久性(D):一旦食物提交,数据就会永久写入系统

MySQL 优化

  1. 选取合适的字段属性,字段的宽度尽可能的小
  2. 用连接查询来替代子查询
  3. 使用事务
  4. 使用外键
  5. 建立索引
  6. 优化查询语句
  7. 锁定表

数据库的三大范式

  1. 保证每一列都是不可再分的属性值,保证每一列的原子性,减少冗余
  2. 保证每一列都必须依赖主键
  3. 保证每一列都与主键有直接关系,而不是间接关系

数据库内部实现机制

MySQL 脏读/虚读/幻读解决方法

解决方法:通过事务的隔离级别(读未提交/读已提交/可重复读/串行化)

  • 脏读:指的是一个线程中的事务读取到另一个线程中未提交的数据(读已提交
  • 虚读:指的是一个线程中的事务读取到另一个线程中提交的 update 的数据(可重复读/加锁
  • 幻读:指的是一个线程中的事务读取到另一个线程中提交的 inster 的数据(串行化

数据库的存储引擎

  • MyISAM
    • 插入数据快,空间和内存使用比较低
    • 不支持事务
    • 数据存储在文件中
    • 支持表级锁
  • InnoDB
    • 支持事务/行锁/外键
    • 数据存储在共享表空间
    • 支持奔溃后修复
  • Memory
    • 所有数据在内存中,数据处理速度快
    • 对表的大小有要求,不能建立太大的表
    • 安全性不高
  • Archive
    • 适合查询和存储

悲观锁和乐观锁

  • 乐观锁:每次去拿数据都会认为别人不会修改数据,但是在更新数据的时候会判断在此期间有没有更新这个数据,适合多读的场景
  • 悲观锁:每次去拿数据都会认为别人会修改数据,所以每次都拿数据都会上锁,适合多写的操作

主从复制

1. 基本过程
  1. 主库在事务提交时会把数据更作事件记录在二进制文件 binlog 中,主库上的 sync_binlog 参数控制 binlog 日志刷新到磁盘中
  2. 主库推送二进制文件 binlog 到从库的中继日志 relay-log,之后从库根据 relay log 日志做数据变更操作
2. 主要的三个线程
  • Binlog dump 线程(主库)
  • I/O 线程(从库)
  • SQL 线程(从库)

当从库上启动复制,首先创建 I/O 线程连接主库,主库随后创建 Binlog dump 线程读取数据库事件发送给 I/O 线程,I/O 线程读取到事件数据之后更新到从库的中继日志 Relay log 中,之后从库的 SQL 线程读取中继日志中更新的数据库事件并应用

3. 三种复制方式
  1. 基于 SQL 语句的复制

    每条修改数据的 SQL 都会保存在 binlog 日志中

  2. 基于行的复制

    每行的数据变化都会记录到 binlog 日志中

  3. 混合复制模式

    基于语句和行混合使用

4. 复制的三种常见架构
  1. 一主多从

    一个主库多个从库,读写分离,主库主要负责写和实时性较高的读的操作,从库主要负责读取的操作

  2. 多级复制

    两个 master,多个 slave,其中一个 master 主要负责推送 binlog 日志到 slave

    优点:解决了主库的 I/O 负载和网络压力

    缺点:数据延时比较大(优化:master2 上选择 BLACKHOLE 引擎来降低延时,原理是 BLACKHOLE 表的数据不会写回到磁盘上,永远是空表,只用来记录 bin log 日志)

  3. 双主复制

    两个 master 库,适合 DBA 做维护,master1 和 master2 互为主从,写的操作访问 master1 ,读的操作访问 master1 或者 master2

5. 复制类型
  • 异步复制

    数据库事务提交之后,在主库写入 bin log 日志就可以成功返回给客户端

  • 半同步复制

    数据库事务提交之后,bin log 不仅要写在主库上,还要同时向从库推送,等到从库收到 bin log 日志后才会返回成功给客户端,如果从库长时间没有返回,则自动调整为异步复制

Nginx

负载均衡五种策略

  1. 轮询(默认)

    每个请求按时间顺序逐一分配到不同后端服务器,如果服务器 down掉,能自动剔除

  2. 权重(weight)

    指定轮询的几率,weight 和访问比率成正比

  3. ip_hash

    解决用户登录信息丢失的情况,每次请求都定位到同一个服务器

  4. Url_hash

    按 url 的 hash 结果来分配请求,使每个 url 定向到同一个对应的后端服务器

  5. 第三方 fair

    按后端服务器响应时间来分配,响应时间短的优先分配

反向代理

1. 理解

反向代理是指代理服务器接收 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端,此时代理服务器对外就变现为一个服务器

2.为什么使用反向代理
  • 可以起到保护网站安全的作用,因为任何来自 internet 的请求都必须先经过代理服务器
  • 通过缓存静态资源,加速 web 请求
  • 实现负载均衡

HTTP

url 访问网站的过程

  1. dns 解析,将域名解析为 ip 地址

  2. tcp 连接,tcp 的三次握手

    • 由浏览器发起,告诉服务器要开始请求数据了

    • 由服务器发起,告诉了浏览器准备好了接收数据,可以发起请求

    • 由浏览器发起,告诉服务器马上发送数据,准备接收

  3. 发送请求

  4. 接收响应

  5. 渲染页面

  6. 断开连接,tcp 的四次挥手

    • 由浏览器发起,告诉服务器请求报文发送完毕,准备关闭

    • 由服务器发起,告诉浏览器,请求报文接收完毕,准备关闭,你也准备关闭

    • 由服务器发起,告诉浏览器,响应报文发送完毕,你准备关闭

    • 由浏览器发起,告诉服务器,响应报文接收完毕,准备关闭

常见的 http 状态码

1xx:请求被接收

2xx:成功

3xx:重定向

4xx:客户端错误

5xx:服务器错误

301:永久重定向
302:临时重定向
401:权限不足,请求认证用户身份信息
403:拒绝访问
404:无法找到请求的资源
405:客户端请求中的方法被禁止
500:服务器内部错误
501:此请求方法不被服务器支持且无法被处理
502:网关错误
503:服务器繁忙
504:不能及时响应

osi 的七层模型 和 tcp/ip 四层关系

OSI 七层网络模型 TCP/IP四层概念模型 对应网络协议
应用层 应用层 HTTP、TFTP, FTP, NFS, WAIS、SMTP
表示层 Telnet, Rlogin, SNMP, Gopher
会话层 SMTP, DNS
传输层 传输层 TCP, UDP
网络层 网络层 IP, ICMP, ARP, RARP, AKP, UUCP
数据链路层 数据链路层 FDDI, Ethernet, Arpanet, PDN, SLIP, PPP
物理层 IEEE 802.1A, IEEE 802.2到IEEE 802.11

跨域怎么出现的,怎么解决跨域

出现:浏览器的同源策略,限制了一个源的文件或者脚本如何和另一个源的资源进行交互,如果没有同源策略,容易收到 XSS/CSRF 等攻击

解决

  1. jsonp,利用 <script> 标签没有跨域限制的漏洞,页面可以动态的得到其他源的 json 数据

    • 优点:兼容性好,可以用于主流浏览器的跨域访问问题
    • 缺点:仅支持 get 方法;不安全,容易遭受 xss 攻击
  2. cors 跨域资源共享,分为简单请求和复杂请求

    • 简单请求
    • 复杂请求,在正式请求之前,增加一次 http 查询请求
  3. nginx 的反向代理

    配置一个代理服务器做跳板机

  4. node 中间件代理(两次跨域)

    实现原理:就是服务器向服务器请求

Redis

Redis 和 memcached 的区别

  • redis 支持更加丰富的数据存储类型(string/hash/list/set/sorted set);memcached 只支持简单的 key-value 结构
  • redis 支持简单的事务
  • redis 支持数据持久型,可以将内存中的数据保存在磁盘中
    • 持久性:
      • RDB:在一定周期内,将内存中的数据以快照的形式保存到硬盘的二进制文件
      • AOF:redis 将每个收到的写命令都通过 write 函数追加到文件最后,redis 重启会重新执行文件中保存的写命令来在内存中重建整个数据库的内容
  • redis 只是单核,memcached 是多核

缓存雪崩/穿透

  • 雪崩:当缓存服务器重启或者是大量缓存在同一时间失效,给后台系统带来很大的压力,导致系统崩溃
    • 解决:
      • 当缓存失效时,增加锁来保证某个 key 只有一个线程操作数据库
      • 分散缓存失效时间
      • 做二级缓存
  • 穿透:大量请求绕过缓存直接请求数据库
    • 解决
      • 对一定不存在的 key 进行过滤,将可能存在 key 放在一个大的 bitmap 中,查询时过滤
      • 对空值也进行缓存,缓存时间短一点

单线程的 redis 为什么这么快

  • 纯内存操作
  • 单线程操作,避免了上下文切换
  • 采用的非阻塞 I/O 多路复用机制

Redis 的数据类型以及每种数据类型的使用场景

  • string:最常规的 set/get 操作,一般做一些复杂的技术功能的缓存
  • hash:存放结构化的对象
  • list:可以做简单的消息队列功能,可以做 redis 分页功能(lrange)
  • sort:存储的是不重复的值,适合做全局去重的功能
  • sorted set:集合中多了个 score 参数,可以做排行榜应用

Redis 的过期策略以及内存淘汰机制

过期策略:

  • 定期删除,没一段时间检查是否有过期 key
  • 惰性删除,使用时用到这个 key 的时候检查,过期就删除

淘汰机制

  • 从已设置过期时间的数据集中挑选最少使用的数据淘汰 -> volatitle-lru
  • 从已设置过期时间的数据集中挑选即将过期的数据淘汰 -> volatitle-ttl
  • 从已设置过期时间的数据集中任意选择数据淘汰 -> volatitle-random
  • 从数据集中挑选最近最少使用的数据淘汰 -> allkeys-lru
  • 从数据集中中任意淘汰 allkeys-random
  • 禁止驱逐数据,新写入会报错 no-enviction

other

如何处理高并发

  • 使用缓存
  • 优化数据库,提高数据使用效率
  • 负载均衡
  • 静态页面
  • 分布式部署,业务分离
  • 防盗链
  • 限制大文件下载
  • cdn 加速

怎么解决商品超卖和秒杀的问题

  • 加锁
  • 队列

API 安全接口解决方案

  • 非对称加密 rsa

    利用公钥和密钥,公钥传递数据,密钥解密获取数据

  • Md5 加密

  • 令牌 access_token

web 安全

  • XSS 攻击,跨站脚本攻击:往 web 页面插入可以执行的脚本代码,达到盗取用户信息或者侵犯用户隐私的目的
    • 攻击方式
      • 非持久型:诱骗点击 url 链接
      • 持久型:一般是表单提交
    • 防范
      • web 渲染的页面必须是来自服务端,做转义
      • 不要相信前端传递过来的数据,将所有字段转义后处理
  • CSRF 跨站伪造请求攻击
    • 攻击方式
      • 被攻击者登录了网站并保留了 cookie 信息
      • 访问了危险网站,并受引诱登录了之前的网站
      • 被攻击者没有做 csrf 防范
    • 防范
      • 正确的使用 get、post请求和cookie
      • 在非 get 中使用 token加密
      • 渲染表单加上 csrfToken,后端验证
  • SQL 注入:没有有效的过滤用户的输入,使攻击者向服务端提交了恶意的 sql 查询代码,导致原 sql 查询逻辑改变
    • 防范
      • 数据库最小操作权限
      • 内容必须转义
      • 尽量不要使用拼接 sql 语句
      • 不要将 sql 错误暴露给用户
  • DDOS 攻击,分布式拒绝服务,使用大量的请求资源导致资源过载,服务不可用
    • 防范
      • 网络上做好架构,负载均衡
      • 限制单个 ip 的访问次数
      • 关闭不必要的服务
      • 防火墙
      • 堆机器
  • dns 和 http 劫持
    • dns:被篡改访问的地址
    • http:被篡改被访问的内容

About

面试复习

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages