PHP高级工程师面试题

准备

  1. 自我介绍:说上家公司负责的项目或者浓缩简历。
  2. 简历项目经验层次php

    • 利用什么技术
    • 实现了什么功能
    • 遇到什么问题
    • 达到类什么结果
  3. 指望薪资
  4. 应用型的问题:要记得站高看远、架构分层
  5. 涉及管理经验及自身对相项目管理的理解

知识点列表

1、Redis

  1. redishtml

    • 应用场景前端

      • string
      • hash
      • set:去重
      • zset: 排行榜
      • list:(阻塞队列、消息通讯)
      • HyperLogLog:大量统计(非精确)
    • 内部数据结构node

      • dict:key[string] VS value (redis obj);拉链法解决冲突(同php);装载因子(哈希表已保存节点数量 / 哈希表大小)超过预约值自动扩充内, 引起(增量式)rehashingmysql

        • 根据ht[0]建立一个比原来size大一倍(也可能减小)的hashtable,
        • 从新计算hash和index值,根据rehashindex逐步操做
        • 到达必定阈值(ht[0]为空)操做中止
        • 期间响应客户端react

          • 写操做:写到新的ht[1]
          • 读操做:先读ht[0],再读ht[1]
      • sds:simple dynamic stringlinux

        • string的底层实现为sds,可是string存储数字的时候,执行incr decr的时候,内部存储就不是sds了。
        • 二进制安全binary safe(5种类型的header+falgs获得具体类型,进而匹配len和alloc)
      • robj:redis object,为多种数据类型提供一种统一的表示方式,同时容许同一类型的数据采用不一样的内部表示,支持对象共享和引用计数。nginx

        • sds
        • string
        • long
        • ziplist
        • quicklist
        • skiplist
      • typedef struct redisObject {
                    unsigned type:4;【OBJ_STRING, OBJ_LIST, OBJ_SET, OBJ_ZSET, OBJ_HASH】
                    unsigned encoding:4【上述type的OBJ-ENCODING _XXX常量,四个位说明同一个type多是不一样的encoding,或者说同一个数据类型,可能不一样的内部表示】;
                    unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */
                    int refcount;
                    void *ptr【真正指向的数据】;
                    } robj
    • OBJ_ENCODING_laravel

      • stringgolang

        • OBJ_ENCODING_RAW,表明sds ,原生string类型
        • OBJ_ENCODING_INT,long类型
        • OBJ_ENCODING_EMBSTR ,嵌入
      • OBJ_HASH

        • OBJ_ENCODING_HT,表示成dict
        • OBJ_ENCODING_ZIPLIST,hash用ziplist表示
      • OBJ_SET

        • OBJ_ENCODING_INTSET,表示成intest
        • config

          • set-max-intset-entries 512【是整型并且数据元素较少时,set使用intset;不然使用dict】
      • OBJ_ZSET

        • OBJ_ENCODING_SKIPLIST,表示成skiplist

          • 思想:多层链表,指针来回查找,插入和更新采起随机层数的方法来规避
          • config

            • zset-max-ziplist-entries 128
            • zset-max-ziplist-value 64
      • OBJ_LIST

        • OBJ_ENCODING_QUICKLIST
        • config

          • list-max-ziplist-size -2
          • list-compress-depth 0
    • 内部结构实现

      • string
      • hash(两种encoding,根据下面的config)

        • ziplist
        • dict
        • config

          • hash-max-ziplist-entries 512【注意单位是“对儿”】
          • hash-max-ziplist-value 64【单个value超过64】
      • set
      • zset
      • list

        • quicklist
        • 定义:是一个ziplist型的双向链表
        • 压缩算法:LZF
    • zset如何根据两个属性排序?好比根据id和age

      • 能够用位操做,把两个属性合成一个double
      • 用zunionstore合并存储为新的key,再zrange
    • redis是如何保证原子性操做的?

      • 由于他是tm单线程的!(ps:mysql是多线程)
      • 在并发脚本中的get set等不是原子的~
      • 在并发中的原子命令incr setnx等是原子的
      • 事务是保证批量操做的原子性
    • 主从复制过程:

      1. 从服务器向主服务器发送sync
      2. 主服务器收到sync命令执行BGSAVE,且在这期间新执行的命令保存到一个缓冲区
      3. 主执行(BGSAVE)完毕后,将.rdb文件发送给从服务器,从服务器将文件载入内存
      4. BGSAVE期间到缓冲区的命令会以redis命令协议的方式,将内容发送给从服务器。
    • 特性:

      • 单线程,自实现(event driver库,见下面四个io多路复用函数)
      • 在/src/ae.c中:宏定义的方式
      • /* Include the best multiplexing layer supported by this system.
                 * The following should be ordered by performances, descending. */
                        #ifdef HAVE_EVPORT
                        #include "ae_evport.c"
                        #else
                            #ifdef HAVE_EPOLL
                            #include "ae_epoll.c"
                            #else
                                #ifdef HAVE_KQUEUE
                                #include "ae_kqueue.c"
                                #else
                                #include "ae_select.c"
                                #endif
                            #endif
      • io多路复用,最经常使用调用函数:select(epoll,kquene,avport等),同时监控多个文件描述符的可读可写
      • reactor方式实现文件处理器(每个网络链接对应一个文件描述符),同时监听多个fd的accept,read(from client),write(to client),close文件事件。
    • 备份与持久化

      • rdb(fork 进程dump到file,可是注意触发节点的覆盖问题,致使数据不完整)

        • 手动 save bgsave
        • 自动 conf:save 900 1 save 300 10 save 60 10000 dbfilename dump.rdb
        • 优势:对服务进程影响小,记录原数据文件方式便于管理还原
        • 缺点:可能数据不完整
      • aof(相似binlog)

        • appendfsync no
        • appendfsync everysec
        • appendfsync always (每执行一个命令)
        • 优势:数据最完整,支持rewrite
        • 缺点:文件相对rdb更大,导入速度比rdb慢
    • 过时策略:

      • 定时过时:时间到了当即删除,cpu不友好,内存友好。
      • 惰性过时:访问时判断是否过时:cpu友好,内存不友好
      • 按期过时:expires dict中scan,清除已过时的key。cpu和内存最优解
    • 内存淘汰机制

      • 127.0.0.1:6379> config get maxmemory-policy

        1) "maxmemory-policy"
        2) "noeviction"
        127.0.0.1:6379>
      • noeviction:新写入时回报错
      • allkeys-lru:移除最近最少使用的key
      • allkeys-random:随机移除某些key
      • volatile-lru:设置了过时时间的key中,移除最近最少使用
      • volatile-random:不解释
      • volatile-ttl:设置类过时时间的键中,有更早过时时间的key优先移除
    • redis队列特殊关注(可能坑)之处

      1. 队列可能丢东西

        • 好比redis挂了,producer没有中止,可是队列数据没法写入(除非同步落地到mysql)
      2. 队列的consumer 须要手动处理commit协议

        • 若是consumer处理完,表示真正完成
        • 若是没有处理完?放回队列?直接丢弃?
      3. 事件重放机制不支持

        • 好比consumer消费错了,那能不能将队列回放呢再次处理呢?
      4. 队列最大长度及过时时间

        • 若是producer远大于consumer,撑爆了怎么办
        • 若是comsumer 一直没有处理,producer的数据如何处理
      5. exactly once
      6. 单机锁sennx或者基于set众多参数没问题,集群下可利用tag机制
      7. 如何保证业务执行时间超过锁的过时时间,而引发误删除操做。答案是能够加一个惟一标识
    • vs memcache

      • memcached

        • 优点

          • 多线程(listen & woker),利用多核
          • round robin
          • cas(check and set,compare and swap)
        • 劣势

          • cache coherency、锁
          • key大小有限制(1M)
        • 特色

          • 内存预分配:slab+trunk
      • redis

        • 优点:

          • 本身封装了一个AEEvent(epoll+select+kqueue),io多路复用
          • 丰富的数据结构(对内+对外)
          • 良好的持久化策略(rdb +aof)
          • 单机可部署多实例,利用多核
        • 劣势:

          • 排序、聚合cpu密集操做会等影响吞吐量
          • key 大小最大为1g
    • more | other

      • redis ziplist与普通双向链表的区别:普通的链表每一项都占用独立的一块内存,各项之间用地址指针(引用)链接起来,这样会致使大量碎片。而ziplist是将表中每项放在先后连续地址空间内,并且对值存储采起变长编码。
      • redis msetnx对应的del,能够采起lua脚本保证get del的原子性
      • redis 单线程如何实现阻塞队列?

        • 阻塞是阻塞client,又不是阻塞server,server不发数据,client不就阻塞住了,当client想要阻塞在某个key上,server会把这个client放到一个block list里,等key发生变化,就send数据给client。
      • redis 阻塞队列的时间设置实现?

        • blocklist里只存了列表,这个timeout存在链接上,靠serverCron来遍历检测,每次遍历5个,
        • 高性能的方案是小堆或者红黑树或者时间轮实现的定时器结构,epoll wait那块timeout参数就设置成下次超时时间
        • 每次poll loop里除了处理io事件,再把定时器的数据结构里处理下,堆和红黑只要检测到一个未超时就能够break了,时间轮这是当前槽都触发了就行
        • 每次检测5个这种比较折中,由于他场景不是大量并发的服务器,rds cli的链接数量毕竟使用者内部可控,并且不须要精确打击,只要保障相对能及时清理就行,redis的网络部分相对比较简单,业务场景可控,足够了
      • redis集群状况下如何作到两个key必hash到一个节点?用{}

2、MySql

  1. mysql

    • 索引

      • 物理存储

        • 聚簇索引
        • 非聚簇索引
      • 数据结构

        • B+树
        • hash
        • fulltext
        • R-tree
      • 逻辑角度

        • 惟一索引 unique
        • 普通索引index
        • 主键索引 primary key
        • 全文索引 full index(myisam)
        • 复合索引 (最左前缀原则)

          • 相似 where a and b and c a b c 问题
          • 联合索引(a,b,c) 可以正确使用索引的有(a=1), (a=1 and b=1),(a=1 and b=1 and c=1)(b=1 and c =1
    • 引擎类型

      • myisam
      • innodb
      • 区别:

        1. myisam采用非汇集索引,innodb采用汇集索引
        2. myisam索引myi与数据myd文件分离,索引文件仅保存数据记录指针地址。
        3. myisam的主索引与辅助索引在结构上没区别,而innodb不同:innodb的全部辅助索引都引用主索引做为data域。
        4. innodb支持事务,行级锁。myisam不行。
        5. innodb必须有主键,而myisam能够没有。
      • 相同点:

        • 都是b+tree 索引
    • 存储

      • innodb

        • clipboard.png
        • clipboard.png
        • 数据被逻辑的存在tablespace,extend(区)中有多个page,page(默认16kb)里放row(每一行,大概每一个page放2-200行记录)
        • .frm:table's format
        • .ibd:table data & associated index data
        • ubunut的frm文件和ibd文件可在目录root@udev:/var/lib/mysql# ls中查看,下图为innodb行格式,由下到上,均向上兼容
        • clipboard.png

          • Antelope 羚羊 对存放bolb或者大varchar存储极长的数据时,将行数据的前768字节存储在数据页中,后面经过偏移量指向溢出页。

            • compact 紧凑的
            • redundant 多余的
          • Barracuda 梭鱼

            • antelope对存放blob的数据彻底溢出,在数据页中只存在20个字节的指针,实际数据放在bolb page
            • compressed
            • dynamic
            • more
      • myisam

        • frm(与innodb通用),在磁盘的datadir文件
        • myi
        • myd
    • 事务

      • 原子性atomicity
      • 一致性consistency
      • 隔离性lsolation
      • 持久性durability
    • 分表数量级

      • 单表在500w左右,性能最佳。BTREE索引树 在3-5之间
    • 隔离级别

      • 事务的隔离性是数据库处理数据的基础之一,隔离级别是提供给用户在性能和可靠性作除选择和权衡的配置项目,如下四种状况都有一个前提(在同一个事务中
      • 1.read_uncommited:脏读,未提交读。不加任何锁,能读取到其余会话中未提交事务修改的数据,主流数据库几乎没有这么用。的见下图
      • clipboard.png
      • 2.read_commit:RC,不可重复读,已提交读。注意这个与1的区别是,读取不加锁,可是数据的写入、修改和删除是须要加锁的,而1是啥锁都不加。啥🔒都不加。只对记录加记录锁,而不会在记录间加间隙锁。因此容许新的记录插入到被锁定记录的附近,因此屡次使用查询语句时,可能获得不一样的结果,non_repeatable_read,见下图,第二个事务修改了id=1的数据后,第一个事务再次读取的时候结果不同。这就是不可重复读,即两次结果不同。
      • image.png
      • 3.repeatable_read【默认级别】:RR,可重读,幻读,返回第一次的查询的快照(不会返回不一样数据)。虽然事务2提交了更改,可是事务1仍然读到的是事务2未修改的状态。见下图
      • image.png
      • 4.serialize:解决了幻读,可串行化。幻读和可重复度读的区别在于致使幻读的是其余事务的insert。这样会引发第一个事务莫名其妙的多出来一条数据。幻读主要是依靠读锁写锁相互独立(互斥),可是会极大的下降并发能力。
    • 索引机制(算法)

      • hash
      • b+tree(m阶b+tree)

        • 全部数据保存在叶子节点,有k个子树的中间节点包含有k个元素
        • 全部叶子节点包含了所有的元素信息,及指向这些元素记录的指针,且叶子节点自己依关键字的大小自小而大顺序连接
        • 全部的中间节点元素都同时存在于子节点,在子节点元素中都是最大(或最小)元素(或者说:每个父节点的元素都出如今子节点中,是子节点的最大或者最小元素)
        • 插入的元素,要始终保持最大元素在根节点中,再次说:全部的叶子节点包含了全量元素信息。每一个叶子节点都带有指向下个节点的指针,造成了有序链表
        • clipboard.png
    • b-tree【不要念成b减tree,-只是个符号】

      • 内存操做(单一节点数量不少时,注意并不比二叉查找树数量少,只是速度比硬盘要快)
      • 自平衡
      • 左旋、右旋
      • mongoDB用的是balance tree
      • 特色(m阶的B树)

        • 根节点至少有两个子女
        • 每一个中间节点都包括k-1个元素和k个孩子(m/2<=k<=m)
        • 每一个叶子节点都包括k-1个元素,(m/2<=k<=m)
        • 全部的叶子节点位于同一层
        • 每一个节点中的元素从小到大排序,节点当中k-1个元素正好是k个孩子包含元素的值域划分
    • b+与b-区别

      1. b+中间节点没有卫星数据,而b-tree有卫星数据(能够理解为key+data的二维数组),因此前者一样大小能够容纳更多的节点元素。这样又致使了b+比b更“矮胖”,更进一步减小了io查询次数。很好的解释了下面这句话:在cluster index(汇集索引中),叶子节点直接包含卫星数据;在非汇集索引中nonclustered index中,叶子节点带有指向卫星数据的指针。
      2. b-只要查找到匹配元素,直接返回,网络匹配元素处理中间节点仍是叶子节点。而b+查询必须查找到叶子节,相对于b-,b+无需返回上层节点重复遍历查找工做,因此得出b-查找并不稳定,而b+是稳定的,b+树经过双向链表将叶子节点串联起来,基于空间换时间。目的就是支持倒叙和顺序查询。
      3. 针对范围查询,b-须要n次中序遍历,而b+只须要经过子节点链表指针遍历便可。
    • 种类

      • optimistic lock乐观锁(并不是真正的锁,是基于版本号基础的先尝试再更改,loop and try)
      • 特色:不会真死锁,必定条件下有较高的冲突频率和重试成本,可是相对悲观能够有更好的并发量
      • pessimistic lock悲观锁

        • 为了保证事务的隔离性,就须要一致性锁定读。读的时候要加锁,防止其余事务再次更改,修改的时候也要加锁,其余事务没法读取。主要就是依靠数据库的锁机制来实现,同时缺点很明显,就是会带来性能的开销,并发的减小。
    • innodb的MVCC(Multi-Version Concurrency Control)

      - 翻译成中文叫~~心理医生~~ ,多版本并发控制,适用于行锁的、事务性的数据库模型。
      - 适用于innodb的rc和rr级别,由于可串行化涉及到锁表
      - 实现思想是在每行增长一个create_verison和delete_version字段
      - update 是插入一个新行,先保存当前版本号到旧行的delete_version,且新建行的new_create_version也就是delete_version
      - delete操做就是直接标记delete_version
      - insert的时候,就是保存至create_version
      - selete的时候能够这样
          - 读delete_version为空的
          - 大于当前事务版本号的
          - 建立版本号<=当前事务版本号的
    • 粒度划分

      • 行锁
      • 表锁
    • 意向锁 intention lock(表级锁)

      • 场景:A对表中一行进行修改,B对整个表修改。若是没有如下的两个锁,B将对全表扫描是否被锁定。反之,A能够对某行添加意向互斥锁(表级),而后再添加互斥锁(行级),而后B只须要等待意向互斥锁释放)
      • 意向共享锁
      • 意向互斥锁
    • 共享锁shard lock 读锁(行锁)
    • 排它锁exclusive lock 写锁(行锁)
    • 锁的算法

      • record lock:加到索引记录上的锁,若是经过where条件上锁,而不知道具体哪行,这样会锁定整个表
      • gap lock:间隙锁某个区间的锁定,对索引记录中的一段连续区域的锁。
      • next-key lock:行锁和GAP(间隙锁)的合并,next-key锁是解决RR级别中 幻读问题的主要方案。能够搜索关键字 快照读(snapshot read)和当前读(current read)去了解~
    • 死锁:
      clipboard.png
    • 注意区分 deadlock VS lock wait timeout
  2. 分库分表
  3. 主从
  4. ACID
  5. 覆盖索引(复合索引)

    • 定义:包含两个或多个属性列的索引称为复合索引。若是查询字段是普通索引,或者是联合索引的最左原则字段,查询结果是联合索引的字段或者是主键。这种就没必要经过主键(汇集索引再次查询)
    • 目的:减小磁盘io,不用回表
    • b+树索引
  6. 汇集索引cluster index 通常为primary key

    • 定义:按照每张表主键构建一棵B+TREE,叶子节点放的整张表的行记录数据
    • 与之相对应的是辅助索引(secondary index)
    • innodb存储引擎支持覆盖索引,即从辅助索引中能够查到查询记录,而不须要查询汇集索引中的记录。
    • b平衡树+树索引
      clipboard.png
    • 上图对应的表结构:
    • CREATE TABLE users(
              id INT NOT NULL,
              first_name VARCHAR(20) NOT NULL,
              last_name VARCHAR(20) NOT NULL,
              age INT NOT NULL,
              PRIMARY KEY(id),
              KEY(last_name, first_name, age)
              KEY(first_name)
    • 一张表必定包含一个汇集索引构成的b+树以及若干辅助索引构成的b+树
    • 每次给字段建一个索引,字段中的数据就会被复制一份出来。用于生成索引,(考虑磁盘空间)。无论何种方式查表,最终都会利用主键经过汇集索引来定位到数据。汇集索引(主键)是通往真实数据的惟一出路。
  7. 辅助索引:非汇集索引均可以被称做辅助索引,其叶子节点不包含行记录的所有数据,仅包含索引中的全部键及一个用于查找对应行记录的【书签(即主键或者说汇集索引)】,下面两个图为辅助索引(first_name,age)以及经过主键再次查找的过程

    • clipboard.png
    • clipboard.png
  8. 联合索引:与覆盖索引没有区别,或者理解为覆盖索引是联合索引的最优解(无需经过主键回表)。
  9. explain

    • extra

      • using index :condition(用了索引,可是回表了)
      • using where :uning index(查询的字段在索引中就能查到,无需回表)
      • using index condition:using filesort(重点优化:代表查到数据后须要再进行排序,尽可能利用索引的有序性。)
      • using where:using index
    • type(链接类型:join type),如下逐步增大

      • system 系统表,磁盘io忽略不计(有些数据就已经在内存中)
      • const 常量链接(加了where条件限制,命中主键pk或者惟一unique索引)
      • eq_ref 主键索引或者非空惟一索引、等值链接;若是把惟一索引改成普通索引+等值匹配,可能type只为ref,由于可能一对多
      • range 区间范围 between and;where in,gt lt;(注意必须是索引)
      • index 索引树扫描,即须要扫描索引上的所有数据,好比innodb的count
      • all 全表扫描
    • select * 与索引(看主要命中条数与总条数,若是相近,用不到索引,就全回表了,若是是必定范围,那就是range use indexcondition)
    • rows(粗略统计,不是精确)
  10. 其余:

    1. varchar为啥为65535?compact行记录的第一个字段为变长字段长度列表,为2个字节16位。参考
    2. 一个表最多多少行?1023,具体也是看行格式的数据结构便可,参考上文的参考连接。
    3. 为何建议给表加主键?主键的做用是把数据格式转为索引(平衡树)
    4. 联合索引在b+树中如何存储?
    5. 为何索引不直接用二叉查找树,要用b树,b+树?主要考虑减小磁盘io(考虑磁盘物理原理及局部性与磁盘预读的特性:)
    6. myisam和innodb必须有主键吗?innodb必须有,数据文件须要按照主键汇集,若是没有innodb会自动生成。

3、算法&数据结构

  • 最小堆:根节点为最小值,且节点比其余孩子小
  • 平衡树(avl 红黑树)
  • 最大堆:根节点为最大值,且节点比其余孩子大
  • sikplist
  • hash

    • hash 碰撞缘由
    • hash 碰撞解决方案

      • 拉链,塞到链表里。优势是相对简单,可是须要附加空间(想到了php max_input_vars
      • 开放寻址,优势是空间利用率高,一直找..

        • 线性探测
        • 二次探测再散列函数
        • 伪随机数
  • 给定数值n,判断n是斐波那契数列的第几项?写算法
  • 反转列表如A->B->C->D 到A->D->C->B
  • 插入排序
  • 数组与链表区别与联系
  • 链表操做

    • 单链表删除

      p->next=p->next->next;
        if(head->next===null){
            head=null
        }
    • 单链表插入

      new_node->next=p->next;
        p->next=new_node
        
        if(head===null){
            head=new_node;
        }
  • 应用问题

    • 如何实现一个LRU功能?【双向链表】
    • 如何实现浏览器前进后退功能?【两个栈】

4、设计模式

  1. 设计模式

    • 单例模式 (static ,consturct)

      static private $instance;
          
          private $config;
          
          private funciton __construct($config){
              
              $this->config=$config;
          }
          
          private funciton __clone(){
              
          }
          static public function instance($config){
              if(!self::$instance instanceof self){
                  self::$instance=new self($config);
              }
              return self::$instance;
          }
      }
    • 简单工厂(switch case include new return )

      {
              public function makeModule($moduleName, $options)
              {
                  switch ($moduleName) {
                      case 'Fight': 
                          return new Fight($options[0], $options[1]);
                      case 'Force': 
                          return new Force($options[0]);
                      case 'Shot': 
                          return new Shot($options[0], $options[1], $options[2]);
                  }
              }
          }
          
      # 使用工厂方式 001
                  class Superman
                      {
                          protected $power;
                      
                          public function __construct()
                          {
                              // 初始化工厂
                              $factory = new SuperModuleFactory;
                      
                              // 经过工厂提供的方法制造须要的模块
                              $this->power = $factory->makeModule('Fight', [9, 100]);
                              // $this->power = $factory->makeModule('Force', [45]);
                              // $this->power = $factory->makeModule('Shot', [99, 50, 2]);
                              /*
                              $this->power = array(
                                  $factory->makeModule('Force', [45]),
                                  $factory->makeModule('Shot', [99, 50, 2])
                              );
                              */
                          }
               }
      # 使用工厂方式 002 
                  class Superman
                      {
                          protected $power;
                      
                          public function __construct(array $modules)
                          {
                              // 初始化工厂
                              $factory = new SuperModuleFactory;
                      
                              // 经过工厂提供的方法制造须要的模块
                              foreach ($modules as $moduleName => $moduleOptions) {
                                  $this->power[] = $factory->makeModule($moduleName, $moduleOptions);
                              }
                          }
                      }
                      
                      // 建立超人
                      $superman = new Superman([
                          'Fight' => [9, 100],
                          'Shot' => [99, 50, 2]
    • 门面模式

      • 对客户屏蔽子系统组件,减小子系统与客户之间的松耦合关系

5、正则表达式

  1. 正则表达式

    • 应用场景

      • 范匹配
      • 模版引擎
      • 词法分析器(lex)
    • 常见正则

6、PHP

  1. php

    • 代码解释过程(大多的非编译语言)

      • lexical词法分析,输入为源代码,输出为token
      • 语法分析 工具为文法(LALR),输出为表达式,7.0为AST,涉及:

        • 注释
        • 分号 & 分隔符
        • 变量
        • 常量
        • 操做数
      • 类型检查、关键字处理、导入,输出为中间代码。工具为选定的的编译器优化工具

        • 中间代码生成(Opcodes)
        • 机器码生成(编译语言)
    • session共享配置
    • phpunit用法
    • cookie购物车和session购物车的实现
    • 弱类型实现
    • 代码规范

      • 自动化:sonarquebe+jenkins
      • 单元测试
    • php进程间如何通讯

      • 信号量
      • 消息队列
      • 管道
      • socket
      • 共享内存
    • php并发模型
    • 变量底层存储结构
    • 经常使用的数组函数(列出10个)

      • array_combine(前面数组做为其键,后面数组作为其值)
      • array_merage(合并两个数组,后面覆盖前面,但数字索引会从新索引,不会覆盖)
      • array_multisort
    • php垃圾回收机制(gc)

      • zend.enable_gc php.ini
      • gc_enable() funciton
    • 把session放入redis里面还会触发相似文件的state session

      • session.gc_probability (default 1)
      • session.gc_divisor (default 100)
      • session.gc_maxlifetime(单位秒)
      • session.cookie_lifetime(单位秒,0表示直到关闭浏览器)
      • session.save_path
      • session_write_close (显示关闭,后期使用须要显示开启)

7、操做系统

  1. 操做系统

    • 多线程
    • 多进程
    • 协程的理解
    • socket和管道的区别
    • 进程间通讯手段

      • 共享内存
      • rpc
      • 管道
    • 线程间通讯手段

      • 读写进程数据段

8、网络协议

  1. 网络协议

    • http

      • 构成:起始行(GET =>200),首部头 (ACCEPT=>CONTENT-TYPE),主体 name =》tongbo
      • 版本:

        • 1.0
        • 1.1
        • 2.0 :多路复用、流量控制
    • 长链接

      • 在一个链接上发送多个数据包
      • 心跳、如何发送心跳
    • httpdns

      • 定义:用http协议代替原始的udp dns协议,能够绕过运营商的local dns
      • 解决问题:避免local dns形成的域名劫持问题和调度不精确问题(更可能是在移动客户端)
      • 其余解决方案

        • 客户端dns缓存
        • 热点域名解析
        • 懒更新策略(ttl过时后再同步)
    • post请求分割head 和body
    • get vs post:

      • get(

        • 安全幂等,请求实体资源
        • 参数只能url编码,且参数长度有限制
        • 浏览器会自动加cache
      • post

        • 附加请求实体于服务器
        • 产生两个tcp数据包
        • 数据支持多种编码格式
    • resultful

      • get:获取资源
      • post:新建资源
      • put:更新完整资源
      • delete:删除资源
      • patch:更新部分资源
    • Rpc VS Http/rest

      • http/rest

        • 同步阻塞

          • 异步回调
        • 优势

          • 客户端支持度高
          • 监控方便
        • 注意点

          • 通讯效率低
          • rest的put/delete支持度差
      • rpc

        • 分类

          • soap(http)
          • protocol buffer(tcp)
          • thrift(tcp)
        • 优点

          • 二进制支持
          • 自动生成服务端、客户端代码,支持语言丰富
          • 自带序列化
        • 注意点

          • 字段类型与定义问题
    • tcp

      • 面向链接,先创建(握手),而后释放(挥手确认拜拜)
      • 只能点对点
      • 可靠交付(相对来讲),全双工,接收和发送端都设有发送和接收cache
      • 面向字节流(流:一连串,无结构的的信息流,流入到进程或从进程流出的字节序列,而一个报文段多少字节是根据窗口值和网络拥塞程度动态变化的)
      • 释放:

        • 客户端:FIN_WAIT 1,中止发送数据给服务端。等待服务端确认
        • 服务端:ack ,进入CLOSE_WAIT(关闭等待),此时若是服务端有数据要发送,客户端还能够接收。
        • 客户端收到服务端确认后,进入FIN_WAIT 2,等待服务器发出链接释放报文段。
        • 此时若是服务端没有数据要发送,发送上步骤客户端等待的释放报文段,而后服务端进入LAST_ACK
        • 客户端收到服务端的last_ack后,发出确认,进入TIME_WAIT,通过2MSL后,客户端关闭
        • 服务端收到客户端报文段后,进入CLOSE
        • clipboard.png
        • 关于TIME_WAIT:

          • time_wait是一种TCP状态,等待2msl能够保证客户端最后一个报文段可以到达服务器,若是未到达,服务器则会超时重传链接释放报文段。使得客户端、服务器均可以正常进入到CLOSE状态。
        • 关于'粘包'

          • 分包:在一个消息体或一帧数据时,经过必定的处理,让接收方能从字节流中识别并截取(还原)出一个个消息体。
          • 短链接tcp分包:发送方关闭链接,接收方read 0,就知道消息尾了
          • 长链接TCP分包:

            • 消息长度固定or消息头中加长度字段
            • 固定消息边界,好比http:rn
            • 利用消息自己格式,如xml,json
      • 特性协议

        • 停等
        • 超时重传
        • 慢启动
        • 滑动窗口
        • 快速重传
    • udp

      • 无链接、best effort、面向报文(不合并、不拆分,保留边界)
      • 无拥塞控制、流量控制、首部开销小(8个字节,而tcp有20个首部)
      • 支持一对一,一对多,多对一
    • 自定义协议
    • rpc

9、大前端

  1. js

    • 百度统计的实现

      • 基于cookie,引入js脚本及baidu我的帐户id,读取当前信息,适当节点发送请求给百度服务器

10、中间件

  1. 中间件

    • rebbitmq
    • kafka
    • Redis 队列

11、php框架

  1. php框架

    • ci
    • yii
    • laravel

      • AppServiceProvider register:服务提供者注册
      • IocContainer:(工厂模式的升华:ioc容器)

        • 控制反转(inversion of control)能够下降计算机代码之间的耦合,其中最多见的方式叫作依赖注入。(Dependence Injection),还有一种方式为依赖查找。
        • 实现方式

          • 基于接口:实现特定接口以供外部容器注入所依赖类型的对象。
          • 基于set方法:还没搞明白。
          • 基于构造函数:实现特定参数的构造函数
        • 管理类依赖
        • 执行(依赖注入DI):经过构造函数或者某些状况下经过setter方法将类依赖注入到类中,容器并不须要被告知如何构建对象,由于他会使用php的反射服务自动解析出具体的对象。
    • swoole
    • 依赖注入与控制翻转

十二 、运维

  1. 运维&架构

    • 服务器cpu99%如何分析
    • mysql 占cpu如何分析
    • php占cpu较高如何分析
    • sso实现方法
    • mysql优化方法
    • 如何提升监测数据的准确性
    • docker 原理及引用及编排管理

十3、golang

  1. golang

    • todo

十4、 Linux

  1. linux

    • epoll
    • 查看负载:cat /proc/loadavg || w || top
    • df
    • top shift+M
    • free
    • ipstat
    • strace
    • grep [-A ,-B, -C]'HTTP/1.1" 200' access.log |wc -l
    • socket和管道(pipe)的区别:socket全双工,pipe半双工*2
    • awk

      • awk '{print $1}' access.log |sort |uniq |wc -l

十5、nginx

  1. nginx

    • worker_connections
    • upstream weight
    • 负责均衡实现方式

      • 轮询
      • ip 哈希
      • 指定权重
      • 第三方

        • fair
        • url_hash

十6、分布式 | 微服务

  1. 分布式

  2. 微服务

    • 最佳原则

      • 高内聚:修改一个功能,只须要改一个服务
      • 低耦合:修改了一个地方,不须要改其余的地方(下游消费者不受影响)
      • 业务内原则:

        • 新服务用新的微服务,肯定无误后保留推动,不然调整
        • 老的保留,直到新服务稳定再切换
        • 必需的的监控与日志|生产-订阅—消费模型
        • 尝试对外不可见的服务先作试点,错误邮件、日志、系统内调用、api内部分红熟接口
    • 考虑问题

      • 服务发现是否须要客户端自实现?
      • 服务可用性保证
      • 要不要拆MySQL表?保证服务底层的高内聚?异或是存到nosql
      • 数据一致性问题?主从|缓存
      • 服务监控日志存储及查询功能是否须要自实现?
      • 基于事件+生产|消费模型选型

        • rabbitmq
        • kafka
        • redis 队列
      • 请求失败是否须要存入队列以便再次发起(最大重试次数与死信队列)?

其余

  1. 其余

    • 两个绝对路径,求之间的相对路径
    • 分布式

      • 基础

        • cap原理
        • 解决多个节点数据一致性的方案其实就是共识算法
      • 分布式协议

        • Paxos:Proposer, Acceptor, Learner
        • ZAB:Follower, Leader, Observer
        • raft:leader ,follower,candidate
        • clipboard.png
      • 分布式工具

        • zk:zab(base paxos)protocol,
        • etcd:raft protocol(mini PAXOS),k-v database

具体

  1. 如何对一个大文件排序(装不进内存的)-好将来

    • 思路:

      • map reduce
      • 分割成小文件(临时文件)
      • 去重
      • awk grep end for sort
      • 输入输出缓冲区
  2. 快速排序代码
  3. 冒泡排序代码

    • 外层循环 0到n-1 //控制比较轮数 n 表示元素的个数
    • 内层循环 0到n-i-1 //控制每一轮比较次数
    • 两两比较作交换
    • 外层循环开始声明 is_switch flag为false,内层循环有交换为true,外层循环结束时判断无switch break
  4. 归并排序代码

面试完成后

  1. 自身定位与公司给定技术评级
  2. todo

其余参考

  1. [感受php要求好高?](zhihu.com/question/21866412/answer/349627984)
相关文章
相关标签/搜索