金三银四Go面试题(包含数据库,网络,架构)

338 阅读17分钟

Go

go源码方面强烈推荐:draveness.me/golang/(必看)

  • sync.mutex原理
  • defer原理
  • sync.map、sync.pool、sync.Once底层原理
  • context的使用
  • panic是什么?是不是所有panic都能被捕获?什么样的不能被捕获?不能被捕获是怎么实现的
  • 煎鱼面试:mp.weixin.qq.com/s/7rCsaGy8B…
  • go抢占式调度mp.weixin.qq.com/s/B8UbFO1i2…
  • Proof 实现 mp.weixin.qq.com/s/1VoZ9dZYk…
  • GMP模型,触发Goroutine切换的原因有哪些?for死循环会怎么样?全局goroutine里面存储什么?
  • 抢占式调度是如何抢占的,怎么调度 goroutine 的,M 和 P 的数量问题?
  • GMP调度
  • 如果系统调用阻塞了G会怎么样
  • 启动过程
  • GC的过程、写屏障的含义及作用?GC,(面 GO 必问题),GC 中 stw 时机,各个阶段是如何解决的?GC是怎么样的三色标记法有什么缺点(不区分新生代)
  • 如何优雅的实现一个 goroutine 池?
  • defer 在什么时机会修改返回值。多个 defer 的顺序?
  • 如何控制goroutine的数量
  • 如何管理goroutine的生命周期
  • 如何对goroutine进行超时的监控和处理
  • golang的当下的gc有何问题?
  • 并发和并行的区别
  • sync.condieevee.com/tech/2019/0…

mysql

  • 你们mysql引擎用的什么?mysql innodb的索引是怎么实现的?为什么用B+树,优点是什么,与B树的区别是什么?
  • B+树索引的最底层单元是什么?什么决定了B+树的高度?B+树的叶子节点是单向链表还是双向链表?
  • 怎么加索引,索引什么情况下失效,联合索引什么时候失效,覆盖索引了解吗?
  • 为什么不用uuid做主键,影响的写入性能还是读取性能?如果业务上能保证唯一性,那么还需要建唯一索引吗?会影响写入性能吗?
  • mysql的隔离级别有几种,默认的隔离级别是什么,互联网常用的隔离级别是什么?
  • ACID了解吗,mysql是用什么机制保证的,redo log和undo log说一下
  • MVCC是什么,是如何实现的,算法说一下?
  • 幻读是什么意思?mysql是怎么处理幻读的?间隙锁了解吗?唯一索引有间隙锁吗?
  • 锁分哪几种,行锁是锁在哪里的?
  • mysql 主从同步的过程是什么样的
  • mysql的高可用是怎么做的
  • 慢查询怎么处理?explain的type有几种类型,你常见的有哪几种?
  • 你们的mysql数据量有多大,如何分库分表,分库分表以后如何查询,如何做分布式事务
  • 如何确定是否使用索引,如何查看 explain 的结果
  • 聚簇索引和非聚簇索引的区别
  • 创建索引后,查询读取I/O的次数
  • 索引的最左前缀原则
  • mysql数据的索引优化以及失效
    • 索引最左前缀 (a,b,c) ,
    • 不要在查询语句字段上做函数运算,
    • select * 的问题
    • 覆盖索引,
    • 要在区分度高的字段建立索引
    • 建索引要注意大小 索引长度过大 会占用更大的 顺便提到上次的身份证上建立索引的案例
    • 避免强制类型的转换
  • mysql的隔离级别?处理什么问题的(脏读、幻读、不可重复读)
  • mysql的主从复制过程?
  • mysql的大表优化方式
  • 底层怎么实现,为什么选了B+树
  • 考虑一个业务场景: 头条的文章的评论量非常大, 比如说一篇热门文章就有几百万的评论, 设计一个后端服务, 实现评论的时序展示与分页问: 需不需要支持页码直接跳转?面试官: 支持和不支持两种场景都考虑一下答: 不需要支持页码翻页就传评论 id 用 offset 翻页
  • 假如用 id 翻页的方式, 数据库表如何设计? 索引如何设计?(文章id, 评论id) 建联合索引,评论 id 需递增
  • 假如量很大, 你觉得需要分库分表吗? 怎么分?需要分,分表有个权衡,按文章 id 分表,读逻辑简单,但写有热点问题;按评论 id 分表,读逻辑复杂,但写压力就平均了。写是要首先保证的,而读总是有缓存等方案来折中,因此按评论 id 分表好。
  • 分库分表后怎么查询分页?每张表查 N 条数据由 client 或 proxy merge
  • 分库分表后怎么保证主键仍然是递增的?讲了 TDDL 的办法:有一张专门用于分配主键的表,每次用乐观锁的方式尝试去取一批主键过来分配,假如乐观锁失败就重试
  • 现在需要支持深分页, 页码直接跳转, 怎么实现?不能做精准深分页,否则压力太大,找产品进行妥协,在50或100页后数据分页是否可以不完全精确,假如可以,那么缓存深页码的起始评论 id
  • 瞬时写入量很大可能会打挂存储, 怎么保护?断路器
  • 断路器内部怎么实现的?可以用 ringbuffer
  • 断路器会造成写入失败, 假如我们不允许写入失败呢?先写进消息队列,削峰填谷异步落库
  • mysql 面试(github.com/KeKe-Li/dat…)
  • 一条sql执行过长的时间,你如何优化,从哪些方面入手?
  • 查看是否涉及多表和子查询,优化Sql结构,如去除冗余字段,是否可拆表等
  • 优化索引结构,看是否可以适当添加索引
  • 数量大的表,可以考虑进行分离/分表(如交易流水表)
  • 数据库主从分离,读写分离
  • explain分析sql语句,查看执行计划,优化sql,有个 Extra 有 Using index Using where 表示什么
  • 查看mysql执行日志,分析是否有其他方面的问题

redis

  • redis的数据类型有哪几种,你们用了哪几种,是怎么用的
  • redis string类型的底层数据结构是怎么样的?
  • redis为什么快
  • redis是怎么实现原子性的(腾讯云问的)mp.weixin.qq.com/s/uIdJN67CC…
  • redis为什么要用单线程,最新的redis 6.0用了多线程,是怎么实现的,你了解吗?
  • redis的跳表了解吗,数据结构是怎么样的,查询的时间复杂度是多少
  • 你们的redis是哨兵模式还是集群模式,具体是怎么配置的,了解吗?
  • redis的分布式锁用过吗,怎么用的?
  • redis单实例的QPS是多少,有测过吗?最新的6.0 QPS多少知道吗?
  • redis的大 key 多大算大?单个redis实例建议多大内存?
  • 写时复制了解吗,在redis哪里用到了?在计算机的哪些场景或者算法里有用到?参考:zhuanlan.zhihu.com/p/339437815

redis的网卡如果被打爆了,怎么办?redis缓存和本地缓存是怎么配合使用的,数据的一致性是如何解决的?参考:mp.weixin.qq.com/s/4W7vmICGx…

问题:如果你的应用程序执行的 Redis 命令有以下特点,那么有可能会导致操作延迟变大:

  1. 经常使用 O(N) 以上复杂度的命令,例如 SORT、SUNION、ZUNIONSTORE 聚合类命令
  2. 使用 O(N) 复杂度的命令,但 N 的值非常大

优化:

这里有两点可以优化:

  1. 业务应用尽量避免写入 bigkey
  2. 如果你使用的 Redis 是 4.0 以上版本,用 UNLINK 命令替代 DEL,此命令可以把释放 key 内存的操作,放到后台线程中去执行,从而降低对 Redis 的影响
  3. 如果你使用的 Redis 是 6.0 以上版本,可以开启 lazy-free 机制(lazyfree-lazy-user-del = yes),在执行 DEL 命令时,释放内存也会放到后台线程中执行。
fork 耗时严重

当 Redis 开启了后台 RDB 和 AOF rewrite 后,在执行时,它们都需要主进程创建出一个子进程进行数据的持久化。

主进程创建子进程,会调用操作系统提供的 fork 函数。

而 fork 在执行过程中,主进程需要拷贝自己的内存页表给子进程,如果这个实例很大,那么这个拷贝的过程也会比较耗时。

而且这个 fork 过程会消耗大量的 CPU 资源,在完成 fork 之前,整个 Redis 实例会被阻塞住,无法处理任何客户端请求。

想避免这种情况,你可以采取以下方案进行优化:

  1. 控制 Redis 实例的内存:尽量在 10G 以下,执行 fork 的耗时与实例大小有关,实例越大,耗时越久
  2. 合理配置数据持久化策略:在 slave 节点执行 RDB 备份,推荐在低峰期执行,而对于丢失数据不敏感的业务(例如把 Redis 当做纯缓存使用),可以关闭 AOF 和 AOF rewrite
  3. Redis 实例不要部署在虚拟机上:fork 的耗时也与系统也有关,虚拟机比物理机耗时更久
  4. 降低主从库全量同步的概率:适当调大 repl-backlog-size 参数,避免主从全量同步
开启AOF

当 Redis 开启 AOF 后,其工作原理如下:

  1. Redis 执行写命令后,把这个命令写入到 AOF 文件内存中(write 系统调用)
  2. Redis 根据配置的 AOF 刷盘策略,把 AOF 内存数据刷到磁盘上(fsync 系统调用)

为了保证 AOF 文件数据的安全性,Redis 提供了 3 种刷盘机制:

  1. appendfsync always:主线程每次执行写操作后立即刷盘,此方案会占用比较大的磁盘 IO 资源,但数据安全性最高
  2. appendfsync no:主线程每次写操作只写内存就返回,内存数据什么时候刷到磁盘,交由操作系统决定,此方案对性能影响最小,但数据安全性也最低,Redis 宕机时丢失的数据取决于操作系统刷盘时机
  3. appendfsync everysec:主线程每次写操作只写内存就返回,然后由后台线程每隔 1 秒执行一次刷盘操作(触发fsync系统调用),此方案对性能影响相对较小,但当 Redis 宕机时会丢失 1 秒的数据

但即便可以使用方案 2,我也不建议你在实例中存入 bigkey。

这是因为 bigkey 在很多场景下,依旧会产生性能问题。例如,bigkey 在分片集群模式下,对于数据的迁移也会有性能影响,以及我后面即将讲到的数据过期、数据淘汰、透明大页,都会受到 bigkey 的影响。

Redis 的过期数据采用被动过期 + 主动过期两种策略:

  1. 被动过期:只有当访问某个 key 时,才判断这个 key 是否已过期,如果已过期,则从实例中删除
  2. 主动过期:Redis 内部维护了一个定时任务,默认每隔 100 毫秒(1秒10次)就会从全局的过期哈希表中随机取出 20 个 key,然后删除其中过期的 key,如果过期 key 的比例超过了 25%,则继续重复此过程,直到过期 key 的比例下降到 25% 以下,或者这次任务的执行耗时超过了 25 毫秒,才会退出循环
执行 O(N) 命令时,关注 N 的大小**

规避使用复杂度过高的命令,就可以高枕无忧了么?

答案是否定的。

当你在执行 O(N) 命令时,同样需要注意 N 的大小。

如果一次性查询过多的数据,也会在网络传输过程中耗时过长,操作延迟变大。

所以,对于容器类型(List/Hash/Set/ZSet),在元素数量未知的情况下,一定不要无脑执行 LRANGE key 0 -1 / HGETALL / SMEMBERS / ZRANGE key 0 -1。

在查询数据时,你要遵循以下原则:

  1. 先查询数据元素的数量(LLEN/HLEN/SCARD/ZCARD)
  2. 元素数量较少,可一次性查询全量数据
  3. 元素数量非常多,分批查询数据(LRANGE/HASCAN/SSCAN/ZSCAN)
关注 DEL 时间复杂度

你没看错,在删除一个 key 时,如果姿势不对,也有可能影响到 Redis 性能。

删除一个 key,我们通常使用的是 DEL 命令,回想一下,你觉得 DEL 的时间复杂度是多少?

O(1) ?其实不一定。

当你删除的是一个 String 类型 key 时,时间复杂度确实是 O(1)。

但当你要删除的 key 是 List/Hash/Set/ZSet 类型,它的复杂度其实为 O(N),N 代表元素个数。

也就是说,删除一个 key,其元素数量越多,执行 DEL 也就越慢!

原因在于,删除大量元素时,需要依次回收每个元素的内存,元素越多,花费的时间也就越久!

而且,这个过程默认是在主线程中执行的,这势必会阻塞主线程,产生性能问题。

那删除这种元素比较多的 key,如何处理呢?

我给你的建议是,分批删除:

  • List类型:执行多次 LPOP/RPOP,直到所有元素都删除完成
  • Hash/Set/ZSet类型:先执行 HSCAN/SSCAN/SCAN 查询元素,再执行 HDEL/SREM/ZREM 依次删除每个元素
  • 缓存雪崩、缓存击穿、缓存穿透
  • 日常缓存和数据一致性处理
  • 缓存和数据库一致性问题(mp.weixin.qq.com/s/4W7vmICGx…)

网络

  1. 浏览器输入一个url到返回,整个过程说一下,都用到了哪些协议?
  2. dns的执行过程?
  3. 通过http的方式进行远程调用以及通过thrift调用各自有什么样的优缺点
  4. TCP vs UDP对比:TCP: 有序、完整性,可靠性,UDP: 无保证;
  5. TCP 是怎么保障可靠性的
  6. tcp如何保证数据的可靠性
  7. http常见状态码
  8. HTTPS 密钥交换
  9. HTTP / HTTPs 区别
  10. Content-Length 代表什么?
  11. http请求中 Request header有哪些?
  12. 输入域名,浏览器提示找不到服务器ip地址原因?
  13. 网络:zhuanlan.zhihu.com/p/108822858
  14. TCP三次握手,四次挥手说一下。为什么需要三次握手,最后一次如果没有行不行,会有什么问题?
  15. TIME_WAIT的作用是什么?2MSL是多长?线上大量的close_wait和time_wait该如何解决?
  16. http2.0的优点说一下。了解QUIC吗?怎么实现的?
  17. https的握手过程说一下。证书是如何验证的?为什么不用非对称加密通信?
  18. 浏览器输入一个url到返回,整个过程说一下,都用到了哪些协议?浏览器的渲染过程了解吗?
  19. 一台服务器最多可以建立多少个TCP链接,为什么?

系统设计(开放性)

  • 分布式id生成器
  • 分布式锁延时任务系统分布式搜索引擎负载均衡器分布式配置管理分布式爬虫
  • 服务限流系统
  • 设计一个短网址系统,要求:uri 不能超过8个字符,能支撑10亿个长网址,长网址和短网址一一对应。实现两个接口:1. 输入长网址,输出对应短网址; 2. 输入短网址,输出对应长网址
  • 设计北京汽车摇号系统,要求:不同
  • 设计短网址系统:8位,10亿长网址(发号器:ID、MD5、短网址)
  • 如何设计一个消息服务:如何保证不丢消息,消息去重。建议看看58同城沈剑的公众号文章
  • 设计一个评论系统的存储,要求实现一二级评论,读qps在百万级别
  • 树形结构,存储使用mysql,设计了一个表,包含文章id、评论id、回复id、用户id等
  • 如何支撑百万级别读请求?使用es索引;es可以支撑这么高的请求吗?不清楚
  • 百万参与人次的活动,在页面上需要显示当前在线人数,设计一个方案实现这个功能。

需求挖掘: 是否需要精确,其他想法没有想法。

技术方案:redis计数。 热key问题怎么解决?本地cache,异步刷新。 方案需要多次引导。

追问,容灾怎么考虑: 服务做集群。 redis 做高可用。

追问,降级手段: 网关层限流, 防攻击

追问,如何支持用户一段时间不活动就算离开?

kafka

  • 事务消息了解吗,rocketmq的事务消息是怎么实现的?
  • kafka是如何保证不丢消息的
  • kafka为什么快? 零拷贝说一下,零拷贝有几种实现?
  • kafka的IR和高水位是什么意思,说一下
  • kafka主要解决什么问题,你们项目里是怎么用的
  • kafka如何保证消息的有序性
  • kafka如果消息堆积了如何处理
  • 工作中如何解决 MQ 消息堆积和消息重复的问题?
  • MQ 应用场景、Kafka 和 rabbit 区别?kafka 为什么支撑高并发
  • kafka 的架构,大致储存结构(高德 字节 滴滴)
  • 如果消费者数超过分区数会怎么样?(顺丰 滴滴)
  • 怎么保证数据的可靠投递?(陌陌 字节)
  • 消费者的 offset 存在哪里?(字节 腾讯 陌陌)
  • 如何通过 offset 定位消息?(字节)
  • 时间轮的原理(陌陌 顺丰)
  • kafka 写入高性能的原因,sendfile 和 mmap 原理,为什么不用 splice(滴滴)

操作系统:

  • 常用的命令有哪些
  • 怎么查看端口占用情况,怎么查看进程打开了哪些文件
  • 如何查看内存,如何查看磁盘,du是什么意思
  • linux的文件系统了解吗,inode了解吗
  • 线上服务器问题如何排查。cpu loader average什么意思,cpu利用率什么意思
  • 进程、线程、协程区别。(这个很重要)
  • poll、epoll、select
  • I/O模型(www.jianshu.com/p/486b0965c…)
  • 什么是虚拟内存
  • 负载均衡mp.weixin.qq.com/s/Rngy_zCop…
  • 再谈负载均衡mp.weixin.qq.com/s/B1pqmFqeD…

etcd

  • etcd是什么?有什么优势
  • raft选主逻辑
  • 日志复制
  • 脑裂问题
  • etcd的watch机制
  • etcd如何实现配置下发和服务发现
  • etcd对于偶数机器的集群的选主处理

算法题

微服务:

微服务的优点是什么

微服务的服务拆分你们是怎么做的 答:www.infoq.cn/article/r2y…

微服务的服务治理你们是怎么做的,都包括哪些模块

RPC具体是怎么实现的,有哪些组件可以说一下吗?RPC的连接池是怎么实现的,数据结构是什么样的,链接如何保活 blog.csdn.net/glamour2015…

项目:

介绍一下你们的项目

你们项目的服务对象是谁,解决了他们的什么问题

你们的并发量多大,高并发是如何解决的

画一下你们项目的架构图

你们项目里的难点,优点,有什么可以改进的地方

你是怎么控制项目进度的

反问环节:

我如果加入你的团队,有这几个问题想问一下

  1. 团队对我的定位如何?
  2. 我的方向可以随着业务调整,但业务大方向是怎样的?
  3. 你对部门的未来发展预期是怎样的呢?
  4. 在未来的进程里,我起到怎样的角色?
  5. 你对我个人的期待是怎样的?

这5个问题,全部问出去 ,回答上来3个答案你觉得满意的就可以考虑,如果5个全是模棱两可的说的,不论薪资多高都不要去,因为这leader没想明白自己未来部门的发展,这种leader跟不了,如果5个问题都回答的你觉得很满意,至少很清晰