> 本文来自我们技术交流群群友的投稿,未经授权,禁止转载。
原文链接:太难了,Java和Go,面试了30多场,终于上岸了!
2023年10月份我就做好了离职跳槽的准备,做了3年Java后端开发的我,对自己的技术能力还是很有底气的。之前虽不是一线大厂,也算是比较知名的中厂了。
加上前公司各种不合理的排期和需求,我感觉就是变相裁员,我这暴脾气可不惯着这个。
我就请假约面试,没想到,被社会毒打了,Java太卷了,要求好高,各种拷打底层。(加上我对Java确实不太感冒)另外我不是科班出身,是文转码,难顶呀
之前公司有事业部使用Go语言,那时候也了解了一些,加上不少Java群都在聊Go语言,我也准备转Go试试。做两手准备吧,这样能更稳妥一点。
哎,公司各种变态需求和排期。我们心里都清楚公司是咋想的,我的很多同事都准备耗着,等补偿。
我最开始也是这个想法,但是说实话,这种上班的日子每天都是煎熬。
之前也累,是加班赶项目的累。
现在的累,是心里累,内耗的累,太难受了,在公司工作也不痛快,新东西也学不下去,很难做跳槽准备呀。
想请假面试也不批,咋搞!?
老子不惯着,裸辞了!
2024年元旦过后没几天我就裸辞了!
因为之前公司太累了,裸辞之后踏踏实实在家里休息了半个多月,睡到自然醒,自己做饭、遛弯、打球、逛街、爽。
然后也该准备好工作了,给自己制定计划,准备踏踏实实学Go。我准备做Java和Go做两份简历出来。
我觉得只是换个语言,问题应该不大,之前的项目经验也是很丰富的,学呗!
我计划是2024年3月底4月初能拿到Offer就行,反正手里的钱也够花。不着急呢。
春节也踏踏实实过,提前回家过年。
春节之后突击一下,把Go基础和并发编程好好搞搞,还有之前的项目经验,好好梳理一下。然后就是各种突击八股文,学!学!学!还是学!
另外坚持每天健身,好身体才能有好状态嘛!
春节之后,我是从3月份才开始约面的,到3月27号面试了大概20多家公司,参加了30多场面试。终于拿到合适的Offer了。
我本来是想冲一冲字节这样的大厂的,算法也准备的挺充分的,一面自我感觉面试的不错,但是不知道为啥没过…
后来分析,可能是被卡学历,卡专业了吧
目前手上有2个Offer,选择了其中更合适的一家,薪资涨幅不小,对得起我这两三个月的付出。
好了,下面我就给你分享一下我的Go面经,也祝大家能早日上岸,顺利找到工作:
1.slice切片(一定看底层结构体实现)
2.GMP模型
3.聊聊什么是锁. Mutex, RWMutex, redis分布式锁。
这块聊的很深, 差不多10分钟,甚至问了锁的状态在硬件上是怎么记录的
4.go的GC原理以及写屏障是什么
5.docker的六大命名空间?
每个容器有自己的命名空间, 包括网络,进程,IPC, 文件系统等. 通过这种方式, 容器之间相互完全隔离, 不会相互影响
- 进程命名空间: 为每个容器创建一个新的进程进程ID(PID)空间, 使得容器内的进程看起来像是独立的操作系统中的进程
- IPC命名空间:
- 网络命名空间
- 挂载命名空间
- UTS命名空间
- 用户命名空间
6.网络七层模型?
应用层, 表示层, 会话层, 传输层, 网络层, 数据链路层, 物理层
7.算法:
8.mysql如何存储ip地址比较合适?如何查询效率比较高?
- 使用varchar存储 浪费空间,无法直接实现范围查询
- 使用int数值存储 占用空间较小
- 使用binary二进制位存储
1.https和http的区别?
2.https的加密是对称加密吗?
内容传输是对称加密, 证书校验是非对称加密
3.浏览器输入谷歌地址, 请描述整个访问过程发生了哪些步骤?
4.tcp三次握手四次挥手? 如果只有两次会出现哪些问题?
5.聚簇索引和非聚簇索引的区别?
6.b+树索引的特点?
7.DNS域名解析过程
8.一道sql题
数据库中有以下两张数据表:
广告表
表名:ad
字段:id, title, create_time
订单表
表名:order
字段:id, ad_id, cost, create_time
请写一条 SQL,查询订单数量最多的前十条广告,并返回以下信息:
广告ID、广告名称、订单数量总和、订单费用总和。
1.grpc底层用的什么协议?
http2.0
2.http2.0和1.1的区别?
- 多路复用: 1.1每个请求必须是独立的TCP请求, 2.0采用多路复用, 一个TCP连接可以进行多次请求, 大大提升性能
- 数据传输: 2.0引入数据流的概念, 允许不同请求在同一连接交错发送
- 头部处理: 2.0 采用HPACK算法对头部数据进行压缩, 降低数据大小和网络开销
- 二进制协议: http/1.1报文头信息必须是文本, 数据体可以是二进制,也可是文本。2.0 头信息和数据体都是二进制, 更加高效的处理数据
- 错误处理: 1.1处理错误需要关闭连接, 2.0引入可以在不关闭连接的情况下处理错误
3.gRPC有几种请求模式?
- 简单模式: 客户端发起请求, 等待服务端响应. (例如普通的grpc定义message, 一次请求一次响应)
- 服务端流式(长连接): 客户端发送请求, 服务端返回一个流, 客户端持续监听这个流, 反序列化其中的内容, 返回给用户,适用于客户端需要向服务端发送大量数据的情况, 如文件上传
- 客户端流式(长连接): 客户端创建一个流, 将请求参数以流的方式给服务端, 服务端再返回单个响应, 适合服务端向客户端发送大量数据的情况, 例如实时数据传输
- 双向流式: 允许客户端和服务端同时读写数据. 双方都可以随时开始和结束数据的发送. 适合双向数据传输模式
传统的http连接时短连接, 一次请求一次响应后, 连接就断开了, 然而, 客户端流式RPC和服务端流式RPC模式基于TCP长连接, 用于多次数据交换.
4.protobuf了解过吗? 和有什么区别? 对比json有什么优势? 压缩率对比json来说能达到多少?
和json的对比:
- protobuf使用二进制格式, json为文本格式, 所以protobuf的序列化和反序列化更加高效
- 由于使用二进制传输, protobuf的体积通常更小
- protobuf是强类型的, 定义数据结构时必须指定每个字段的类型, 可以减少解析时的错误, json是弱类型的, 不强制字段的类型
5.var定义slice, 不使用make声明, 可以直接使用吗? 数组可以直接使用吗?为什么
切片不能直接使用. 如果不进行make, 那么切片是nil, 不能直接使用
数组可以直接使用, 数组在创建时已经固定了大小, 会被立即分配内存
6.go中有几种方式可以解决并发安全问题?
1.并发原语2.mutex锁3.channel
7.mysql中,如何判断一个字段是否适合建立索引?
- 该字段是否经常作为查询条件
- 区分度高的字段
- 列的数据类型。文本字段建立索引占据更大空间, 数值字段效率更高
- 更新频率。如果是经常发生写操作的字段,由于需要维护b+树的索引结构,会降低效率。
8.如果让你设计一个消息队列,你会如何设计?需要考虑哪些问题?
9.项目中限流是如何设计的,使用的是go-sentinal.
10.如果让你设计限流器,你如何设计?
令牌桶\滑动窗口算法\漏斗算法
口述用户注册功能的整个流程, 如果两个请求同时使用相同用户名进行注册, 如何保证注册逻辑正确
算法: 合并区间
1.一个访问url是如何找到微服务的?
2.一次完整的url请求过程
3.RPC协议了解吗?grpc协议了解吗?
4.restful请求和RPC协议的区别?
5.rpc通常是长连接还是短连接?
6.webSocket是长连接还是短连接?
7.主键索引和非主键索引的区别?
8.mysql中union和union all的区别?
union: 对两个结果集进行并集操作, 不包括重复行, 相当于distinct, 同时进行默认规则的排序
union all: 对两个结果集进行并集操作, 包括重复行, 即所有结果全部显示, 不管是否重复
9.exist和in的区别?
in函数执行的原理:
先查询in中的语句, 讲结果缓存, 然后使用主查询结果, 匹配in中的缓存结果, 所以in中的数据量如果是比较小的, 那么查询效率快, 否则拖慢查询
10.索引优化?
11.context是如何使用的?
12.引用类型有哪些?
13.map是线程安全的吗?
14.go中的struct能否进行比较?
15.range迭代map是有序的吗?
16.场景: 制作登录系统, 允许手机端, pc端, 平板端多端登录, 一旦有一端修改密码, 其它端登陆态失效, 如何设计?
17.给定一个整数数组, 判断该数组是否有序(注意: 升序或者降序都判断为有序)
1.介绍一下gin中的中间件? (如何自定义一个中间件)
2.gin的拦截器有c.next放行的方法, 那么它是如何做到执行完毕链路方法之后, 又返回到当前拦截器位置的呢?
c.next() c.abort()
gin的中间件实际上还是gin.HandlerFunc, 和其它处理器是一样的
执行完next之后, 又返回当前中间件的特性, 依赖go语言的闭包和函数运行栈实现.
执行next放行后, 将当前函数入栈, 直到遇到c.Abort()返回, 然后根据原来的链路反向执行回去, 而且闭包允许引用函数外的变量和函数,返回时可以直接正常运行
3.切片的扩容机制?
4.内存对齐?
内存对齐是计算机硬件对内存数据访问的一个优化手段。当数据在内存中的地址是某个固定大小的整数倍时,处理器访问该数据的速度会更快。
这种优化可以减少处理器访问内存的次数,提高程序的运行效率。
例如,一个int32类型的变量在32位处理器上通常需要对齐到4字节的边界,而在64位处理器上可能需要对齐到8字节的边界。如果不对齐,处理器在访问这些数据时可能需要进行额外的内存操作,这会影响程序的性能。
5.索引? 回表查询?
6.mysql中的数据是如何加载到内存中的, 如何写入到磁盘中的?
7.开启了事务, 刚执行完插入, mysql宕机, 如何保证的这条数据不插入成功
8.redis是怎么使用的? redis的订阅和发布?
9.http状态码: 1开头的
10.get和post的区别? (网络层面)
11.给定两个数组, 求两个数组的交集
12.数组长度为30亿, 最小数字为1, 最大数字为35亿, 判定给定的数字是否出现在数组中
1.假设有一台本地及其,无法做加减乘除运算, 我们提供了一个服务器端的Http API, 可以串两个数字类型的参数, 响应结果是这两个参数的和, 请写一个高效的函数, 调用远程方法, 计算出结果
2.redis常用的类型? 以及使用用途
3.场景: 基于redis实现限流, 每分钟限定用户只能访问100次, 如何实现?
使用sort set, 分数设置为访问时间, 访问时间-60秒, 判断有多少个请求, 如果大于100, 则不允许请求
4.mysql失效场景?
mysql自动评测,如果数据量小, 不走索引, 当使用order by时, 如果发现走索引的效率比较慢, 也会舍弃索引
5.索引优化做过哪些优化?
6.最左前缀法则的原理是什么?
7.id, name两个字段, where name like %abc%, 有1000万数据, 怎么进行优化?
先根据name查询id, 再根据id查询出所需要的字段
8.prometheus怎么使用的? 存储类型是什么?
9.kafka如何保证的消息有序?
10.有并发场景吗?
11.讲一下整个服务的组件链路
1.waitGroup, 如果有一个协程卡死了, 不返回context处理, 定义超时时间, 和公共状态, 如果出错了, 协程中使用context处理超时, 并且讲公共装填设置为true
2.你们的流量表数据量有多大?
3.抓取一次接口数据要响应时间要多久?
4.缓存?
5.输出100个100以内加减法
1.每天的线索量有多少?
2.GMP模型
3.Innodb的ACID是如何保证的?
4.微博热搜功能如何实现? 小顶堆+redis排序
5.给定a,b两个字符串, 判断字符串b是否为字符串a的子串
1.http和https的区别?
2.https用的是对称加密还是非对称加密?
3.b+树索引结构的特点? 底层的叶子节点起到的作用是什么?
4.聚簇索引和非聚簇索引的区别?
1.表中数据量有多大?
2.哪些适合内存存储? 哪些适合mysql查询?
3.索引优化?
4.开发使用的是什么框架? 如果要实现接口鉴权效果, 怎么实现?
5.了解规则引擎吗? 如果自己设计状态机, 如何设计?
6.场景题: 一个日志文件, 有100万行, 其中每一行可能出现重复的日志, 请找出前50条重复次数最多的日志
7.小顶堆排序的时间复杂度是多少?
8.有使用过channel吗
9.sql执行慢的原因? 如何排查?
- 查看是否建立了索引, 索引是否生效。解决方案: explain查看索引命中情况,以及查询时间
- 单表数据量过多,导致查询瓶颈。解决方案:水平分表,垂直分表,分库: 例如已经拆分万1000张表,将0-100放到同一数据库实例中,将100-200放到另外一个数据库实例中,依此类推把1000张表存放到10个数据库实例中。 这样根据业务主键将请求路由到不同的数据库实例, 从而让每个数据库实例的流量比较小, 达到提高数据库性能的目的。
- 网络原因导致机器负载过高,可以部署一主多从的mysql集群,提高mysql的查询处理性能
- 热点数据导致单点负载不均衡。
10.进程与线程的区别:
- 本质区别:进程是操作系统分配资源的最小单位,线程是处理器任务调度的最小单位
- 包含关系:一个进程至少有一个线程,线程是进程的一部分
- 资源开销:同一进程内的线程共享进程的地址空间,每个线程都有自己独立的运行栈和程序计数器,线程间切换的开销小
4.影响关系:一个进程崩溃后,其它进程不受影响。 一个线程崩溃,可能导致所属进程被系统杀掉
11.slice的扩容机制:
go1.18版本后, 扩容使用threshold为临界点(源码中设置为256)
当slice容量 < 256时, 每次扩容为原来的两倍。当slice容量 > 256时, 每次增加(oldcap + 3*threshold) 3/4
12.tcp和udp的区别?
- 连接: tcp需要建立连接 udp不需建立连接
- 服务对象: tcp是一对一, udp可一对一, 一对多
- 可靠性: tcp可靠, 有序, udp不可靠, 无序
- 拥塞控制,流量控制: tcp拥有拥塞控制和流量控制, 保证数据传输的安全性, udp即使网络非常拥堵, 也不影响udp的发送速率
- 传输方式: tcp为流式传输, 没有边界, 但保证顺序和可靠, udp是一个包一个包发送, 有边界, 但是可能丢包或乱序
- 首部开销: tcp的首部开销大, udp的首部只有固定的8字节,开销小
13.restful请求?
get: 表示读取服务器上的资源
post: 表示在服务器上创建资源
put: 表示更新或者替换服务器上的资源
delete: 表示删除服务器上的资源
patch: 表示更新/修改资源的一部分
14.restFul请求和http请求的区别?
http 是一种应用层协议, 它定义乐客户端如何与服务器进行通信, 包括请求和响应的格式.
restFul是一种软件架构风格, 依赖于http协议来实现, 然后根据对资源的不同操作类型, 划分为不同的restful请求
15.什么是grpc? protobuf/json区别与优势?
- grpc是远程调用框架,基于http2.0实现,允许在计算机之间进行跨语言,跨平台通信,使得构建分布式系统更加简介高效
- grpc使用protocol buffer作为默认序列化机制,比json更加高效
算法1: 顺时针旋转矩阵
算法2: 合并区间
1.介绍一下业务表的字段
2.定时任务刷新字段, 是怎么实现的?
3.分布式锁? 分布式死锁如何解决? 看门狗机制? 如何避免当前线程加的锁, 被其它线程解锁?
4.乐观锁和悲观锁的区别? 写多读少的情况, 应该使用乐观锁还是悲观锁?
5.分布式场景下, 如何实现乐观锁?
6.kafka的幂等性? 如何避免消息被重复消费?
7.两个线程, 同时向mysql中插入一条数据?
8.kafka如何保证消息不丢失
9.sql优化场景:
select id,name,balance from account where update_time > '2020-09-19' limit 100000, 10
该语句为什么查询慢? 有什么优化思路?
1.http和gRpc的区别?
2.mysql,redis,mongoDB,ES 说说如何根据使用场景,选择对应的存储组件?
3.线上的接口性能差, 如何排查和提高?
4.redis常见的数据结构?
5.找出链表的倒数第N个节点。如何判断链表有环?
6.分库分表如何设计?
场景: 例如本订单表是按照id进行的分表, 但是有的查询, 需要根据id进行查询, 有的查询需要根据活动id查询, 如何实现这个分表方案?
- 按照id进行分表 再按照活动id进行分一次表
- 如果事务要求不高, 可以将活动的数据同步到ES, 使用es进行相关查询
- 效率高:protobuf使用二进制编码,编码解码速度更高,体积更小
- 可读性: 虽然protobuf是二进制格式,但是其定义文件是可读的,大型数据结构情况下,更加易于维护和理解
- 跨语言支持:protobuf支持多种编程语言
8.redis中的数据类型?底层结构?
redis list的逻辑类似双向链表,每个节点有next,prev两个指针,和一个value指针真正存储值,如果单纯使用双端链表,会出现问题
- 如果每个node节点中,value指针指向的数据很小,比如只存储了一个int值,那么prev,next指针占据的Node节点的绝大部分的空间,真正存储数据的有效负载就很低,链表节点出现很多的话,就会出现很多不连续的内存碎片
- 链表查询时,需要沿着链表顺序进行查询,所以双端链表的查找效率低
redis7.0前的版本为解决上述问题,实现了quickList的结构,将Node节点的value指针,指向一个ziplist实例,ziplist是一块连续的空间,可以存储多个list的元素,这样quickList与普通链表相比,Node节点数量会更少,内存碎片也更少,而且一个Node中存放了多个元素,prev,next指针占据的空间比例很少,有效负载变得很高
ziplist虽然是一块连续空间,但是不能像数据一样进行随机访问,查找元素的时候同样需要从头开始扫描,但是ziplist是一块连续空间,就不会像Node查找一样有很多指针解析的开销,数据量少时,迭代一遍的效率比较快
9.渐进式rehash?
在resis使用过程中,当哈希表已经到达容量上限,redis通过rehash进行rehash进行扩缩容。但是,redis执行命令时单线程模型,对当前哈希表进行rehash时,一次rehash操作可能导致服务器出现阻塞并停止对外服务。为解决该问题,使用渐进式rehash方案,就是将rehash分为多次完成。在redis中,字典数据结构底层使用两个全局哈希表实现,为方便理解称之为哈希表1和哈希表2。另外,字典还维护一个rehashIdx字段,来记录rehash操作的下标位置,初始值为-1,代表未进行rehash操作
渐进式rehash的详细步骤:
- 首先为哈希表2分配空间,默认长度时哈希表1长度的2倍
- 设置索引计数器变量rehashInx为0, 表示rehash工作正式开始
- 在rehash进行期间,每次对字典执行增删改查操作时,除了执行指定的操作以外,还会把哈希表1在当前rehashInx索引上的所有键值对rehash到哈希表2。 当rehash操作完成之后 rehashInx属性的值就会+1
- 随着字典增删改查操作的不断执行,最终所有键值对都会被rehash到哈希表2中。rehash操作完成之后,哈希表1table数组的指针指向哈希表2 table数组的指针, 哈希表2 table数组的指针指向 null, 并将 rehashIdx 属性的值设置为-1, rehash操作完成
注意:
- 在渐进式rehash进行期间,字典的删除,查找,更新等操作,会在两个哈希表上运行
- 在渐进式rehash执行期间,字典的添加操作权在 哈希表2 上进行
- rehash后新的下标为N或者N+size,N+为原下标,size为原数组大小
10.分库分表:如果分表策略, 不能满足查询条件要求, 怎么处理?
方案1: 按照多个查询条件, 拆分为多个冗余表。方案2: 例如按照id拆的,那么正常拆,正常拆,不重要的查询字段, 将数据同步到es中, 走es查询
1.kafka如何做的容灾?
2.kafka的性能为什么高?
3.用户态和内核态?
4.mysql的容灾如何做的?
5.mysql从库的同步模式?
- 异步复制: 默认为异步同步. 主库提交事务后, 立即返回给客户端, 不关心从库是否已经接收并处理.问题: 如果主库宕机, 由于主库数据没有同步到从库, 可能导致数据丢失
- 全同步复制: 主库执行完事务, 必须等到所有从库执行同库完毕, 才算事务执行成功
- 半同步复制: 主库至少需要等待一个从库接收并写入RelayLog文件即可.
6.数据库的事务隔离级别是什么? 遇到过幻读吗? 如何解决幻读?
幻读: 当前事务查询不到对应数据, 但是插入该数据插入不进去
7.mysql中有哪些锁?
行级锁, 表级锁
8.go如何启动一个协程?
9.协程和线程的区别?
10.进程和线程的区别?
11.有线程为什么还需要协程? 主要是对线程的哪个问题进行了优化?
12.linux的硬链接和软连接?
13.go的内存逃逸?
14.interface一般都是怎么使用的?
15.https如何保证的安全?
16.https连接的密钥流程?
公钥是公开的, 私钥是服务端私有的, 客户端先发送请求,服务端接收请求后, 服务端根据公钥对 响应回公钥
17.time_wait是解决什么问题的?
18.算法: 最长回文子串?
1.协程池的作用?
2.内存逃逸分析?
3.go的内存回收什么条件会触发? go的GC能够手动触发吗?
4.channel的底层实现? 有缓冲的,无缓冲的channel, 如果管道已经关闭了, 读取会不会发生错误?
5.切片使用的时候需要注意什么?
6.go中的参数传递是值传递还是引用传递?
7.defer的执行顺序?
8.100G的文件, 统计出所有英文字母, 按照字母表顺序输出
9.linux如何分割文件?
10.接口性能如何优化?
11.什么情况会全表扫描?
12.主丛同步的原理? mysql还有什么相关的log文件?
13.分布式锁的原理?
1.项目中用到哪些设计模式?
2.promethus如何使用的?
3.协程池自己实现的还是第三方包? 协程池的功能有哪些? sync.Pool的回收机制
4.如何获取进程中运行的协程数量?
5.遇到的线上故障有哪些?
6.线上go程序占用内存是多少?
7.接口优化思路?
8.线上每张表的数据量有多大?
9.如何提升数据库层面的性能
10.ES如何使用的? 倒排索引的原理是什么?
11.自己实现过哪些数据结构?
12.用户10分钟内, 如何只看到同一条广告
13.go语言和java语言的差异点
14.GC回收原理
15.项目中的难点
16.go应用突然挂了, 都有哪些原因? 如何排查?
17.recover能够捕捉到子协程的错误吗?
1.mysql存储引擎?
2.mysql隔离级别? 分别解决了什么问题?
3.2pc, 3pc 算法
4.10亿个数据获取前100个最大数据?
5.单个表到达多大要进行拆分? 为什么需要拆表?
6.redis哪些使用场景?
7.服务的熔断降级?
8.平时如何提升和学习?
9.TCP和UDP可以绑定同一个端口吗?
10.linux如何查看cpu, 内存负载?
11.进程间通信有哪些方式?
12.redis的数据类型?
13.redis和mysql的一致性问题?
1.最熟悉,最有收获的项目
2.协程池使用的第三方包还是自己实现的?
3.GMP中, P的数量大小默认是多少? P的数量是固定死的还是可以手动调整的?
cpu核心数. 可以通过设置环境变量 GOMAXPROCS来调整P的数量
4.kafka的一致性? kafka默认的ack级别?
一致性: 可靠性, 幂等性, 有序性.默认ack级别为1
5.kafka挂了, 如何保证异步消息不丢失?
- 设置ack级别为-1, 所有副本都收到才算成功写入
- 设置重试次数, 发送失败可以重试
- 开启幂等性, 确保重试也不会产生重复的消息
- 将消息写入mysql数据库, 然后再异步发送到kafka
6.kafka事务消息?
指生产者向kafka发送消息时, 要么全部发送成功, 要么全部发送失败并回滚.
确保了消息的一致性,原子性操作和精准一次消费.
生产者产生一条事务消息, 获取一个事务id, 发送事务消息时, 是同步发送的, 保证消息一定顺利写入broker
如果发送的是异步消息, 对于生产者来说, 发送后即显示发送成功, 但是下游broker的ack级别如果是-1, 那么只有该消息全部副本同步成功, 才算发送成功,所以异步消息还是会受ack级别影响.
7.口述堆排序的原理?
8.聊天系统如何直到客户是否在线? 用户聊天使用的是长连接还是短连接?使用websocket连接, 还需要自己实现心跳保活吗?
不需要, websocket自己已经实现了心跳保活机制, 只需要设置pingInterval和pingTimeout即可
1.GMP模型?
2.协程创建后如何调度?
先进入p的私有队列, 如果满了, 进入全局队列
3.context的结构和用法
4.一次url的请求过程?
5.请求到达项目服务器后的调用链路
6.nginx是否为单例的.
7.算法: 两数相除
8.平时mysql优化的案例?
9.in, exist的使用
10.联合索引
11.binlog日志
12.分布式事务: 下游两个db使用redis, 需要更新这两个不同的db, 如何自己实现最终一致性
13.两阶段提交, 三阶段提交?
1.slice和array的区别?
2.map是否并发安全?
3.channel相关? 如果没有初始化, 可以写吗? 可以读吗?已经关闭了, 再写?
4.如果是无缓冲类型管道? 读取和有缓冲的区别?
5.select监听多个管道
6.10个goroutine想要顺序执行, 如何实现?
7.10个协程同时执行, 如果其中有一个协程产生了错误, 其它协程停止运行, 如何实现?
8.如果controller方法中启动了一个go协程, 如何保证该协程和方法的生命周期一致?
9.接口性能优化?
10.分库分表? 水平分表, 垂直分表
11.项目中技术难点?
12.kafka重复消息问题?
13.ES如何使用的? ES的延迟?
14.一个服务已经跪了, 但是其它服务依赖该服务,如何在编码层面处理?
15.nginx具体的处理过哪些问题?
16.端口有大量的time_wait如何解决?
- 减少time_wait的等待时间
- 检查连接池是否够用
17.场景题: 兑换码永久有效, 海量玩家同时进行兑换, 如何设计?
缓存, 布隆过滤器.
18.算法题: 函数只能胜场1-5的函数, 请实现生成1-7的函数
1.服务注册和发现?
2.grpc的序列化和反序列化协议?
3.设置分布式锁的命令? setnx
4.redis的事务? redis执行lua脚本, 为什么lua脚本能够保证原子性执行?
redis是单线程的, 会把当前脚本执行完后再执行其它命令
5.redis的持久化方式? AOF在持久化时的优化策略?
当文件超过某个阈值时, 保存当前文件的快照, 旧的AOF文件就舍弃不用了, 因为只需要记录数据最新的状态即可
6.sort set的底层实现?
7.kafka的结构? ack默认级别?
8.有序性如何保证?
9.用户表? 字段为性别, 1和2 适合建立索引吗? 建立索引反而导致查询变慢的原因?
10.最左前缀法则?
11.订单列表, 越往后翻越慢, 原因是什么? 如何进行优化?
12.es用过吗?
13.订单定时关闭? 延迟队列?
rocketmq, kafka本身没有实现延迟消息队列的功能.
kafka:
常见的实现方式可以使用主题分区和时间戳, 可以创建一个专门用于延时消息的主题, 该主题创建多个分区, 将要延时发送的消息发送到该主题, 设置消息的期望执行时间. 消费者订阅该主题, 按照时间顺序消费消息, 判断当前时间是否到达了消息设定的执行时间, 如果达到则执行相应的操作, 否则将该消息重新发送到延迟队列
rabbitmq:ttl+死信队列实现延迟队列, 可以给指定队列或者消息设置ttl过期时间, 一旦到达过期时间, 那么会称为死信, 可以发送到指定的死信队列
14.时间轮算法?
15.多协程编排? waitGroup的实现?
16.单例模式
17.层序遍历二叉树
1.为什么要自己实现大顶堆? 大顶堆和小顶堆的使用场景?
2.如何利用堆, 获取第k大的元素? 堆如何删除某一个特定的节点? 大顶堆如何转换为一个小顶堆?
3.引入mq, 实现异步提速, 如何理解?
4.协程池使用的是第三方包吗? 如果自己实现一个协程池, 描述你的思路?
5.recover能捕获到其它协程的panic吗?
6.说一下对grpc的理解? grpc互相调用, 如何实现互相的权限验证和授权?
7.http2.0 的tsl三次握手过程?
8.grpc中, 如果客户端需要向服务端发送大文件, 如何实现? (使用客户端流模式)
9.http2.0的相关特性? 其中的多路复用为了解决什么问题? (解决对头阻塞问题)
10.grpc中的deadLine和timeout, 应该怎么用?
grpc的流控是如何处理的? 滑动窗口控制发送和接收速速率?
11.go-zero中的服务熔断和限流是怎么做的?
12.以下两个代码片段输出的结果:
func test() int { result := 1 defer func() { result++ } return 0 } func test() (result int) { result = 1 defer func() { result++ } return 0 }
1.项目中涉及到哪些监控? prometheus
2.队列出现消息积压, 如何处理?
3.消息幂等性?
4.一个sql语句, 已经建立了索引, 但是突然查询很慢, 如何排查?
5.索引失效场景?
6.mysql如何解决的幻读?
select … for update: 保证当前事务中查询的范围加锁, 不被其它事务修改
7.做索引优化, 如何减少回表次数–索引下推
索引下推: 指将上层(服务层)负责的事情, 交给下层(引擎层)处理.
不使用索引下推: 根据索引中的主键值, 定位并读取完整的行记录, 然后将记录交给server层去检测该记录是否满足where条件
使用索引下推: 获取索引, 判断索引是否符合条件范围, 如果满足, 再进行对应的回表查询获取主键, 如果不满足, 直接过滤掉
8.分布式事务, 二阶段提交, 三阶段提交的区别?
9.linux查看网络io的命令? netstat
10.如果出现大量time-wait状态, 如何处理?
11.网络的拥塞控制?
1.限流算法
2.redis的集群和分片
3.cap理论
1.限流算法 nginx默认使用的是哪种限流算法?
2.redis常用的数据结构
3.redis的缓存击穿, 缓存穿透, 缓存雪崩 以及相关的解决方案
4.redis中内存满了, 继续写入, 会发生什么?
- LRU算法删除数据
- 删除带有过期时间的键
- 随机删除键
- 不删除任何键, 返回错误
5.redis清理过期key的时机? redis删除key时, 是新启动一个进程处理删除任务吗
6.redis中有大量的key都是长期有效的, 现需要扫描所有的key, 进行特殊判断, 符合条件进行删除
7.redis的删除命令 del
8.redis的扫描命令: scan和keys的区别? 对redis的性能是否有损?
keys: 用于返回匹配指定规则的所有键, 类似mysql中的like模糊匹配功能
问题1: keys需要将所有redis中的键都遍历一遍,对性能影响较大
问题2: keys命令是一个阻塞命令, 直接阻塞其它客户端对redis的访问
线上一般严禁使用keys命令, 由于数据量过大, 可能一个命令直接导致redis不可用
scan命令:
- scan命令的时间复杂度也是O(N), 但是它是分次进行的, 不会阻塞线程
- scan命令提供了limit参数, 可以控制每次返回结果的最大条数
但scan命令返回的结果可能出现重复, 需要客户端去重.
9.mysql事务四大特性, 隔离级别? 是否解决了幻读?
10.mvcc采用的是什么日志文件?
11.select … for update使用的是当前读还是快照读?
当前读
12.mysql的调优经验? 索引下推?
13.主键索引和唯一索引的区别?
14.sql语句: 表中有name, city字段, 查询city中人数前三的数据
15.引用类型和值类型的区别?
16.切片的扩容机制
17.map是否为并发安全的? context是否为并发安全的?
在Go语言中,context.Context 是并发安全的。
这意味着你可以在多个goroutine之间安全地共享和传递同一个 context.Context 实例,而无需担心数据竞争或其他并发问题。
context.Context 的设计考虑到了并发编程的需求,它内部使用了适当的同步机制来确保在多个goroutine访问时能够保持正确的状态。因此,你可以放心地在多个goroutine中使用同一个 context.Context 来传递取消信号、超时信息或其他元数据。
感谢群友的分享,希望这篇最新面经对大家有帮助。
更多面经请关注公众号:王中阳Go
或者加我微信:wangzhongyang1993 备注:Go学习
原文链接:最新Go面经,看完你就是下一个Offer收割机