[PHP面试]问题探讨4

1. BTree的构建原理,查看

数据库不少引擎都是用BTree+做为索引的数据结构。数据库索引的主要是为了更快的查找和定位数据记录。 若是不考虑性能的话,可使用二叉树来搜索,根据索引的字段表来实现。 二叉树根据左右节点的log2n的复杂度的实现。 可是二叉树存在深度过高的状况,这样查找的深度不少,对于特殊的状况它的复杂都是N, 这样性能不高。 为了解决二叉树的高度问题,提出了M叉树,这个M叉树能够在一个节点上挂多个节点。 可是M叉树也存在一个问题,对于重建索引或者新建节点的时候,可能存在节点大批量的移动的状况。php

为了解决这个问题, 采用旋转的概念,也就是平衡树的概念。 经过旋转树的逻辑来处理操做。保持节点的平衡html

2. 计数的的概念引用,查看

每一个PHP的变量都会有一个计数器,存在一个zval的变量(在5.6版本以前是24个字节用于存储),除了包括变量和类型,还增长了2个字节一个is_ref的引用的数据。 第二个是是refcount,表示引用的计数器的数量和数据的逻辑处理。 全部的符号存在一个符号表中,其中每一个符号都有做用域(scope),那些主脚本(好比:经过浏览器请求的的脚本)和每一个函数或者方法也都有做用域。mysql

3. LRU的缓存实现

LRU的缓存逻辑的处理操做, LRU的思路一个链表的逻辑操做,在链表的表头操做插入, 若是有热点的数据,在表头进行插入, 若是链表的长度超过了固定的长度, 则擅长链表尾部的节点。nginx

这种算法比较简单,能够比较缓存高校的节点数据, 可是也可能会存在污染的状况。 好比一个访问很集中的状况,次数不少,可是在必定的时间段里面它使用低,这时候很容易出现缓存淘汰的操做。web

4. B树和B+树的区别[重点]

一、B+树的层级更少:相较于B树B+每一个非叶子节点存储的关键字数更多,树的层级更少因此查询数据更快;redis

二、B+树查询速度更稳定:B+全部关键字数据地址都存在叶子节点上,因此每次查找的次数都相同因此查询速度要比B树更稳定;算法

三、B+树自然具有排序功能:B+树全部的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。sql

四、B+树全节点遍历更快:B+树遍历整棵树只须要遍历全部的叶子节点便可,,而不须要像B树同样须要对每一层进行遍历,这有利于数据库作全表扫描。docker

B树相对于B+树的优势是,若是常常访问的数据离根节点很近,而B树的非叶子节点自己存有关键字其数据的地址,因此这种数据检索的时候会要比B+树快。数据库

5. memcache算法

分布式算法解析 主要是经过slab块来分配内存的算法逻辑, 对于分布式的算法逻辑操做采用:

  1. 余数算法逻辑 先获取hashcode的散列值,再除于服务器的台数,根据余数获取服务的节点数

  2. 散列算法。先算法memcache的散列值, 并将其分不到0~2^32次方的圆上。 若是超过2^32次方仍是找不到用户的话, 就将数据保存到第一台memcache上

6. 压力测试

环境:Ubuntu16.04 + Core I5 4核 + 8G内存 PHP7.0.10 脚本:ab -c 100 -n 10000 http://127.0.0.1:9501/ Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.2 0 2 Processing: 0 9 9.6 6 96 Waiting: 0 9 9.6 6 96 Total: 0 9 9.6 6 96

使用wrk来测试性能的状况,看下是否能够处理的能力操做 wrk -t4 -c8 -d60s http://192.168.1.10:8812/hello.php

wrk -t4 -c8 -d60s http://192.168.1.10:8812/hello.php

7. swoole的原理

主要是采用多路复用IO的逻辑来实现,而多路复用的IO是异步非阻塞的操做。 对于要回调的时间写入到红黑树树,这个是自由平等的二叉树,能够保证搜索的速度控制再logN的时间复杂度实现

深刻浅出网络编程与Swoole内核,查看

swoole协程原理是由事件驱动和栈切换两步共同完成的实现的。

8. http的三次握手和四次挥手

http的三次握手和四次挥手

四次挥手主要是客户端发送我要中断,服务端接受到指令的时候,发送你的数据我已经收到,而且发送我也没有数据要发送了, 最后客户端发送我已经收到了。

9. ZooKeeper &ZAB 协议&Paxos算法

Paxos 算法应该能够说是 ZooKeeper 的灵魂了。可是,ZooKeeper 并无彻底采用 Paxos算法 ,而是使用 ZAB 协议做为其保证数据一致性的核心算法。另外,在ZooKeeper的官方文档中也指出,ZAB协议并不像 Paxos 算法那样,是一种通用的分布式一致性算法,它是一种特别为Zookeeper设计的崩溃可恢复的原子消息广播算法。

ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。

10. 跳跃表

  1. 以顺序list做为基础结构
  2. 分多个block,每一个block第一个元素构成新的list,从而实现分层跳跃

11. 10分钟看懂Docker和K8S,查看

12. 遇到最复杂的事情?

13. 内网一个域名怎么解析多个ip

对于内网的域名的解析主要仍是经过负载均衡的处理的方式。经过访问DNS的域名,而后配置多个ip轮询做为负载均衡的策略,这样一个域名的方法,能够解析多个IP

14. 数据库事务隔离机制

事务隔离是数据库事务特征中的一种。 ACID,原子性,一致性,隔离性,持久性。

隔离机制主要是解决事务读写等级的状况。 通常常见的事务有问题有,

  1. 读未提交:能够读到未提交的数据。这是能够出现脏读,幻读

  2. 读提交:能够读到提交的数据。这个主要是读取数据的快照,能够解决脏读的问题,不可以解决不可重读的问题。 能够在读取提交的时候,同时进行更新了。 这样就不可以解决不可重读的问题。

  3. 可重读:主要是针对不可重读的问题,在读取的时候不可以进行更新操做。 也是mysql默认的事务级别。

  4. 串行化是事务的最高级别,就是一个个排队的执行。 性能比较低。

15. 怎么来保证服务高可用?

服务的高可用主要是来解决服务在使用过程当中的遇到问题可以自动容错和快速的恢复,同时系统随着业务增加也能够自动的扩展。

架构的常见问题:单系统的问题和系统间的问题。

单机的处理问题主要包括, 慢查询的问题,影响执行的性能甚至影响锁表和锁库,造成读取的I/O阻塞的,从而影响其性能。

大事务问题:事务执行的时间性阻塞,还有服务的请求超时和重试的问题。以及一些代码影响的系统的执行性能的问题,致使系统不可用或者响应时间太长。

除了单系统的问题,还有系统间的问题。

  1. 单机负载的问题,对于这样,采用负载均衡,保证不一样的机器可以均衡的分配机器的流量
  2. 熔断机制, 对于大量的使用,采用熔断机制,能够减小系统的稳定性问题。
  3. 限流,对于服务器性能进行预估,若是超过了服务去的性能和响应需求,则限制流量,保质核心业务的正常使用。
  4. 对于服务器资源进行隔离,而且对服务的资源进行更加细粒度话的控制,如采用docker对资源控制,对于进程和线程的隔离。
  5. 对于依赖问题。

检查的清单

大分类 小分类 check项目
基础组件依赖 缓存 挂了是否可用,跟其余系统共用
MYSQL 跟其余系统共用,慢查询,大事务,链接池监控情况,大表,读写分类,主从延时敏感
MQ 挂了是否可用, 依赖于消息发送的顺序
日志 创建日志不超过30%,使用日志的性能和稳定性
其余组件 是否有监控的系统来监控
依赖于外部环境 依赖于外部的上下游的状况
核心接口 性能问题
JVM 基本配置 堆栈的配置, 线程的监控和报警, 批量更新和缓存操做
容量预估 高峰期的CPU load,高峰期的内存, 高峰期的磁盘IO,高峰期的网卡,是否三倍冗余

16. 分库分表原则,查看

表拆分,大表拆成小表主要是解决减小表记录查询的时间,同时提升数据库的吞吐率,这就是所谓的分表

分表只是解决了查询性能和效率的问题,但对于数据库的并发处理无法带来质的提高, 面对高并发的读写, 当数据库master服务器没法承载写的操做压力时候,无论如何扩展slave服务器都没有意义。 因此要换个思路对于库进行拆分,提升库的写入能力,这就是所谓的分库。

分表包括水平拆分和垂直拆分,以及分区拆分

水平拆分的维度包括

  1. 水平切分的分片维度,如根据hash来拆分, 根据时间片来拆分

难点在事务的处理。

  1. 事务补偿机制,对于多段事务保持其最终一致性的实现逻辑
  2. 事务路由,不管使用上面哪一种方法实现分布式事务,都须要对分库分表的多个数据源路由事务,通常经过对Spring环境的配置,为不一样的数据源配置不一样的事务管理器(TransactionManager)。
  3. 分库分表引发的问题 问题一:扩容与迁移 在分库分表后,若是涉及的分片已经达到了承载数据的最大值,就须要对集群进行扩容。扩容是很麻烦的,通常会成倍地扩容。

Step1:按照新旧分片规则,对新旧数据库进行双写。

Step2:将双写前按照旧分片规则写入的历史数据,根据新分片规则迁移写入新的数据库。

Step3:将按照旧的分片规则查询改成按照新的分片规则查询。

Step4:将双写数据库逻辑从代码中下线,只按照新的分片规则写入数据。

Step5:删除按照旧分片规则写入的历史数据。

要避免在一个事务中同时修改数据库db0和数据库db1中的表,由于操做起来很复杂,对效率也会有必定的影响。请参考第三章的内容。

要避免在一个事务中同时修改数据库db0和数据库db1中的表,由于操做起来很复杂,对效率也会有必定的影响。请参考第三章的内容。

17. 开源监控系统梳理

  • zabbix,是一个web的界面提供分布式系统监控以及网络监视功能企业级的开源解决方案

  • zabbix能够收集各类网络参数, 保证系统的安全运营, zabbix支持两种方式,一种是zabbix server, 一种是zabbix agent。能够对端口监控,查看远程服务器和网络监视的状态。

  • zenoss Zenoss Core是开源企业级IT管理软件-是智能监控软件,他容许IT管理员依靠单一的WEB控制台来监控网络架构的状态和健康度。Zenoss Core同时也是开源的网络与系统管理软件。

  • HTOP 能够很清晰的查看网络的服务器状况和性能的状况。 包括IO,负载等数据状况。

  • 第三方服务器: 监控宝,能够主要是经过探针的方式,来监控多种服务。 不过对于链路监控支持的不是很好。

  • 全链路监控,也是系统在使用的。 Zipkin全链路监控,查看

经过统一的trace id来监控总体的链路服务状况,而且把这种服务运用平常的开发报警和日志的问题定位之中。

  • 错误日志的监控,可使用ELK的实现
  • grafana是很好的监控界面,能够配置指标显示监控的效果图形。

监控的主要内容:

  • 硬件监控
  • 系统监控
  • 应用监控
  • 网络监控
  • 流量分析
  • 日志监控
  • 安全监控
  • API监控
  • 性能监控
  • 业务监控

18. MQ对比之RabbitMQ & Redis ,查看

Redis是轻量级的消息队列,写入和出队列性能都比较高,

RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现的产品,RabbitMQ是一个消息代理,从“生产者”接收消息并传递消息至“消费者”,期间可根据规则路由、缓存、持久化消息。“生产者”也即message发送者如下简称P,相对应的“消费者”乃message接收者如下简称C,message经过queue由P到C,queue存在于RabbitMQ,可存储尽量多的message,多个P可向同一queue发送message,多个C可从同一个queue接收message

19. redis 热key问题

Redis缓存之穿透、雪崩、热Key问题,查看

热key问题及解决方案

产生的缘由: 用户消费的数据远大于生产的数据,如在突发的事件请求的数据大于远超过要写入的数据。就会形成热数据。

咱们通常采用缓存+过时时间来解决这个问题, 可是过时后容易集中打到缓存中。 集中出现的两个问题:

  1. 访问的数据是一个热点key
  2. 构建缓存须要时间

若是出现以上的问题, 就会出现缓存失效,大量的请求就会绕过redis缓存,而直接查询后端服务的压力,包括服务器和数据库的压力。

解决的方案:

  1. 对于热点的key设置永不过时,这是从物理上进行来设置不过时,而经过代码的改进来定时把任务进行修改key从而知足其效果数据的状况。
  2. 采用互斥锁的逻辑,只让一个线程来构建缓存,(查询数据库来重建缓存) 其余线程都要等待, 直到的第一个线程构建完成,直接查询缓存的数据信息。
缓存穿透问题

场景描述:缓存查询某个key的时候会从数据库中来读取,若是缓存层查询不到就会到查询存储层去读取数据,而后就失去了缓存的意义,在必定的程度上影响数据库压力。 解决方案: 对于不存在的key放到布隆过滤器(hash)的数据结构,把全部的可能存在的数据hash到一个bitmap里面, 对于不存在的数据会被这个bitmap进行过滤。若是查询一个数据为空, 对于为空的数据,咱们也会进行缓存的操做。 不过设置时间不超过5分钟。布隆过滤器重要是解决一个排序的数据,按照位来存储,其实构建的一个巨大的稀疏矩阵,对于数据过滤很是重要,对于遍历数据的时候若是出现0,则表示没有合适的数据,并进行过滤使用

缓存失效带来的雪崩问题

这种是来自于key的大面积失效,带来的后端服务查询数据的压力,从而致使数据库的压力。 一个简单的方法对于缓存的值都加上一个随机值,这样在访问的时候,不容易出现大面积的失效,从而查询后端的服务。

同时咱们能够在redis和数据库之间增长互斥锁(使用互斥锁(mutex key))或者查询队列,来缓解对数据的压力。 对于查询比较大的状况,能够经过队列的等待来解决。

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //表明缓存值过时
          //设置3min的超时,防止del操做失败的时候,下次缓存过时一直不能load db
		  if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //表明设置成功
               value = db.get(key);
                      redis.set(key, value, expire_secs);
                      redis.del(key_mutex);
              } else {  //这个时候表明同时候的其余线程已经load db并回设到缓存了,这时候重试获取缓存值便可
                      sleep(50);
                      get(key);  //重试
              }
          } else {
              return value;      
          }
 }

复制代码

20. lnmp高并发优化简介

增长work_rlimit_nofile和worker_connections数量,并禁用keepalive_timeout。

保持处理的链接数,并禁用keepalive的处理, nginx的配置参数主要集中在worker进程数量,使用的异步事件IO创建的链接数。也能够对nginx和php-fpm的优化配置,包括nginx 启动以后,对于php进程不够,能够设置pm.max_children来设置其进程数量。

php-fpm的调参数:动态和静态的状况下启动的线程和进程的数量的状况。

思路

内核层面:加大链接数,加快tcp回收

mysql层面:增大链接数, 关闭磁盘noatime, 使用SSD硬盘

php层面:用长链接,节省链接数 用内存缓存(memcached/redis),减轻mysql压力

注意 内存缓存适用于缓存复杂的sql查询。由于php与memcached也要创建tcp链接,因此简单的sql查询不须要用缓存。

21. 高并发环境在nginx和php层面要考虑注意什么

对在高并发的状况下,保持性能的高可用。 对于这样的状况下,nginx 层面根据机器的状况下计算下nginx的配置的worker数量和connections的数量,而且保证进程服务的稳定。
PHP主要是接受Nginx的fastcgi的报文。是不错的选择哦。

21.1 nginx配置踩过什么坑

22. 聊聊服务稳定性保障这些事 ,查看

22.1 稳定性的重要性
22.2 保障策略架构篇
  • 从架构层面保障稳定性,常见的策略包括限流,降级,隔离,超时,重试和集群等。

限制流量的大小,下降请求的流量,降级的目的很降级的目的比较简单(保证基础服务的可用,保证核心业务的可用,对于辅助的业务不进行访问正常), 第一个是保障服务器基本可用,第二个是保障服务的核心服务可用。降级是怎么一个思路呢?通常降级的每一个策略都是针对一个场景,预想特定场景下须要要解决什么问题;而后再梳理在这个场景下须要保留哪些核心基本服务;

  • 限流:限流常见的是漏桶算法和令牌算法。思路就是在把全部的流量是一个池子,流动的速率是稳定的,孔的高度也是稳定的。漏桶算法可以保证请求的负载时间长, 即每秒可以处理的请求数量。

  • 令牌算法:令牌桶算法也是有一个桶,可是桶不漏,桶里面放了一些令牌,每来一个请求就在桶里拿一个令牌,若是没有令牌它就能够等待,令牌满了就再也不往里面加令牌。这样方法基本上也能够达到一个限流的目的。令牌桶算法和漏桶算法的一个显著区别是漏桶算法在后端取请求量时,基本上漏的速率是同样的,可是令牌桶算法中后端部分能够有突发请求,若是桶满了,能够将桶里全部令牌都拿走。

  • 降级: 通常状况下,系统上线以后总会遇到一些不稳定状况,好比 redis 挂掉,甚至后端数据库 My SQL 挂掉。当出现不稳定状况以后,系统如何保证继续提供这些服务。

22.3 保障策略流程篇

对于作了好了基本的策略,咱们进一步采用, 线上的保证其稳定性。 Code Review: 来对代码的审核,提升代码的质量,而且对代码的进行整理。

压测: 压测的目的第一保持系统的稳定性。在高并发的是时候也能够保持系统的稳定性, 由于在必定的流量的基础上。检查性能的抗压能力, 检查系统的可以承受的QPS

灰度: 灰度目的是小范围试错,尽可能发现问题。只让某个地区的人先访问其特性, 遇到问题的及时反馈

监控: 自动化及时发现问题。监控的问题发现的事情。

全链路的监控服务,来保持系统的稳定性。

23. nginx配置踩过什么坑

Nginx的处理,

24. 其余问题

24.1 PHP7 opcache缓存清理问题,查看

opcache 一方面提升了php的性能,可是另外一方面,对于线上发版原本说,很容易出现缓存一直存在的状况。 考虑解决该问题的方式,主要集中在两个方面, 一个是设置opcache的失效时间,另外一个是经过手动或者自动更新文件,清理opcache的缓存。 对于能够时间使用调用opcache_reset 来重置缓存,也可使用发版本的rsync来更新同步缓存。