2021中大厂php+go面试题(1)
一、前言
最近打算从二线去一线,借着远程面试盛行的机会,果断远程面了一圈,遇到的面试题也都记了下来,主要是php+go的部分面试题。部分问题附带答案,希望对大家找工作能有帮助。
首先面试都是从小公司到大公司的过程,小公司主要为了练手,熟悉面试节奏,后面才去面大公司。尽量不要一开始就奔着大公司去,容易出现准备不足的情况。。。另外,算法是真的难!
本文章主要是部分小公司,马蜂窝,得物,b站,小米,度小满,知乎等
。剩余部分面试题放到另一篇文章:
2021中大厂php+go面试题(2)
友情提示: 大部分的面试题都是重复的,因此会越写越少。。
二、正式面试题
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 ,hgetall5)初始化呢,缓存中无数据怎么办? 写的有脚本,遍历数据写入到redis6)mq里面的数据在哪消费的,在udc.job4.高并发秒杀场景设计,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文件,并生成lockupdate会读取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的时候,会查出所有的用户信息。防范:是过滤用户输入,使用预处理来拼接sqlxss跨站脚本:网页中注入恶性脚本。持久型是存入到数据库,读出的时候弹出恶意代码,反射型是通过电子邮件等,引导用户点击恶意链接。防范:用户输入过滤,cookie加密csrf:跨站请求伪造。拿到A的cookie,访问恶意网站b,b就可以拿着a的cookie去访问a网站。防范:token机制,验证referer5.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对外服务,拿到请求后,分配给rs2)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 为23)不可变数组,就是直接赋值固定内容的数组,初始计数是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)RebalanceRebalance 本质上是一种协议,规定了一个 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、主库做好账户权限把控,主库不可以停止写binlog4、从库开启只读 read_only=ON,不允许人为写入5、定期进行主从一致性检验(2)解决方案1、将从库重新实现2.使用percona-toolkit工具辅助(最佳方案)3、手动重建不一致的表4.另起脚本做一致性校验,不一致的话报警3.go的协程为什么比线程更轻量级答:线程切换需要切换上下文,寄存器,堆栈等(1)go协程也叫用户态线程,协程之间的切换发生在用户态。在用户态没有时钟中断,系统调用等机制,因此效率高。(2)就协程是一段代码,一个函数入口,以及在堆上为其分配的一个堆栈。占用内存小,一般是2kb,线程需要8M4.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引擎,创建的表只是在本地有表定义文件,数据文件则存在于远程数据库中
6.小米一面
1.让你设计一个框架,主要模块有哪些?怎么设计路由更高效?答:(1)框架流程入口文件->定义变量->引入函数库->自动加载类->启动框架->路由解析->加载控制器->返回结果(2)2.二叉树的非递归前序遍历3.mysql的undo日志原理,中继日志是干嘛的参考mysql拾遗4.nginx和php的关系,一个请求进来怎么到php的答:通过fastcgi协议,请求到nginx,通过fastcgi转发到9000端口,php-fpm监听9000端口,然后php程序处理5.反转链表怎么反转的?6.mysql的myisam的索引结构是什么样子的MyISAM引擎使用B+Tree作为索引结构,索引文件叶节点的data域存放的是数据记录的地址,指向数据文件中对应的值,每个节点只有该索引列的值。myisam的主键索引和二级索引的结构没区别
7.度小满一面
1.有序数组里面查询某个值出现的次数二分获取索引位置,双指针从索引位置左右遍历2.php的static什么情况下会用,好处是什么答:静态的东西都是给类用的(包括类常量),非静态的都是给对象用的(1)静态方法可以直接被类访问,不需要实例化(2)函数执行完静态属性的值会一直都在3.mysql的mvcc实现原理undo+间隙锁4.redis的rehash过程,中间有读写会分别怎么处理?断电呢?答:ht[0],是存放数据的tableht[1],只有正在进行扩容时才会使用,它也是存放数据的table,长度为ht[0]的两倍进行读操作:会先去ht[0]中找,找不到再去ht[1]中找。进行写操作:直接写在ht[1]中。rehashidx 初始是-1,开始rehash则为0,每次rehash都+1,rehash结束则修改为-1
8.b站一面
0.介绍项目里面的亮点
1.go的引用类型有哪些答:值类型分别有:int系列、float系列、bool、string、数组和结构体引用类型有:指针、slice切片、管道channel、接口interface、map、函数等值类型的特点是:变量直接存储值,内存通常在栈中分配引用类型的特点是:变量存储的是一个地址,这个地址对应的空间里才是真正存储的值,内存通常在堆中分配2.go的select的default作用当 select 中的其他条件分支都没有准备好的时候,`default` 分支会被执行。为了非阻塞的发送或者接收,可使用 default 分支:3.go的defer,里面有多个函数,执行顺序是什么答:后面的函数先执行defer特性:1. 关键字 defer 用于注册延迟调用。2. 这些调用直到 return 前才被执。因此,可以用来做资源清理。3. 多个defer语句,按先进后出的方式执行。4. defer语句中的变量,在defer声明时就决定了。defer用途:1. 关闭文件句柄2. 锁资源释放3. 数据库连接释放4.两个Goroutine,怎么控制先后顺序?答:参考:https://www.cnblogs.com/qingfj/p/14881692.html通过两个channel来控制,方法一:一个channel A有值,执行打印奇数。然后给另一个channel B赋值方法二: 读取channel B,打印偶数给channel A赋值注意:方法中需要是for循环的状态。其次是结束的话,也通过chan来阻塞。当要结束的时候,给channel C赋值,则main主协程会读取到C5.channel被关闭还能读出值吗,多次读的时候会返回什么?对一个关闭的channel写入呢,返回值是什么类型?答:(1)channel被关闭后是可读的,直到数据读完为止。如果继续读数据,得到的是零值(对于int,就是0)。(2)写已经关闭的 chan 会 panic 6.go的并发模型参考:https://segmentfault.com/a/1190000018150987(1)多线程共享内存 ,java/c++等语言实现的就是这个(2)CSP并发模型,go语言特有的,通过goroutine和channel来实现的Go语言的线程模型:MPGM指的是Machine,一个M直接关联了一个内核线程。由操作系统管理。P指的是”processor”,代表了M所需的上下文环境,也是处理用户级代码逻辑的处理器。它负责衔接M和G的调度上下文,将等待执行的G与M对接。G指的是Goroutine,其实本质上也是一种轻量级的线程。包括了调用栈,重要的调度信息,例如channel等。P和M数量一般会保持一致,跟cpu的核数有关。goroutinue会在一个队列里面,每次执行就会pop一个出来,当阻塞时,会调用其他的协程来做切换。优势:1)开销小,比常规线程小2)调度性能好,go可以控制goroutinue的调度缺点:协程调度机制无法实现公平调度。 7.go的缓冲channel 和单个channel有什么区别 无缓冲: 当向ch1中存值后需要其他协程取值,否则一直阻塞有缓冲: 不会阻塞,因为缓冲大小是1,只有当放第二个值的时候,第一个还没被人拿走,才会阻塞。
9.得物A部门二面
---php
1.php怎么实现常驻进程的,如何配置,如何监控为啥要常驻?常驻有什么好处答:通过pcntl 扩展和 posix扩展实现。参考:https://www.jianshu.com/p/161d9981112a创建步骤:1.创建子进程,终止父进程 (脱离父进程终端)2.在子进程中创建新会话(posix_setsid()方法)3.改变工作目录 (chdir('/') )4.重设文件创建掩码 (umask(0))5.关闭文件描述符 (主要是关闭父进程打开的文件等)优点就是可以在后台一直处理任务。常用的管理工具是:Supervisor 2.php内存泄露的排查与处理原因:(1)大内存变量未释放(2)循环引用自己(3)php-fpm在频繁删除缓存的时候会编译报错排查:看代码,看内存峰值,x-debug查看程序性能损耗--golang
1.golang的缓冲channel,在切换业务的时候怎么处理?答:不懂
2.golang的context的withcancel用过吗,什么场景(1) 关闭goroutinue(2)父级的context被关闭之后,他的子context也会被关闭1. WithCancel()函数接受一个 Context 并返回其子Context和取消函数cancel2. 新创建协程中传入子Context做参数,且需监控子Context的Done通道,若收到消息,则退出3. 需要新协程结束时,在外面调用 cancel 函数,即会往子Context的Done通道发送消息4. 注意:当 父Context的 Done() 关闭的时候,子 ctx 的 Done() 也会被关闭3.goroutinue的变量作用域问题,在循环中调用goroutinue修改变量,传递的变量会改变吗?如何优化答:循环中调用goroutinue,并在协程中打印value:很可能value指向最后一个元素。解决方案:(1)value作为参数传递给goroutinue(2) 在循环中新创建变量4.golang如何调度goroutinue的: 答:看概念
5.golang的switch和php的switch的区别(1)go中加上了默认break,匹配到对应case,在执行完相应代码后就会退出整个switch 代码块(2)go中用fallthrough关键字继续执行后续分支的代码--- 中间件
1.kafuka10个分区,一个消费者,golang会起几个协程答:可以是单个线程,也可以是多个线程。多线程的话不是线程安全的,需要注意点
2.kafka的offset是存在哪里的? 答:Kafka版本[0.10.1.1],已默认将消费的 offset 迁入到了 Kafka 一个名为 __consumer_offsets 的Topic中。原理:利用 Kafka 自身的 Topic,以消费的Group,Topic,以及Partition做为组合Key。所有的消费offset都提交写入到上述的Topic中。因为这部分消息是非常重要,以至于是不能容忍丢数据的,所以消息的 acking 级别设置为了 -1,生产者等到所有的 ISR 都收到消息后才会得到 ack(数据安全性极好,当然,其速度会有所影响)。所以 Kafka 又在内存中维护了一个关于 Group,Topic 和Partition 的三元组来维护最新的 offset 信息,消费者获取最新的offset的时候会直接从内存中获取。(2)kafka的position 在 consumer 端,大家都知道可以控制 offset,所以可以控制消费,其实 offset 只有在重启的时候才会用到。在机器正常运行时我们用的是 position,我们实时消费的位置也是 position 而不是 offset。3.rabbitmq的ack和kafka的ack区别?rabbitmq:处理完数据才发送ack,mq就可以放心删除数据了。当消费者异常退出没有发送ack,此消息会发送给下一个消费者,保证不丢失。kafka的ack机制就是指生产者的ack了4.mysql分库分表,每个表的id都从1开始吗,为什么要设置一般会设置全局的分布式id,主要方法为:(1)redis维护全局id底层,有宕机风险(2)简单号段模式,比如long类型,从1亿开始递增(3)雪花算法的发送器,百度的百度uid-generator,美团的ecp-uid5.kafka如何保证消息都分发到指定的分区上去(1)设置相同的key,kafka是hash(key)%numPartitions ,相同的key可以保证发送到同一个分区(2)生产端设置connection=1,该参数指定了生产者在收到服务器响应之前可以发送多少个消息。(3)分区的话,一个分区最好,保证写入顺序 (4)为实现Producer的幂等性,Kafka引入了Producer ID(即PID)和Sequence Number每个生产者Commit一条消息时将其对应序号递增--- 架构层面
1.整体业务的架构大概聊一下,服务之间的通信方式,信息流处理2.k8s的请求怎么转发到内部实际的ip的?服务之间的通信呢?答:(1)Service就是一个把所有Pod统一成一个组,然后对外提供固定一个IP,(2)我们访问service ip,k8s中的kube-proxy会自动负载均衡后端的8个pod,这一套服务集群内部访问,只需要一个service ip 和端口号就可以(3)外网访问:在每个Node上打开一个随机端口并且每个Node的端口都是一样的,通过<NodeIP>:NodePort的方式Kubernetes集群外部的程序可以访问Service。访问到service之后,自然也就能找到对应的pod提供服务了(4).ClusterIP:提供一个集群内部的虚拟IP(与Pod不在同一网段),以供集群内部的pod之间通信使用。(5)生产环境下的外网访问:Ingress 能把集群内 Service 配置成外网能够访问的 URL,流量负载均衡,终止SSL,提供基于域名访问的虚拟主机等等。1)Nginx 反向代理负载均衡器2)Ingress ControllerIngress Controller 可以理解为控制器,它通过不断的跟 Kubernetes API交互,实时获取后端 Service、Pod 等的变化,比如新增、删除等,然后结合 Ingress 定义的规则生成配置,然后动态更新上边的 Nginx 负载均衡器,并刷新使配置生效,来达到服务自动发现的作用。3)IngressIngress 则是定义规则,通过它定义某个域名的请求过来之后转发到集群中指定的Service。它可以通过 Yaml 文件定义,可以给一个或多个 Service 定义一个或多个 Ingress 规则。3.服务限流怎么做的?服务熔断怎么做的?限流:(1)代码里的队列计数redis-cell是一个用rust语言编写的基于令牌桶算法的的限流模块,提供原子性的限流功能,并允许突发流量,可以很方便的应用于分布式环境中(2)网关限流nginx自带的ngx_http_limit_req_module模块是对请求进行限流,即限制某一时间段内用户的请求速率;且使用的是漏桶算法熔断:熔断就是用php扩展滑动窗口计数滑动窗口算法限流最适合的需求场景,就是X秒内,最多允许Y个请求
10.度小满二面
1.一大堆元素中,求最大的n个数(分治,大顶堆)1)分治+大顶堆排序2)小顶堆,然后遍历,每次跟小顶堆的元素做对比,小的废弃。大于的话,就把这个大的元素入堆即可。最终结果就是小顶堆。2.查找第k大元素2.golang的withgroupAdd():每次激活想要被等待完成的goroutine之前,先调用Add(),用来设置或添加要等待完成的goroutine数量
例如Add(2)或者两次调用Add(1)都会设置等待计数器的值为2,表示要等待2个goroutine
完成Done():每次需要等待的goroutine在真正完成之前,应该调用该方法来人为表示goroutine完成了,该方法会对等待计数器减1Wait():在等待计数器减为0之前,Wait()会一直阻塞当前的goroutine3.mysql的事务如何优化提升速度答:通过减小锁粒度和减少锁的持有时间进行调优(1)结合业务场景,使用低级别事务隔离(2)sql优化避免行锁升级表锁(3)更新等行锁操作放到事务后面,尽量减少持有锁的时间。比如我们先创建订单,执行逻辑,最后扣除库存。4.红黑树和二叉树的区别,性能为什么比二叉树好?
红黑树是一种平衡二叉查找树。它是为了解决普通二叉查找树在数据更新的过程中,
复杂度退化的问题而产生的。红黑树的高度近似 log2n,所以它是近似平衡,
插入、删除、查找操作的时间复杂度都是 O(logn)。AVL 树是一种高度平衡的二叉树,所以查找的效率非常高,但是,有利就有弊,
AVL 树为了维持这种高度的平衡,就要付出更多的代价。每次插入、删除都要做调整,
就比较复杂、耗时
AVL树的查询性能更稳定,如果更新频繁的话,红黑树更好。
(1)红黑树的查询性能略微逊色于AVL树,因为他比avl树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的avl树最多多一次比较,(2)红黑树在插入和删除上完爆avl树,avl树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于avl树为了维持平衡的开销要小得多5.什么情况下用rabbitmq,什么情况下用kafka呢答:(1)吞吐量高的时候用kafka(2)需要低延迟的情况下用rabbitmq(3)部分延时队列用rabbitmq
11.伴鱼一面
1.链表有next指针和random指针,深拷贝 (ok)
2.矩阵里面有1和0,1代表岛屿,求出所有岛屿的数量 (深度搜索)
3.二叉树的中序遍历,迭代方式1)根节点入栈,左节点入栈2)一直到左节点为null,出栈,打印值3)右节点入栈4.php怎么连接rabbitmq和kafka的(1)rabbitmq1)php下载amqp扩展,里面带的也有rabbitmq扩展文件2)php通过amqp连接到mq上面,然后就可以发送调用了(2)kafka1)安装librdkafka 扩展2)连接broker,初始化生产者即可
12.知乎一面
1.M个有序数组的合并
有若干有序子数组, 合并为一个有序数组。假设M个子数组, 子数组的平均长度是 N2.LRU Cache
支持普通put 和 get 功能, 长度限制 1k。 不考虑缓存时间失效策略。1)数组存储每个节点,key=>节点查询的时候先判断key在不在数组2)注意数组要定义长度的,超过长度则删除尾部值3)put的时候,注意数组满没满,没满就生成新节点,然后插入到链表头部3.go的new和make的区别
(1)内置函数new按指定类型长度分配零值内存,返回指针,并不关心类型内部构造和初始化方式。(int、float、bool和string这些类型都属于值类型)
(2)内置函数make对引用类型进行创建,编译器会将make转换为目标类型专用的创建函数,以确保完成全部内存分配和相关属性初始化。(引用类型:slice、map、channel)(3)两个函数都有内存分配
13.小米二面
1.14亿个数的排序,求出第1亿个数是多少2.假如要你编写一个框架,DB类怎么实现conn()query()3.用sql求出每门课的平均分和最大分。
select b.课程名,avg(a.分数) as 平均成绩,max(a.分数) as 最高成绩,
min(a.分数) as 最低成绩
from 成绩表 a,课程表 b
where a.课程号=b.课程号
group by b.课程名
**介于篇幅过长,剩下部分放到另一篇文章。希望对大家能有帮助。
2021中大厂php+go面试题(2)
end**
2021中大厂php+go面试题(1)相关推荐
- 2021中大厂php+go面试题(2)
一.前言 废话不多说,本篇是面试题系列的第二篇.文章面试题包括:快手,字节,得物,滴滴,百度等.第一篇面试题为: 2021中大厂php+go面试题(1) 友情提示: 大部分的面试题都是重复的,因此会越 ...
- 2021年最新大厂php+go面试题集(四)
持续更新,每天进步一点点... 微信公众号:码农编程进阶笔记 关注可获得更多的视频教程及面试技巧.问题或建议,请公众号留言! 22.回响科技一面 1.kafka多个分区怎么保证消息顺序(1)首先发送消 ...
- 2021大厂字节跳动笔试题(含答案)
2021字节跳动web工程师笔试题 第一题 [ {num: 12, city: 'beijing'}, {num: 56, city: 'shanghai'}, {num: 167, city: 'g ...
- 进大厂一条龙服务(Java核心面试知识点+一线大厂Java笔试面试题+月薪3万Java优秀简历模板),看这篇就够了
你有没有觉得Java_工程师竞争压力大.就业困难?不知道面试Java工程师应该准备些什么?.. 现在一切都解决了!你想要的干货知识和面试题统统在这,还有月薪3万Java优秀简历模板,快拿回去嚼烂吧! ...
- 【2021最新版】RabbitMQ面试题总结(32道题含答案解析)
文章目录 1.什么是rabbitmq? 2.为什么要使用rabbitmq? 3.使用rabbitmq的场景. 4.如何确保消息正确地发送至RabbitMQ?如何确保消息接收方消费了消息? 5.如何避免 ...
- (一)梳理前端知识体系,搞定大厂必考面试题
梳理前端知识体系,搞定大厂必考面试题 常见面试题 JS基础知识 变量类型和计算 原型和原型链 作用域和闭包 异步和单线程 运行环境 HTTP协议 总结 常见面试题 JS基础知识 变量类型和计算 typ ...
- 2022最新Spring相关大厂常问技术面试题大全 —— 金三银四好时机
Spring相关大厂常问面试题 1. 什么是 Spring 框架? 2. 列举一些重要的Spring模块? 3. @RestController 与 @Controller 的区别 4. 谈谈自己对于 ...
- linux sed面试题,【2021最新版】Linux面试题总结(48道题含答案解析)
文章目录 1.绝对路径用什么符号表示?当前目录.上层目录用什么表示?主目录用什么表示? 切换目录用什么命令? 2.怎么查看当前进程?怎么执行退出?怎么查看当前路径? 3.怎么清屏?怎么退出当前命令?怎 ...
- 2021年N1叉车司机免费试题及N1叉车司机考试总结
题库来源:安全生产模拟考试一点通公众号小程序 安全生产模拟考试一点通:N1叉车司机免费试题是安全生产模拟考试一点通生成的,N1叉车司机证模拟考试题库是根据N1叉车司机最新版教材汇编出N1叉车司机仿真模 ...
最新文章
- Analysis and Design Overview
- VDI序曲二十 桌面虚拟化和RemoteApp集成到SharePoint 2010里
- python 判断目录和文件是否存在,若不存在即创建
- javascript注意点(1)
- 一起播四个视频的AVS脚本
- html5列表菜单特效,HTML5 SVG汉堡包菜单按钮分段动画特效
- JavaWEB/JSP 中简单的验证码 springMVC
- [导入]QZONE跳转FLASH地址生成工具
- 详解微信扫码支付二-------新人的一些心得
- 硬件工程师面试基础知识点
- java乘法口诀表_java 输出乘法口诀表
- (20210301未解决)error: chmod on /path/.git/config.lock failed: Operation not permitted
- oracle sysobject,SQL2000数据库提示未能读取并闩锁页 sysobjects 失败数据库修复
- 抽水马桶工作原理演示
- Python:百分制转五分制
- Forecasting (一):introduction
- 餐饮店的会员充值消费系统一般用哪个?
- 【国产】大数据自动化运维调度工具TASKCTL流程触发方式
- 淘宝店铺商品管理解决方案-商品SKU信息获取和修改oAuth2.0接口接入解决方案
- 北京大学计算机考研信息汇总
热门文章
- python做logistic回归_用Python做Logistic回归
- GitLab代码回滚到特定版本
- 软考-网络总结-协议
- segformer 使用笔记
- js push(),pop(),unshift(),shift()的用法小结
- Jquery 点击图片在弹出层显示大图
- non-strictly-monotonic PTS
- 快速理解平衡二叉树、B-tree、B+tree、B*tree
- module 'cv2' has no attribute 'CV_LOAD_IMAGE_GRAYSCALE'
- 图像傅里叶变换-不错