程序笔记   发布时间:2022-07-14  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了2021中大厂php+go面试题(2)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

一、前言

废话不多说࿰c;本篇是面试题系列的第二篇。文章面试题包括:快手࿰c;字节࿰c;得物࿰c;滴滴࿰c;百度等。第一篇面试题为: 2021中大厂php+go面试题(1)

友情提示: 大部分的面试题都是重复的࿰c;因此会越写越少。。

二、正文

1、快手一面

@H_674_17@1.CDn工作原理 答:CDN通过广泛的网络节点分布࿰c;提供快速、稳定、安全、可编程的全球内容分发 加速服务࿰c;支持将网站、音视频、下载等内容分发至接近用户的节点࿰c;使用户可就近 取得所需内容࿰c;提高用户访问的响应速度和成功率。 https://blog.csdn.net/aliyunbaike/article/details/84952966 2.go的init用过吗࿰c;主要使用场景是哪些? 答:每一个源文件都可以包含一个 init 函数࿰c;该函数会在 main 函数执行前࿰c; 被 Go 运行框架调用࿰c;也就是说 init 会在 main 函数前被调用。 3.快速排序 4.go的map怎么删除元素 delete(map, 键) 如果要清空map元素࿰c;直接make一个新map就可以 5.go的syncmap 1)map在并发编程中࿰c;读是线程安全的࿰c;写不是 2)sync.map是线程安全的࿰c;不需要初始化࿰c;声明即可 3)Store 表示存储࿰c;Load 表示获取࿰c;delete 表示删除 4)

2、边锋一面

@H_674_17@1.redis的连接跟mysql的连接有什么区别?为什么redis可以承受 更高的访问量? io多路复用 2.dns解析的具体流程 3.nginx访问php的方式࿰c;优缺点࿰c;怎么访问的 4.php获取请求到生成opcode的过程 ࿰c;opcode是干什么的࿰c;跟机器码有什么区别 答: 本质上一个opcode由两个参数(op1࿰c;op2)、返回值和处理函数组成。它的官方解释就 是php脚本编译后的中间语言࿰c;类似于java中的bytecode或者是.net中的MSL。 5.php定义类外的 静态变量࿰c;还有类里面的静态变量有什么区别?你说到类里面的静态变量是不会立刻释放的࿰c;那么有100个请求去请求这个类࿰c;静态变量的值累加࿰c;100次之后你认为这个值是多少࿰c;为什么 6.php定义类外的 静态变量࿰c;还有类里面的静态变量有什么区别?你说到类里面的静态变量是不会立刻释放的࿰c;那么有100个请求去请求这个类࿰c;静态变量的值累加࿰c;100次之后你认为这个值是多少࿰c;为什么 答:都是在程序一启动时就分配了内存空间࿰c;生命周期一样࿰c;但是作用域和可见性却 不一样 1)类内部静态变量必须通过类名或者对象名去访问࿰c;该变量在整个程序中都可见。 2)类外的静态变量只能在定义文件中使用࿰c;只在定义文件中可见࿰c;无法在非定义文件中使用。 7.nginx发送请求到phpc;这个请求是什么格式的࿰c;里面都包含了哪些内容 用户访问域名->域名进行DNS解析->请求到对应IP服务器和端口-> nginx监听到对应端口的请求->nginx对url进行LOCATIOn匹配-> 执行匹配LOCATIOn下的规则->nginx转发请求给php-> php-fpm的master进程监听到nginx请求->master进程将请求分配给闲置的worker进程 ->worker进程执行请求->worker进程返回执行结果给nginx->nginx返回结果给用户 nginx连接php的方式: 1)tcp方式: ip+9000端口 2)unix_socket:(要求nginx和php必须在同一台服务器上) fastcgi_pass unix:/tmp/php-fpm.socket 8.redis做队列࿰c;如果消费者挂掉了࿰c;这个数据丢失怎么办 redis有个命令叫做LPUSHRPOP(以及阻塞版本和不同方向的版本)࿰c;即从一个队列 弹出的同时将这个消息送入另一个队列࿰c;同时返回给客户端。原子操作。 9.rebbitmq会积压到内存爆掉࿰c;kafka为什么不会 答:当RabbitMQ收到消息时࿰c;如果是持久化消息࿰c;则会储存在内存中࿰c;同时也会写入 磁盘;如果是非持久化消息࿰c;则只会存在内存中

3、字节一面

@H_674_17@1.bitmap设置的长度是多大࿰c;用到了哪些hash函数 bitmap底层使用的还是字符串结构࿰c;最多是512M ࿰c;也就是2的32次方 位 2.渐进式hash࿰c;对渐进式的理解 1)从Dict.ht[0].table[0]的bucket进行rehash。 2)处理完一个bucket后࿰c;将ht[0].table[Dict.rehashidx] 置为 NULL。 3)将Dict.rehashidx加1࿰c;处理下一个bucket 查询: 比较当前key的大小和 rehashidx的大小࿰c;来选择 去h0还是h1中进行查询。 3.kafka的分区和消费者的分配原则 (1)分区数: Tt / max(Tp, TC) (2) key怎么分配到分区的? 1)有key的时候࿰c;做一次hash࿰c;根据分区数取模 2)key为null࿰c;则随机找一个分区写入 (3)分区和消费者的策略 1)range :partitions的个数除于消费者线程的总数来决定每个消费者线程消费 几个分区。如果除不尽࿰c;那么前面几个消费者线程将会多消费一个分区 2)将所有主题的分区组成 list列表࿰c;然后对 list列表按照 hashCode 进行排序 4.统计相同用户的访问次数࿰c;sort排序 cat logs/baidu.access.log | awk '{print $(NF-1)}' | sort | uniq -c | sort -k 1 -n -r|head -10 5.有n个任务࿰c;每个任务有开始和结束时间c;如何安排任务的顺序࿰c; 使得完成的任务个数是最多的

4、b站B部门一面

@H_674_17@1.php实现锁 1)静态变量(同一个请求的话࿰c;会不释放。多个请求的话会初始化) 2)apcu 将php代码编译之后所产生的bytecode暂存在共享内存内供重复使用࿰c;以提升应用的运行效率。(Opcode Cache) 提供用户数据缓存功能࿰c;需要显示的调用࿰c;redis/memcache类似。(User Data Cache) 2.订单表的分库࿰c;如何查询?数据量比较大的话呢 淘宝的做法是拆分买家库和卖家库࿰c;也就是两个库:买家库、卖家库。 买家库࿰c;按照用户的id来分库分表。卖家库࿰c;按照卖家的id来分库分表。 写入的时候࿰c;先写入买家库࿰c;然后通过消息队列异步写入到卖家库。 3.http304产生的原因࿰c;我们可以用它来实现什么场景 4.redis的bitmqp的缺点 数据比较松散的情况下不好用 5.go的读写锁 6.redis的list做队列࿰c;当数据比较多的时候怎么处理? (1)拆分法 可以遍历list࿰c;拆分到多个list中去࿰c;多个list可以按照顺序࿰c;比如1,-1000࿰c; 10001-2000 这样取名字 (2)如果有范围查询的需求࿰c;可以虑转换为zset来处理范围查询࿰c;按照时间戳 来进行排序即可 7.外部请求接口很慢࿰c;该怎么排查?服务器资源不足怎么办 (1)服务器扩容 (2)需要预估一个qps࿰c;扩容*120%即可 1.内存使用过高࿰c;频繁gc导致cpu占满 2.内存使用不高࿰c;出现了类似死循环场景 通过第三方监控平台查看堆栈信息 8.lru的加锁࿰c;在操作链表的时候需要加读写锁的

5、货拉拉一面

@H_674_17@1.php-fpm的超时配置࿰c;超时之后会显示什么 (1)Nginx 504 Gateway Time-out的含义是没有请求到可以执行的php-CGI。 (2)Nginx 502 Bad Gateway的含义是请求的php-CGI已经执行࿰c;但是由于 读取资源的程序没有执行完毕而导致php-CGI进程终止。 (3) 502错误是php-fpm控制的࿰c;超时会终止cgi (4) 504是nginx报出的࿰c;代表nginx连接fastcgi超时 2.codis的缺点是什么 (1)master挂掉了࿰c;只能靠运维人员去维护 (2)codis不保证数据一致性࿰c;不支持主从复制 (3)非官方出品࿰c;后续升级没保障 (4)codis不支持事务 3.mysql的死锁产生࿰c;还有如何防止 (1)按同一顺序访问对象。 (2)保持事务简短并在一个批处理中。 (3)使用低隔离级别。 (4)避免长事务࿰c;将事务拆解 (5)设置锁超时等待innodb_lock_wait_timeout 4.mysql分表的查询问题࿰c;怎么不遍历所有表做一个查询 (1)借用redis或者数据表࿰c;存储映射关系࿰c;映射查询字段和分表的关系 (2)找到分表之后࿰c;直接执行查询࿰c;组合数据即可 5.php5.6和7.0的区别࿰c;写代码用到什么新特性了 (1)php7.0之前出现的致命错误࿰c;都改成了抛出异常 (2)增加了空结合操作符(??)。效果相当于三元运算符 (3) php7.0新增了函数的返回类型声明 (4)define 可以定义常量数组 为什么php7比较快: 1、存储变量的结构体变小࿰c;尽量使结构体里成员共用内存空间࿰c;减少引用࿰c; 这样内存占用降低࿰c;变量的操作速度得到提升。 2、字符串结构体的改变࿰c;字符串信息和数据本身原来是分成两个独立内存块存放࿰c; php7尽量将它们存入同一块内存࿰c;提升了cpu缓存命中率。 3、数组结构的改变࿰c;数组元素和hash映射表在php5中会存入多个内存块࿰c; php7尽量将它们分配在同一块内存里࿰c;降低了内存占用、提升了cpu缓存命中率。 4、改进了函数的调用机制࿰c;通过对参数传递环节的优化࿰c;减少一些指令操作࿰c; 提高了执行效率。 6.laravel,yii࿰c;ci的区别࿰c;laravel的特点?控制反转?依赖注入? (1)laravel社区最活跃࿰c;支持的扩展也多 (2)yii的配置文件比较麻烦࿰c;不过支持多种环境配置 (3)laravel的路由比较强大࿰c;但是基于组件式࿰c;稍微臃肿点 (4)yii的view和model层不太好用 控制反转:和依赖注入配合使用࿰c;只不过是用容器去绑定依赖࿰c; 这样相当于控制权给到了容器。 依赖注入:不用在程序里实例化类࿰c;可以通过参数的形式注入进去 ci:CI中的超级对象就是当前控制器对象࿰c;它提供了很多属性.($this) 7.composer的自动加载机制 (1)autoload机制 可以使得 php 程序有可能在使用类时才自动包含类文件࿰c; 而不是一开始就将所有的类文件include进来࿰c;这种机制也称为 Lazy loading (惰性加载)。 (2)单个autoload也不方便c;难以维护࿰c;所以就出现了composer: composer 会找到符合 PR4 规范的第三方库的源 将其加载到 vendor 目录下 初始化顶级域名的映射并写入到指定的文件里 写好一个 autoload 函数࿰c;并且注册到 spl_autoload_register()里 8.redis的持久化࿰c;会持久化过期的key吗 (1)aof是以记录命令方式࿰c;所以如果还没过期࿰c;那么不会有变更的命令࿰c; 如果过期c;会在aof日志插入一条del命令。 (2)rdb的话是内存快照方式࿰c;如果持久化时࿰c;key已经过期࿰c;那么不会持久化࿰c; 如果在过期之前就已经持久化了࿰c;那么在恢复数据时࿰c;会判断key是否过期࿰c; 如果过期不会导入。 9.redis和memcache的区别 (1)存储数据安全--memcache挂掉后࿰c;数据没了;redis可以定期保存到磁盘(持久化); (2)灾难恢复--memcache挂掉后࿰c;数据不可恢复; redis数据丢失后可以通过aof恢复; (3)redis数据结构更丰富 (4)Memcached单个key-value大小有限࿰c;一个value最大只支持1MB࿰c;redis最大支持512MB

6、滴滴一面

@H_674_17@1.go的协程比线程轻到哪里了? (1)协程在用户态进行上下文切换࿰c;耗时是线程的30/1。 线程需要:1,000 ~ 1,500 纳秒 (2)协程初始2kb࿰c;线程好几m (3)线程切换:cpu上下文(寄存器),私有的栈࿰c;线程状态等 协程千幻:cpu上下文(寄存器) 缺点:cpu无法实现抢占式调用协程 2.算法题:堆排序 升序----使用大顶堆 降序----使用小顶堆 (1)为什么升序要用大顶堆呢 大顶堆的特点:每个结点的值都大于或等于其左右孩子结点的值࿰c;我们把大顶堆构建 完毕后根节点的值一定是最大的࿰c;然后把根节点和最后一个元素(也可以说最后一个节 点)交换位置c;那么末尾元素此时就是最大元素了 3.go的runtime (1)在把用户写的程序翻译成可执行文件的过程中࿰c;把 runtime 代码塞进了 可执行文件 1)初始化全局变量࿰c; 2)调用每个模块的init函数 3)初始化 GC࿰c;以及初始化 Go scheduler 4) 启用一个协程࿰c;调用用户写的 main 函数。

7、滴滴二面

@H_674_17@1.php的autoload加载机制 //根据类名找到文件 $path = str_replace('_', '/', $class_Name); //直接引入   require_once $path . '.php'; 2.php的数组扩容 (1)有个参数࿰c;当删除的数量比较多时࿰c;先进行rehash计算࿰c;去掉删除的部分 (2)删除比较少࿰c;空间不足࿰c;则扩容+rehash,申请2倍的空间࿰c;然后rehash计算 3.redis的zset结构 (1)数据量小于128或者存储的key小于64则为ziplist 特点是内存连续࿰c;占用空间小 (2)正常情况下是跳跃表࿰c;存在多级索引࿰c;第一层是双向链表结构 由许多层结构组成。 每一层都是一个有序的链表。最底层 (Level 1) 的链表包含所有元素。 如果一个元素出现在 Level i 的链表中࿰c;它在 Level i 之下的链表也都会出现 (3)为什么用跳跃表不用红黑树 (1)跳跃表底层是双向链表࿰c;适合做范围查询 (2)跳跃表的修改࿰c;删除只需要更改相邻节点的指针࿰c;不需要重建树 (3)跳跃表占用的内存比红黑树少一些 (3)zet结构 1)由字典和跳跃表构成。字典让我们查询单个元素的时间复杂度是o(1)c; 跳跃表主要是按照分值对元素排序.范围查询的时候࿰c;时间复杂度是o(loginN) 4.一个请求到php程序的过程 (1)三次握手之后࿰c;请求建立连接࿰c;进入全连接队列࿰c;accept()函数可以取到 (2)Nginx会按照FastCGI协议的消息格式发送数据࿰c; worker进程再按照协议多次read()数据并解析 (3)词法语法分析࿰c;生成语言片段 (4)zend引擎根据opcode调用机器指令 (5)执行用户通过register_shutdown_function()注册的关闭函数 (6)释放资源࿰c;清理符号表࿰c;销毁超全局变量࿰c;重置max_execution_time 等等 5.一个请求到go程序的过程 golang作为常驻进程, 请求第三方服务或者资源(http, mysql, redis等)完毕后, 需要手动关闭连接, 否则连接会一直存在; (1)为什么请求之后要defer关闭 https://www.cnblogs.com/lovezbs/p/13197587.html 如果请求不手动关闭的话࿰c;每个请求都会创建两个goroutIne,y 分别去往这个连接写入请求(writeLoop函数)和读取响应(readLoop函数)࿰c; 且请求结束不会主动释放࿰c;会导致goroutIne不断增加࿰c;导致内存泄露 (2)go的链接复用问题 在go的源码中特意指出࿰c;需要读取rep.body才能复用链接。有时候 我们只读取header做判断࿰c;code不是200就返回错误࿰c;这样的话该链接 就不会复用࿰c;导致出现大量的tcp : rst. --- go作为客户端 1.创建http.Client对象client 2.创建http.request对象req 3.发送请求client.do(req) 4.关闭resp.body.Close() ---- 源码部分 (1)client.do 主要是参数校验࿰c;设置默认值࿰c;调用client.send (2)client.send cookie的装载࿰c;获取Transport对象࿰c;调用http.send (3)http.send 校验请求参数࿰c;超时取消(setrequestCancel)和请求事务: rt.RoundTrip(req) (4)client.setrequestCancel 创建一个协程利用SELEct chan机制阻塞等待取消请求 (5)Transport.RoundTrip 参数校验࿰c;获取缓存的或新建的连接 (6)Transport.getConn 连接池有空闲则取出空闲连接 连接池无空闲则创建新连接 达到最大数量则阻塞࿰c;等待空闲连接 同时开启了两个goroutIne࿰c;分别 读取response 和 写request --- go作为服务端是如何处理的 http.HandleFunc("/Hello", SayHello) (0) 首先调用http.HandleFunc 往DefaultServeMux的map[String]muxEntry中增加对应的handler和路由规则 (1)http.ListenAndServe(":9090", nil) //设置监听的端口 (2)ListenAndServe内部使用Net包调用了 net.Listen("tcp", addr) 来监听端口 --- 接收客户端请求 (1)启动for循环࿰c;使 Listener 不断地接收来自客户端的请求࿰c;accept (2)给每个请求实例化一个conn,serve.NewConn (3)调用go c.serve启动协程࿰c;用户的每一次请求都是在一个新的 goroutIne中服务࿰c;互相不影响 --- 处理请求 (1)分析请求࿰c;取出请求体resp,req (2)根据ServeMux 路由规则管理器map࿰c;判断请求分发给哪些handle (3)我们注册的函数会转化为handleFunc类型࿰c;然后通过 handler.servehttp(resp,req),从而实现请求处理 6.gin框架的接口会开启协程吗 答:会的࿰c;参照上面的请求流程 客户端:每次请求开启两个协程࿰c;负责读写 服务端:每次开启一个协程处理请求 7.外部怎么访问k8s的pod (1)nodeip: service设置为nodeIP类型c;集群外就可以使用K8s任意一个节点 的IP加上30000端口访问该服务了࿰c;kube-proxy会自动将流量以轮询的方式转发给 该service的每一个pod。 (2)LoadBalancer:公有云提供的负载均衡器。 任意节点的IP加30051端口访问服务 10.97.121.42:30051 使用EXTERNAL-IP来访问࿰c;这是云供应商提供的负载均衡IP (3)ingress K8s管理的负载均衡容器࿰c;它的镜像包含一个nginx或HAProxy负载均衡器和 一个控制器守护进程 外部访问URL,访问该服务࿰c;入口是80端口࿰c;然后Ingress controller直接将流量 转发给后端Pod࿰c;不需再经过kube-proxy的转发࿰c;比LoadBalance方式更高效 8.k8s的服务发现 (1)通过service实现的 (2)etcd是干什么的 https://zhuanlan.zhihu.com/p/96721097 etcd 是一个分布式的、可靠的 key-value 存储系统࿰c;它用于存储分布式系统 中的关键数据。 使用Raft 一致性算法来实现分布式一致性 服务注册: (1)提交服务配置࿰c;创建service对象࿰c;创建endpoint对象 (2)DNS监控service变化࿰c;注册服务 服务发现: (1)kube-proxy 监控ep变化࿰c;通过IPVS修改路由规则࿰c;去往service流量转向pod (2)服务通过DNS和service name 寻找 cluster ip (3)流量转发给 cluster ip,随后被路由规则转给 对应POD (4)kube-proxy 监控 pod࿰c;一旦发现 pod 服务变化࿰c;将会把新的 ip 地址更新 到 service。kube-proxy 更新的存储在 etcd 里的映射关系(ep) 9.dns解析步骤 1)操作系统会先检查自己本地的hosts文件是否有这个网址映射关系 2)如果hosts里没有这个域名的映射࿰c;则查找本地DNS解析器缓存 3)查找本地DNS服务器࿰c;也就是配置中的首选dns服务器 4)转发模式:把请求转发到上一层dns服务器࿰c;不断转发 5)非转发: 先发送到13台根服务器࿰c;根服务器返回顶级域名服务器的ip࿰c; 客户端访问该ip࿰c;然后由顶级域名服务器进行下一级的查询 6)为什么根域名只有13台? 答:因为采用udp协议减小开销࿰c;dns规定512字节的传输上限࿰c; 一次返回最多返回13个根域名记录 10.redis集群的分布式是什么样子的 不同的服务在不同的节点上。这些服务组合起来才是完整的功能࿰c; 这就是分布式。

8、b站B部门二面

@H_674_17@1.k8s的服务发现࿰c;服务注册࿰c;服务调用是为了什么 服务注册: (1)提交服务配置࿰c;创建service对象࿰c;创建endpoint对象 (2)DNS监控service变化࿰c;注册服务 服务调用: (1)有两种方式࿰c;一种是RPC方式࿰c;另一种是事件驱动(Event-driven)方式࿰c;也就是发消息方式 服务发现: (1)kube-proxy 监控ep变化࿰c;通过IPVS修改路由规则࿰c;去往service流量转向pod (2)服务通过DNS和service name 寻找 cluster ip (3)流量转发给 cluster ip,随后被路由规则转给 对应POD (4)kube-proxy 监控 pod࿰c;一旦发现 pod 服务变化࿰c;将会把新的 ip 地址更新 到 service。kube-proxy 更新的存储在 etcd 里的映射关系(ep) 2.k8s我们发布服务的时候࿰c;怎么进行一个平滑启动 答:https://yuerblog.cc/2019/12/11/k8s-%E5%A6%82%E4%BD%95%E5%B9%B3%E6%BB%91%E5%8F%91%E5%B8%83%E5%BA%94%E7%94%A8%EF%BC%9F/ 上线: 1)POD上线需要配置健康检查 2)健康检查通过࿰c;service才会将POD加入endpoints列表࿰c; 流量进入可以正常响应 下线: 1)POD下线时会在etcd中先标记POD状态为terminaTing退出中࿰c; 其他相关联动资源会监听到变化并采取后续动作。 2)先关闭监听࿰c;处理完已有请求࿰c;退出进程 3.redis集群扩容的一个过程 (1)添加节点 (2)分配hash槽࿰c;可以全部重新分配࿰c; 也可以指定节点分出一部分槽出来 (3)槽迁移 每个节点计算自己的槽࿰c;比如原来节点负责5000个槽࿰c;现在负责4000个࿰c; 则把多余的1000迁移到新节点。主要是迁移槽上的key࿰c; 4.mysql同时读写一行会数据࿰c;会触发锁吗 对于普通SELECT语句࿰c;InnoDB不会加任何锁࿰c;所以读写同时进行没有问题࿰c; 读为快照读࿰c;写为当前读 5.go的map的底层结构 (1)结构:散列表+bucket (2)底层一个数组arr index = hash(key) arr[index] = struct{xxxx} (3)每个bucket中可以存储8个kv键值对࿰c; (4)hash值的低八位和bucket数组长度取余࿰c;定位到在数组中的那个下标࿰c; hash值的高八位存储在bucket中的tophash中࿰c;用来快速判断key是否存在࿰c; 6.redis和MySQl的强一致性如何实现 (1)两段式提交࿰c;引入一个协调者。 事务A和事务B都分为准备和提交阶段࿰c;状态同步给协调者࿰c;任一步骤出问题则回滚 (2)raft算法实现 7.kafka在扩容的时候࿰c;怎么在不影响现有业务的情况下扩容 (1)kafka新增节点࿰c;对其他节点来说是无感知的 (2)在新节点上创建topic,或者迁移topic分区即可 8.redis的热点key如何处理 (1)收集热点key࿰c;比如自己写日志或者用redis提供的命令 (2)加载到内存࿰c;直接在内存中读取 (3)热点key分散࿰c;加个随机数进行分散࿰c;分散到多个redis机器࿰c; 读的时候随机从有备份的redis上读取即可 9.redis集群的脑裂如何避免 min-slave解决。当脑裂之后࿰c;会有一个分区的slave升级为master, 此时根据配置文件࿰c;当slave少于配置个数则停止写入。 这样保证只有一个master提供写入࿰c;等网络恢复也不会有问题 10.es的架构࿰c;index的内部实现 https://blog.csdn.net/u013380694/article/details/101760607 它可以将索引划分为多个分片࿰c;可以部署到集群中的任何一个节点࿰c; 且每个分片都有副本࿰c;实现高可用 (1)它允许水平切分内容卷。 (2)它允许通过分片来分布和执行操作来应对日益增长的执行量。 (3)一个索引就像数据库。而Type就相当于每一张表࿰c; 而mapping就相当于表的结构定义࿰c;定义了什么字段类型等 往index的一个type里添加一行数据就叫做一个document 每一个document有多个field 查询: (1)客户端发送请求到协调节点 (2)协调节点从分片上查询数据࿰c;由协协调节点进行聚合 (3)合并数据࿰c;返回给客户端

9、回响科技一面

@H_674_17@1.kafka多个分区怎么保证消息顺序 (1)首先发送消息可以通过指定key+单分区实现 (2)多个消费者消费的时候࿰c;可以自己对key取模࿰c;放入到队列中࿰c; 开多线程去消费这些队列。队列内是有序的 2.mysql在没有隔离级别的情况下࿰c;多线程修改一行数据可以吗 (1)隔离级别是为了解决事务的并发问题࿰c;比如脏读࿰c;不可重复读࿰c;幻读问题等 (2)当没有隔离级别的时候࿰c;多线程修改一行数据࿰c;就会 出现:原始数据是0.线程1想+1࿰c;线程2也想+1࿰c;那么同时执行࿰c;结果是2࿰c; 但是对于线程1来说࿰c;我只是想+1而已 3.幂等性和线程安全?两个线程修改一个变量࿰c;为什么不行 (1)确保在多线程访问的时候࿰c;我们的程序还能按照我们预期的行为去执行࿰c; 那么就是线程安全。 (2)两个线程修改一个变量是可以的࿰c;但结果可能不是我们想要的 4.redis为什么要有单线程࿰c;除了锁还有其他原因吗 (1)锁开销 (2)不存在多进程或者多线程导致的切换而消耗CPU (3)无法发挥多核CPU性能࿰c;不过可以通过在单机开多个redis实例来完善࿰c; 同时给redis实例绑定cpu核即可发挥多核的优势 5.rpc和http访问的区别在哪 相同点:底层通讯都是基于socket࿰c;都可以实现远程调用࿰c;都可以实现服务调用服务 不同点: (1)速度来看࿰c;RPC要比http更快࿰c;然底层都是TCP࿰c;但是http协议的信息往往比较臃肿 (2难度来看࿰c;RPC实现较为复杂࿰c;http相对比较简单 (3)如果对效率要求更高用rpc࿰c;灵活性通用性要求高用http (4)rpc是长连接࿰c;http是短连接࿰c;效率更高 (5)rpc可以压缩消息࿰c;实现更极致的流量优化 6.mysql直接修改库存有什么问题? (1)没什么问题࿰c;主要是怕mysql承受不住太大的流量挂掉 (2)常规方法是库存设置无符合࿰c;不能是负数࿰c;使用事务࿰c; 代价是速度比较慢 (3)我们可以虑使用乐观锁࿰c;查询出version࿰c;修改的时候根据version来修改 7.go中的锁是怎么实现的 互斥锁:通过状态status和信号量来实现的。 协程1加锁的话࿰c;lock=1 协程2加锁的话࿰c;waiter=1࿰c;代表等下 锁释放: 协程A主要是通过释放信号量来通知协程b࿰c;此时协程B可以加锁 自旋:加锁失败会持续请求加锁࿰c;不会立刻阻塞。是通过cpu的空转实现的࿰c;30个时钟周期 8. redis的rdb和aof过程大概说一下

10、全民快乐一面

@H_674_17@1.go常用的包有哪些࿰c;说说http和io包的函数 2.php的Trait函数࿰c;Trait引用的方法和原父类方法哪个优先级比较高 父级使用Trait关键字࿰c;当前类 通过use使用父类 (1)代码复用࿰c;相当于copy了一份代码 (2)类成员优先级为:当前类>Trait>父类 3.mysql主从不一致的原因࿰c;在配置一样࿰c;虑网络因素的情况下 (1)主从两台机器的负载不一致࿰c;线程忙不过来 (2)max_allowed_packet ࿰c;主库设置的大࿰c;当有大sql的话࿰c;从库无法执行 (3)自增键不一致 ࿰c;自增步长不一致导致 (4)同步参数未设置 =1 4.go的chAnnel怎么保证线程安全的 (1)chAnnel内部维护了一个互斥锁࿰c;来保证线程安全 5.100W用户刷视频࿰c;怎么保证用户刷的视频不不重复 6.php安装扩展的步骤࿰c;编译的命令是哪个 1.  wget extension.tar.gz下载相应的扩展包并解压。 2.  cd extension/切换到扩展extension的目录中 3.  /php/bin/phpize 运行php安装目录下的phpize文件࿰c; 这时候会在extension目录下生成相应的configure文件。 4.  /configure --with-php-config=/php/bin/php-config 运行配置࿰c; 如果你的服务器上只是装了一个版本的php则不需要添加--with-php-config 。后面的参数只是为了告诉phpize要建立基于哪个版本的扩展。 5.  make && make install 编译模块 7.唯一索引和主键索引的区别 (1)一个表只能有一个主键索引࿰c;可以有多个唯一索引; (2)主键索引一定是唯一索引࿰c; 唯一索引不是主键索引; (3)主键可以与外键 构成 参照完整性约束࿰c; 防止数据不一致。

11、货拉拉二面

@H_674_17@1.kafka保证消息顺序性写入 生产者发送消息的send有四个参数 (分区号、时间戳、key、headers)࿰c;我们可以指定key࿰c; 来保证消息都发送到同一个分区 2.php的while..true常驻进程会造成什么影响 3.缓存击穿和缓存穿透 (1)缓存击穿࿰c;redis额热点key过期 1)不给热点key设置过期时间 2)互斥锁࿰c;发现无缓存࿰c;加锁去更新缓存 (2)缓存穿透是redis+mysql都顶不住了 1)参数校验࿰c;防止不存在的key 2)布隆过滤器 3)缓存空值或者默认值

12、b站B部门三面

@H_674_17@1.接口网络超时如何排查 (1)代码层面 1)下游sql等查询是否超时 2)数据库连接是否满了࿰c;代码中是否出现死循环等 占用大量的cpu和内存 (2)网络层面 1)运营商网络问题 2.kafka的offset和MySQl的索引的区别 kafka索引: (1)偏移量索引文件用来建立消息偏移量(offset)到物理地址之间的映射关系࿰c;便快速定位消息所在的物理文件位置; (2)时间戳索引文件则根据指定的时间戳(timestamp)来查找对应的偏移量信息。 查找步骤: (1)根据offset找到日志分段的索引文件(.index文件) (2)读取偏移量索引索引文件࿰c;使用二分找到最大索引项 (3)读取日志分段文件并且从日志分段文件中顺序查找(.log文件) relativeOffset对应的消息 区别: (1)kafka是系数索引࿰c;R_998_11845@ysql是b+树索引 (2)kafka维护索引使用了跳跃表结构࿰c;索引维护结构不会随便变动࿰c;有新索引 文件才更新。mysql的索引树更新比较频繁 (3)应用场景不同࿰c;kafka是主要是顺序写入࿰c;顺序读出࿰c;很少有检索的操作。 3.x=1 and y>1 order by z如何建索引

13.好未来一面

@H_674_17@ 1.服务间通信的实现 微服务必须使用进程间通信机制来交互࿰c;微服务架构 异步消息机制和同步请求/响应机制这两类 IPC 机制可用 2.服务探针的实现 存活探针:为了查看容器是否正在运行࿰c;如果返回false则重启pod 就绪探针:查看容器是否准备好接受http请求,通过则把流量发到pod上 存活探针和就绪探针被称作健康检查。 3.进程࿰c;线程间的通信方式 进程-------- 1)管道( pipe ):一般是父子进程通信 2)信号量:主要作为进程间以及同一进程内不同线程之间的同步手段 也是一种锁机制 3)共享内存:最快的ipc通信 4)套接字:可用于不同的进程通信。 5)消息队列:由消息的链表࿰c;存放在内核中并由消息队列标识符标识 线程---------------- 线程间的通信目的主要是用于线程同步࿰c;所以线程没有像进程通信中的用于 数据交换的通信机制。 1)锁机制:包括互斥锁、条件变量、读写锁 2)信号量机制(SemaphorE):包括无名线程信号量和命名线程信号量 3)信号机制(Signal):类似进程间的信号处理

14、映客一面

@H_674_17@ 1.手写lru 2.mysql的acid分别是怎么实现的 Atomicity)原子性: 事务是最小的执行单位࿰c;不允许分割。原子性确保动作 要么全部完成࿰c;要么完全不起作用; (1)通过undo日志࿰c;事务回滚时能够撤销所有已经成功执行的sql语句 (consistency)一致性: 执行事务前后࿰c;数据保持一致; (1)一致性是事务追求的最终目标࿰c;前问所诉的原子性、持久性和隔离性࿰c; 其实都是为了保证数据库状态的一致性。 (isolation)隔离性: 并发访问数据库时c;一个事务不被其他事务所干扰。 (1)四种隔离级别实现的 (Durability)持久性: 一个事务被提交之后。对数据库中数据的改变是持久的࿰c; 即使数据库发生故障。 (1)Innnodb有很多 log࿰c;持久性靠的是 redo log。 (2)如果出现缓冲丢失࿰c;可以从redo logo日志中恢复 3.go的syncmap怎么实现并发安全的 (1)步骤 a、过 read 和 dirty 两个字段将读写分离࿰c;读的数据存在只读字段 read 上࿰c; 将最新写入的数据则存在 dirty 字段上 b、读取时会先查询 read࿰c;不存在再查询 dirty࿰c;写入时则只写入 dirty c、读取 read 并不需要加锁࿰c;而读或写 dirty 都需要加锁 d、另外有 misses 字段来统计 read 被穿透的次数(被穿透指需要读 dirty 的情况)࿰c;超过一定次数则将 dirty 数据同步到 read 上 e、对于删除数据则直接通过标记来延迟删除 (2)原理 sync.map实现就是依靠两张map对读操作和写操作分离࿰c;后续根据需要在把 dirty map合入 read map中。 4.tcp的timewait怎么产生的࿰c;如何防范 作用: (1)保证服务器能收到最后一次ack (2)同时2msl能保证旧报文消失࿰c;防止旧报文出现在新的连接中 防范: (1)服务器设置套接字:so_reuseaddr (2)短连接改成长连接 (3)linux内核参数:net.ipv4.tcp_tw_reuse 5.介绍项目的时候࿰c;最好是把技术栈各方 面都详细的说一下 6.插入100W数据࿰c;大概耗时多少࿰c;如何优化?批量插入的时候会影响 其他操作吗࿰c;如何优化? 7.redis的分布式锁在高并发情况下会出现什么问题 (1)锁续约问题࿰c;可以用redisson的看门狗机制 (2)锁超时时间一定要设置 (3)根据value上锁࿰c;防止释放锁混乱 (4)分布式场景下࿰c;R_998_11845@aster加锁之后挂掉࿰c;slave会成为新的master 此时A客户端认为自己上锁了࿰c;B客户端也能获取到锁࿰c;会造成锁混乱 使用redlock会好一些 8.https到底是对称加密还是非对称加密? 答:是非对称加密(公私钥) +对称加密(传输内容对称加密) 1.客户端请求服务端࿰c;获取公钥。 2.服务端生成公私钥࿰c;自己保存私钥(SK)࿰c;将公钥(PK)发给客户端。 3.客户端生成随机字符串key࿰c;通过公钥(PK)加密后发送给服务端。 4.服务端拿到加密后的内容后࿰c;用自己的私钥(SK)进行解密࿰c;得到key, 后续的过程都是通过密钥(key)来进行对称加密来传输。

15、小猪民宿

@H_674_17@1.php的worker线程假死࿰c;如何重连的 (1)首先࿰c;php-fpm假死一般是线程繁忙或者请求数过多࿰c;超时等原因࿰c; 主要是修改配置文件࿰c;增加请求数量限制࿰c;超时时间等。 (2)kill掉worker之后࿰c;R_998_11845@aster进程会自动创建一个work出来 2.设计php框架的问题 3. mysql的查询优化器工作原理 (1)主要是判断cost࿰c;cost包括扫描行数等 (2)参照mysql拾遗 4.单机多少配置才能顶住1000qps 参https://blog.csdn.net/weixin_34346099/article/details/88679411 假如机器是4核8G: (1)同时处理的请求做多4个 (2) 假设一个进程30M࿰c;那么4048/30 = 135(留一些给mysql) (3) 假设一个请求200ms࿰c;那么1000qps要求 T = (1000 / n ) * t 总耗时:T 一次处理请求:n 每次请求时间:t 200ms (4) 根据计算可以得知࿰c;我们一次要处理200个请求才行 首先我们的worker进程是足够的࿰c;其次是4核也够用 (5 )其他需要注意的点 1)mysql连接数 2) 服务器句柄限制࿰c; ulimit -n查看 3)tcp的timewait影响࿰c;允许端口复用 5.压测需要注意的参数 1)qps 2) 请求处理时间 3)

16.滴滴二面

@H_674_17@1.一致性hash (1)对2的32次方取模࿰c;构造0-2的32次方哈希环 (2)对服务器的IP或主机名作为关键字进行哈希 (3)计算key的hash࿰c;计算出在哪个空间࿰c;顺时针往下寻找节点即可 (4)为了防止数据分布不均匀࿰c;构造虚拟节点 (5)节点宕机࿰c;只会影响不一部分数据࿰c;其他节点还能正常使用 2.两个文件a和b里面都是id࿰c;求出不同的id (1)分治࿰c;hash(id)%1000࿰c;分成1000个小文件,a0...a99 (2)此时a99中的id肯定也在b99中࿰c;文件就转化为了对小文件的求去重 (3) 读取a0࿰c;构造hash表࿰c;便遍历b0࿰c;如果a0中不存在则为不重复 的id࿰c;放入新集合中即可 4.myisam的应用场景 特点:高性能读取࿰c;存储的有行数࿰c;无事务 场景:(1)需要频繁count的场景 (2)读多写少的场景

17.百度1-5面

@H_674_17@大部分八股文跟上面雷同࿰c;只记录不同的 1.对于团队管理的理解 2.项目的架构设计࿰c;为什么这么设计 3.字符串中࿰c;中括号࿰c;大括号࿰c;小括号࿰c; 判断是否匹配(算法) 4.乱序数组࿰c;构建二叉树(算法)

三、后记

      以上就是博主历时2个月的面试记录了。提醒大家一定要刷算法题࿰c;博主基本都是倒在算法题上面。其次面试看运气࿰c;不要在意࿰c;面就完了。

end

大佬总结

以上是大佬教程为你收集整理的2021中大厂php+go面试题(2)全部内容,希望文章能够帮你解决2021中大厂php+go面试题(2)所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。