首先面试都是从小公司到大公司的过程,小公司主要为了练手,熟悉面试节奏,后面才去面大公司。尽量不要一开始就奔着大公司去,容易出现准备不足的情况。。。另外,算法是真的难!遇到的面试题也都记了下来,主要是php+go的部分面试题。部分问题附带答案,希望对大家找工作能有帮助。你要做的就是每天进步一点点。。。
微信公众号:码农编程进阶笔记
关注可获得更多的视频教程及面试技巧。问题或建议,请公众号留言!
~~~~~1.不知名小公司A~~~~~
1.k8s的服务注册
????答:参照k8s笔记
2.rabbitmq的消息确认机制,项目里面怎么确认的
????消息确认:
????1)生产者到消息队列,这个是利用消息队列
????的confirm机制和持久化机制,持久话之后就给生产者发送一个ack确认
????????生产者只能设置为事务,或者confirm,不能共用
????2)消息队列,内部有唯一的msg_id,会先根据该id判断消息是否重复发送,mq再决定是
????否接收该消息
????3)消费端,消费成功则发送ack给消费队列,消费队列才会删除该消息
????????$q->nack($message->getDeliveryTag());?//?deliveryTag?可以用来回传告诉?rabbitmq?这个消息处理成功?清除此消息
????避免重复消费:
????1)业务需要有一个唯一的id,避免消息队列重复下发消息。一般可以跟db的唯一字段对应起来,或者用redis来实现过滤
????消息分发策略:
????????1)轮训分发模式。?每个消费者收到的消息数量是一样的
????????2)?公平分发,会考虑到消费者的当前消费能力等
3.rabbitmq实时性怎么实现?
????答:维护一个常驻进程,实时读取队列消费即可,一般使用的维护工具是:
3.redis和mysql的一致性,项目里面怎么用的
????查询:
????数据分为静态数据和动态数据。
????静态数据:直接读redis,不存在则返回默认值
????动态数据:直接读redis,不存在则返回默认值
????更新:
????1)旧数据缓存的映射(删除key),更新缓存映射关系(Set)
????2)mq异步更新db
????问题:redis断电,不去读db,直接返回默认值吗?
????答:是的,因为有集群的高可用,最多出问题几秒就重新拉起来一个。
????????而且数据是最终一致性的。
???3)创建数据,开启事务,先写入到db,后更新到redis,事务提交。
???4)?每个数据都有默认值处理,防止缓存查询失败,返回无数据的情况
???4)redis结构:hash结构存储,?hmget?,hgetall
???5)初始化呢,缓存中无数据怎么办??写的有脚本,遍历数据写入到redis
???6)mq里面的数据在哪消费的,在udc.job
4.高并发秒杀场景设计,redis怎么设计秒杀的
????参照redis部分,已经设计了一个秒杀系统
5.redis大key存储,value是怎么存储的
????1)拆分为多个key-value,用multi事务去组合查询。分解单次操作压力
????2)使用hash存储,然后每个field代表一个属性。查询的时候查询部分属性,
????存储的话也可以按照属性存储。本质上还是拆分
????3)存储的时候,对key做取模拆分,分配到不同的key上面
6.redis集群同步数据
????(1)?【所有的redis节点彼此互联(PING-PONG机制)】,内部使用二进制协议优化
????传输速度和带宽。
????(2)?节点的fail是通过集群中【超过半数的节点检测失效】时才生效。
????(3)?客户端与redis节点直连,不需要中间代理层。客户端不需要连接集群所有节点,
????【客户端连接集群中任何一个可用节点即可】。
????(4)Redis集群预分好16384个桶,当需要在Redis集群中放置一个key-value?时,
????计算key属于哪个桶,然后存放value
????(5)集群正常工作至少需要3个主节点,一共就需要6个节点,其中3个为主节点,
????3个为从节点
????---查询
????(1)计算key所在槽,在本节点上,就直接返回数据
????(2)不在本节点上,则执行move,指引client转向负责对应槽的节点,
????并客户端需要再次发送想要执行的和key相关的命令
7.对mysql架构的理解
????答:客户端和服务端组成。
????客户端进程向服务器进程发送MySQL语句,服务器进程处理后再向客户端进程发送处理结果
????客户端:对应配置为:[client],[mysql],[mysqladmin]
????服务端:对应配置为:[server],[mysqld],[mysqld_safe]
????引擎部分:mysql中具体与文件打交道的子系统,是官方提供的文件访问层的
????一个抽象接口来定制一种文件访问机制
????执行过程:
????????(1)客户端连接服务端,mysql-uxxx?-pxxx
????????(2)服务端进行查询缓存,不过5.7不建议使用,8.0废弃
????????(3)服务端语法解析,判断请求的语法是否正确,然后从文本中将要查询的表等
????????(4)查询优化:生成一个执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序是啥样的
????????(5)存储引擎:MySQL server完成了查询优化后,只需按照生成的执行计划调用
????????底层存储引擎提供的API,获取到数据后返回给客户端就好了。
8.为什么项目里面是用curl来调度服务的,怎么不用rpc,差距在哪?
????答:https://blog.csdn.net/AlbenXie/article/details/105230018
????(1)http的报文header头占用空间太多了,rpc一般会优化这块
????(2)rpc是基于http2.0的,减少rtt,长连接方面有优势
????(3)rpc传输的序列化反序列化可以是protobuf
????(4)rpc框架包含了重试机制,路由策略,负载均衡策略,高可用策略,
????流量控制策略等等能用在消息处理上的功能
9.php的桶结构
????(1)bucket桶结构,实际的数据存储在这里,用链地址法防止冲突。(redis也是)
????????数据是链表连接的,foreach就是根据赋值顺序,找到下一个元素的指针,依次遍历
????(2)一个hashtable默认分配8个bucket,如果存储的元素大于8个会自动扩容,
????扩容后的大小为2的倍数。一般是先看看删除的元素是否到达阈值,到达的话则重建
????索引。没有到达阈值则扩容,*2
????(3)php的forach比for快,就是因为forach直接拿首个bucket的指针开始遍历,省去了
????计算key的hash值的过程,同样的,next(),prev()等方法也是直接在hashtable上就能取到值
????(4)php7之后,是先通过计算key得到value的位置,然后把key存到中间表,中间表
????主要存储key和value的映射关系。扩容的时候,中间表也要重新计算
????(5)php删除数组的中的元素,并不是立刻删除的,只是给标识为IS_UNDEF,扩容的时候
????才会真正的删除掉
????(6)查找时先在散列表中映射到nIndex,得到value在Bucket数组的位置idx,
????再从Bucket数组中取出元素。
~~~~~2.不知名小公司B~~~~
1.include和require的区别
答:
1)报错
??? include 引入文件的时候,如果碰到错误,会给出提示,并继续运行下边的代码。
??? require 引入文件的时候,如果碰到错误,会给出提示,并停止运行下边的代码。
2)文件引用方式
include()?执行时需要引用的文件每次都要进行读取和评估,
require()?执行时需要引用的文件只处理一次
3)include_once?函数和include类似,只不过只会引入一次
2.composer?insall和update的区别
????答:install读取lock文件,没有的话,则读取json文件,并生成lock
????????update会读取json,拉取最新依赖,把新的版本写入lock
????????也就是说,当本地没有lock文件的时候,install和update是一样的
3.cookie和session
????答:服务端生成cookie返回给客户端,客户端请求带着cookie,
????服务端获取cookie和session_id,
????然后读取session文件,就可以对比客户端的cookie了。
????session是依附于cookie的,需要cookie来存储session_id。当禁用cookie的时候,
????通过url重写或者表单隐藏域来提交session_id
4.sql注入,xss,csrf
????答:sql注入,用户输入sql命令或者sql注释,拼接sql的时候,会查出所有的
????用户信息。
????防范:是过滤用户输入,使用预处理来拼接sql
??? xss跨站脚本:网页中注入恶性脚本。持久型是存入到数据库,读出的时候弹出恶意代码,
????反射型是通过电子邮件等,引导用户点击恶意链接。
????防范:用户输入过滤,cookie加密
??? csrf:跨站请求伪造。拿到A的cookie,访问恶意网站b,b就可以拿着a的cookie去访问a网站。
????防范:token机制,验证referer
5.git?pull和git?fetch的区别
????答:都是更新远程代码到本地
????(1)git?pull相当于暴力合并,直接拉取代码,并合并,相当于git?fetch?+?git?merge
????(2)git?fetch(下载)拉取代码后,一般需要手动合并下代码
6.线程是什么,线程的上下文切换
????答:?上下文切换:上下文切换就是从当前执行任务切换到另一个任务执行的过程。但是,
????为了确保下次能从正确的位置继续执行,在切换之前,会保存上一个任务的状态。
????进程切换:
????(1)切换页目录以使用新的地址空间
????(2)切换内核栈(函数)和硬件(寄存器)上下文
????寄存器:cpu内部的元件,可以保存数据,保存地址,指令等
7.trait的好处
????伪多继承。php中一个类能继承多个接口,但只能继承一个父类。
????使用trait,可以实现继承多个父类,避免复用代码
8.负载均衡原理
????Lvs的nat:?
????????客户端?-->?Load?Balancer?-->?RS?-->?Load?Balancer?-->?客户端
????????1)LB可以修改客户端发来的ip头,tcp头,定位带rs服务器群
????????2)服务器响应后,会发送给LB网关,LB再修改ip和tcp报文,发送给客户端
????LVS的DR:
????????客户端?-->?Load?Balancer?-->?RS?-->?客户端
????????1)Rs公用一个ip,LB对外服务,拿到请求后,分配给rs
????????2)rs直接返回数据包给客户端????
9.mysql的长连接和短连接,都有什么特点,框架里有使用吗?
答:长连接指在一个连接上可以连续发送多个数据包,在连接保持期间,
????如果没有数据包发送,需要双方发链路检测包。
????mysql的长连接如果长期闲置,mysql会8小时后(默认时间)主动断开该连接。
10.线程池的大概设计
?????(1)要设置最大连接和最大连接空闲数。小于最空闲数则使用完入池。大于最大空闲数则释放
????(2)需要多一个队列,来表示等待队列。当请求没有?数据库连接空闲,则进入队列。设置有默认的超时时间,超时报错
????(3)当一个链接使用完,要判断是否有等待队列需求,有的话直接返回给等待中的需求,没有的话就入池
????(4)均衡和保活。均衡可采用队列先进先出的方式保持?。保活的话,类似于发送心跳,保持连接活性
11.php的数组扩容
????我们知道,数组存储需要连续的内存空间,那么扩容的时候呢,是虚拟内存的方式,
????还是直接申请一大块内存呢?
????答:一个hashtable默认分配8个bucket,如果存储的元素大于8个会自动扩容,
????扩容后的大小为2的倍数。
~~~~3.马蜂窝一面~~~~
1.python的切片了解吗
????答:切片操作基本表达式:object[start_index:end_index:step]
????(1)冒号':'可以省略,step默认为1.
????(2)step的正负代表切片的方向
2.okr和kpi的区别
????(1)OKR 强调全员思考;KPI 强调管理层思考。
????(2)OKR 强调自我驱动;KPI 强调外在驱动。
????(3)KPI 只能让驴使劲走,而 OKR 用于保证驴头朝正确的方向。
3.es数据超过一亿,有没有做过什么优化
????答:首先es数据在磁盘上,每次查询也是去查询缓存,不存在缓存
????则去磁盘查找,刷新到缓存。缓存一般占机器内存的50%
????(1)热数据单独建索引,类似于mysql的分表。
????????可以hash%64这样,减小索引大小。
????(2)查询部分不要使用复杂的join,parent-child这种
????????其次是filter查询效率比query高,而且会缓存数据,方便下次查询。
????(3)分页不要太大,es每次分页都会向所有节点查询数据,然后
????返回给node1,node1最终返回数据,所以分页小点好。
4.mysql插入数据,断电重启之后,数据会丢失吗,为什么
????答:靠的是redo log,事务每次执行会先写入到缓冲区,通过两段提交方式,
????????保证恢复已经commit的数据。
????????checkpoint:记录被刷新到磁盘的redo?log的id,mysql重启之后会从上一次的
??????? checkpoint开始恢复,加快恢复的速度。
????????(1)事务执行的几个阶段
????????????①?InnoDB)prepare?redo?log
????????????②?Server)write?binlog
????????????③?InnoDB)commit?redo?log
????????(2)从上个checkpoint开始恢复,如果redo?log有两个状态,则直接提交。
????????如果redo?只有prepare,则拿些事务id去查询binlog,binlog有写入则提交,
????????binlog无写入则回滚该事务。
5.tcp的三次握手是特有的吗,udp会有吗,了解udp吗?
????(1)tcp和udp的区别
????????1)tcp可靠,udp不可靠
????????2)tcp需要先建立连接,udp不需要
????????3)tcp是一对一,udp可以1对多
????????4)tcp效率低,udp效率高
????????5)TCP?有滑动窗口可以用来控制流量,而?UDP?则不具备流量控制的能力
????????6)TCP 是面向字节流的传输层协议,而 UDP 是面向报文的传输层协议;
????????7)TCP?的应用场景是对消息准确性和顺序要求较高的场景,
????????而 UDP 则是应用于对通信效率较高、准确性要求相对较低的场景。
????(2)面向字节流和面向报文的区别
????????面向字节:TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,
????????当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。
????????如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后
????????再构成报文段发送出去
????????面向报文:送方的UDP对应用层交下来的报文,不合并,不拆分,
????????只是在其上面加上首部(最小8字节)后就交给了下面的网络层。
????(3)tcp粘包
????????答:发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,
????????后一包数据的头紧接着前一包数据的尾。
????????半包:数据包比较大,tcp每次发送只能发送一半
????????注意:udp不存在粘包,不会合并小包。
????????造成粘包原因:
????????????1)发送方合并多个小分组,在一个确认到来时一起发送
????????????2)接收方接收数据到缓存,程序去缓存中读取。当程序读取速度<接收速度,
????????????就可能粘包。
????????解决方案:
????????????1)发送方使用TCP_NODELAY选项来关闭Nagle算法
????????????2)发送的时候把长度也发送过去。程序收到之后,根据长度确认
????????????????包的大小,然后进行分割。
?????(4)tcp其实没有包的概念
?????????TCP是字节流协议,确实没有包的概念,包是应用层的概念,只是概念叫做
?????????粘包。
?????(5)ip包分片
?????????1)最大传输单元:数据链路层对数据帧的长度都有一个限制,也就是链路层所能
?????????承受的最大数据长度,这个值称为最大传输单元,即MTU。
?????????通常是1500字节。
?????????2)在IP包头中,以16位来描述IP包的长度。一个IP包,最长可能是65535字节
?????????3)当ip包大于MTU,则要进行分片,分为多个小包传输。如果设置
?????????不可分片,则数据包被丢弃,出现报错。
?????????4)TCP的选项字段中,有一个最大报文段长度(MSS),一般是1024字节
?????????5)ip头长度,tcp头长度都是固定20字节。
?????????6)IP包头中,用了三个标志来描述一个分片包,分别是:
?????????????分片标志(0/1),分片偏移标志(分片在原包的位置),不允许分片标志
6.?mysql和redis如何保证数据一致性
????从应用场景分析。读多写少,和读少写多,可以了解下缓存策略。
????缓存策略:
????读多写少:
????????(1)缓存为主,不存在则返回默认值
????????(2)更新的时候更新缓存,队列异步更新db
????????(3)数据预热,启动系统之前先用脚本去跑缓存
????读少写多:
????????(1)每次读取,没有缓存就写入缓存
????????(2)更新的时候,更新数据,删除缓存。
????????(3)写多读少的话,会减小缓存的更新消耗。
7.php7.0对于引用计数的优化有哪些?
????答:
????1)当对整型,浮点型,静态字符串赋值时,引用计数是0
????????动态字符串就是用函数生成的字符串,这种的会有引用计数。
????????因为php7的引用计数value?中而不是?zval_struct,当数据类型简单的时候,
????????value可以直接存下。
????2)引用&之后,refcount?为2
????3)不可变数组,就是直接赋值固定内容的数组,初始计数是2.
????动态数组初始计数是1.
????4)循环引用会造成内存泄露。比如:
????????//?数组循环引用
????????$arrA['arrA']?=?&$arrA;
~~~~4.马蜂窝二面~~~~
1. rabbitmq是分布式的吗,大概架构是怎么样的?
????答:是分布式的。
????主备集群模式,通过备用实现高可用。
????镜像模式,一个节点的数据会同步到3个其他节点上,保证
????数据不丢失。
2.kafka,会丢数据吗,丢数据在哪一步,怎么处理?
????答:会丢的,主要从生产者,服务器,消费者几个方向来处理。
????(1)Broker:broker存储topic的数据。如果某topic有N个partition,
????集群有N个broker,那么每个broker存储该topic的一个partition。
??? kafka采用了批量刷盘的做法,数据存在缓冲区。
????只能通过调整刷盘机制的参数缓解该情况。比如,减少刷盘间隔,
????减少刷盘数据量大小。时间越短,性能越差,可靠性越好(尽可能可靠)。
????这是一个选择题
????(2)生产端:设置及ack为-1或者all.
??????? ack=0:只负责发送,效率最高。
????????ack=1:保证leader能收到
????????ack=-1:保证leader和ISR列表都能收到,注意isr列表不能设置的太小
????????生产端也是异步批量发送数据到broker的,要保证数据不丢失,可以设置
????????同步发送,扩大Buffer的容量配置
????(3)消费端
????消费端手动提交offset
????(4)每个partition都有leader和floower.
????生产者发布消息时根据消息是否有键,采用不同的分区策略。消息没有键时,
????通过轮询方式进行客户端负载均衡;消息有键时,根据分区语义(例如hash)
????确保相同键的消息总是发送到同一分区
????(5)Rebalance
????Rebalance?本质上是一种协议,规定了一个?Consumer?Group?下的所有?consumer?
????如何达成一致,来分配订阅?Topic?的每个分区
????触发方式:
????????组成员个数发生变化。例如有新的 consumer 实例加入该消费组或者离开组。
????????订阅的 Topic 个数发生变化。
????????订阅 Topic 的分区数发生变化。
3.kafka发现消息积压了怎么办?增加消费者有用吗?
????答:一个分区最多被一个消费者消费,消费者多了之后没用的。
????我们可以在消费者中只做不耗时的操作,耗时的操作打入到二级队列,
????二级队列多做几个分区,这样消费能力跟得上
4.redis多个master怎么平均分配数据进去,会不会出现有的负载很高的情况
????答:不管是codis还是redis官方集群,都是hash算法计算key,找到对应的槽,
????最后找到节点,也就是master了。codis是1024个槽
5.redis的bitmap存储的key是什么?为什么不用redis提供的命令来求交集并集?
????答:(1)key存储的是用户id
????(2)redis提供的命令非常耗费cpu性能,自己程序做位操作好一些。
6. redis的分布式锁,过期时间如何续约?
????答:https://segmentfault.com/a/1190000022436625
????(1)redis的setnx和set都是针对单机redis的。如果是主从或者集群redis,
????当matser宕机,锁还没到slave.slave成为新master的时候,锁会失效。
????(2)redis的redlock是分布式集群锁,总体思想是尝试锁住所有节点,当有
????一半以上节点被锁住就代表加锁成功??.
????(3)zookeeper的分布式锁
????????1)一个ZooKeeper分布式锁,首先需要创建一个父节点,尽量是持久节点
????????(PERSISTENT类型),然后每个要获得锁的线程,都在这个节点下创建个
????????临时顺序节点。由于ZK节点,是按照创建的次序,依次递增的。
??????? 2)判断逻辑就是序号最小的先加锁,其他的阻塞。前一个锁
????????释放之后,会通知后面的节点。
??????? 3)可重入性,同一个线程可以重复加锁。
???(4)zookeeper和redis的优劣势
???????(1)基于ZooKeeper的分布式锁,适用于高可靠(高可用)而并发量不是太大
???????????的场景;
????????(2)基于Redis的分布式锁,适用于并发量很大、性能要求很高的、而可靠性
????????????问题可以通过其他方案去弥补的场景
~~~~~5.得物A部门一面~~~~
1.lru算法的大概实现,go怎么实现lru算法
??????答:步骤如下:
????(1)当访问的数据命中缓存,遍历得到这个数据对应的结点,并将其从原来的
????位置删除,然后再插入到链表的头部;(修改链表指针O(1))
????(2)?如果此数据没有在缓存链表中,分为两种情况:
????(3)?如果此时缓存未满,则将此结点直接插入到链表的头部;
????(4)如果此时缓存已满,则遍历至链表尾结点将其删除,将新的数据结点
????插入链表的头部。
??? php采用:数组+单链表的方式实现
??? golang采用:map+结构体链表的方式实现
?2.?mysql的主从不一致怎么解决
?????答:
?????(1)如何避免主从不一致:
????????1、主库binlog采用ROW格式
????????2、主从实例数据库版本保持一致
????????3、主库做好账户权限把控,主库不可以停止写binlog
????????4、从库开启只读?read_only=ON,不允许人为写入
????????5、定期进行主从一致性检验
?????(2)解决方案
?????1、将从库重新实现
?????2.使用percona-toolkit工具辅助(最佳方案)
?????3、手动重建不一致的表
?????4.另起脚本做一致性校验,不一致的话报警
?3.go的协程为什么比线程更轻量级
?????答:线程切换需要切换上下文,寄存器,堆栈等
?????(1)go协程也叫用户态线程,协程之间的切换发生在用户态。
?????在用户态没有时钟中断,系统调用等机制,因此效率高。
?????(2)就协程是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。
?????占用内存小,一般是2kb,线程需要8M
?4.kafka怎么防止重复消费?kafka的消费ack跟rabbitmq有什么区别
?????答:(1)在断电或者重平衡的时候,有可能消费者还没提交offset,导致
?????重复消费问题。一般是业务唯一id,数据库唯一键或者用redis存储消费过的id,
?????做一次判断过滤。
?????(2)一个是提交ack之后删除数据
?????????kafka是提交offset之后不删除数据,数据可以重复消费
?5.go怎么实现的锁
?????答:(1)读写锁sync.RWMutex?的?RLock())和写锁?Lock()
????????(2)互斥锁sync.Mutex
????????(3)atomic?包操作保证原子性?
?6.你认为项目最有亮点的地方说一下
?7.mysql分库的场景,如何连表查询?
?????(1)相同mysql下的不同库join查询。
?????可以带上库名,比如a.demo?和b.demo
?????(2)不同mysql下的查询
?????可以通过mysql的federated引擎,创建的表只是在本地有表定义文件,
?????数据文件则存在于远程数据库中
往期精选
php程序员面试题(偏中级面试题)
PHP 中高级程序员面试模拟题
2021年最新PHP 面试、笔试题汇总(一)
2021年最新PHP 面试、笔试题汇总? (二)
2021年最新PHP 面试、笔试题汇总(三)