哭晕,腾讯的面试太难了。。。

国庆假期刚结束,马上就收到了一位粉丝分享的腾讯音乐面试经历。这是一场质量很高的面试,大厂面试官确实实力强劲。

但是由于一直忙于交接和工作,他完全裸面,所以在面试后直呼:“想哭,面试中全程被面试官牵着走,没有掌握主动权将话题引向自己擅长的方向”。

所以我建议大家在面试前一定要充分准备,特别是项目相关内容要深入理解每个决策背后的逻辑。

下面看一下他分享的内容吧:

面试内容

(一)开场

面试官介绍岗位

岗位为腾讯音乐 - 全民K歌 - 国际版 - 直播歌房后台研发工程师,主要负责直播相关功能,开发语言为Go和C++。

关于求职者基本情况

要求5分钟以内的自我介绍。

被问到所在公司技术团队裁撤后为何会留下自己。

岗位base深圳能否接受。

(二)项目相关

系统重构 - 数据迁移项目

微服务相关

如何理解微服务,为什么微服务能提升系统可拓展性。

微服务相比于单体服务的缺点。

服务间通信成本指的是什么,成本体现在哪。

数据库迁移原因与成本评估

把数据库从MongoDB迁移到MySQL的原因。

如何评估迁移异构数据库(MongoDB到MySQL)的成本,是否仅考虑成熟度和被接受程度,因为迁移涉及数据同步工作量巨大。

技术选型相关

如果采用最终一致性方案,MySQL支持事务而MongoDB不支持事务,有什么原因不使用最终一致性方案。数据同步与异常处理

迁移过程中数据同步怎么做(新数据库写MySQL,写脚本迁移Mongo数据到MySQL)。

业务要读写新旧数据时怎么办。

迁移比较暴力,如何发现数据异常,异构数据库迁移时如何保证每条数据正常迁移到MySQL。

唯一键场景下(Mongo已有数据,切换到MySQL写时可能重复写入)的处理。

优化服务器项目

分布式缓存实现

优化服务器引入分布式缓存技术(具体是Redis),如何实现的。

缓存与数据库一致性

如何保证Redis缓存和数据库的数据一致性(回答缓存先写数据库后写存在问题)。

写缓存成功数据库失败时缓存是否为脏数据。

先写数据库成功再写Redis,缓存更新失败怎么办,如何知道何时将数据库数据同步到缓存及同步的做法。

缓存是否有过期时间机制,有没有不过期一直生效的情况,有过期的话多久过期。

缓存同时过期会有什么问题以及如何解决。

数据抓取业务项目

Kafka相关

Kafka在业务中的角色。

业务为什么要经过Kafka这一层,账号量有多大。

定时任务可分散执行时间,Kafka在这种情况下削峰意义不大,是否有其他考虑使用Kafka的因素。

防止账号丢失已有确认机制,当作下游处理失败重新触发即可,为何还需要Kafka。

抖音微信小游戏归因业务项目

Token缓存相关

微信小游戏的token存于sync.map(服务内存),为何使用服务内存而不使用Redis或其他外部缓存方案。

用户量相关,当有一定数量实例和用户量时这种方案是否有缺陷(此处存在理解偏差导致回答失误)。

(三)Go和MySQL

1. MySQL相关

1. MySQL中索引如何实现,为什么MySQL里不使用B树。

在MySQL中,索引的实现主要依赖于特定的数据结构,以提高数据检索的速度。其中最常见的索引类型是基于B+树(B+Tree)的数据结构。

MySQL中的索引实现

B+树索引:

MySQL中的大多数存储引擎(如InnoDB和MyISAM)默认使用B+树作为索引的数据结构。

B+树的所有叶子节点都处于同一层,且相互之间有指针相连,这样可以方便地进行范围查询。

叶子节点包含了指向记录的指针,而非内部节点,这使得B+树更适合用于全键值、范围或排序操作。

B树索引:

虽然B树也可以用作索引,但在MySQL中使用较少。B树的每个节点都可以存储数据,包括内部节点,这可能导致更多的磁盘I/O操作,因为每次查询可能需要遍历更多的节点。

为什么MySQL里不使用B树

尽管B树在理论上可以用来实现索引,但在MySQL中更倾向于使用B+树,主要原因包括:

磁盘I/O优化:

B+树的所有数据都在叶子节点上,这意味着对于非叶子节点来说,只需要存储键值和指向下一层节点的指针,这使得每个节点可以容纳更多的键值,进一步降低了树的高度,减少了磁盘I/O次数。

范围查询优化:

B+树的叶子节点之间有链接,这使得范围查询更加高效。执行范围查询时,可以从第一个满足条件的叶子节点开始,沿着节点间的链接快速访问后续节点,无需返回上层节点重新寻找下一个满足条件的节点。

插入删除效率:

在B+树中,插入和删除操作通常只影响叶子节点,不会影响非叶子节点,这简化了树的维护过程,提高了操作效率。

Go相关

2. 切片如何实现

一个切片实际上是一个包含三个字段的结构体:

指针(Pointer):指向底层数组的一个指针。

长度(Length):表示切片当前包含的元素个数。

容量(Capacity):表示从切片指向的数组起始位置到数组末尾的元素个数。

底层结构:

type slice struct {    array uintptr  // 指向底层数组的指针    len  int      // 切片的长度    cap  int      // 切片的容量}

3. Go里并发读写map会出现问题,如何解决

使用互斥锁(Mutex)

使用 sync.Mutex 或 sync.RWMutex 对 map 的读写操作进行同步控制。这种方法适用于读写操作都较频繁的场景,示例:

import (    "sync")type SafeMap struct {    mu sync.Mutex    m  map[string]int}func (sm *SafeMap) Set(key string, value int) {    sm.mu.Lock()    defer sm.mu.Unlock()    sm.m[key] = value}func (sm *SafeMap) Get(key string) (int, bool) {    sm.mu.Lock()    defer sm.mu.Unlock()    value, ok := sm.m[key]    return value, ok}

使用 sync.Map:

Go 1.9 版本引入了 sync.Map,这是一个并发安全的 map 实现。sync.Map 适用于读多写少的场景,因为它在读取时不加锁,而在写入时才加锁,从而减少了锁的竞争,示例:

import (    "sync")var sm sync.Mapfunc Set(key, value interface{}) {    sm.Store(key, value)}func Get(key interface{}) (interface{}, bool) {    return sm.Load(key)}

使用通道(Channel):

通过通道协调对 map 的访问,确保同一时间只有一个goroutine可以读写 map。

4. Go里的sort排序如何实现

sort 包提供了多种排序功能,可以对不同类型的切片和自定义集合进行排序。sort 包的核心思想是通过实现 sort.Interface 接口来提供排序功能:

sort.Interface 是一个接口,定义了排序所需的三个方法:

Len() :返回要排序的元素个数。

Less(i, j int) :如果第 i 个元素应该排在第 j 个元素之前,则返回 true。

Swap(i, j int) :交换第 i 个元素和第 j 个元素的位置。

type Interface interface {    Len() int    Less(i, j int) bool    Swap(i, j int)}

常见类型的排序:

sort 包提供了对常见类型的切片进行排序的便捷函数:

Ints :对 []int 类型的切片进行升序排序。

Float64s :对 []float64 类型的切片进行升序排序。

Strings :对 []string 类型的切片进行升序排序。

5. 协程和线程的区别,线程开销大的原因,协程有上下文切换为何线程消耗更多CPU资源

协程和线程的区别

资源消耗:

线程:每个线程有自己的栈空间(几十KB到几MB),内存消耗大。

协程:栈空间较小(几KB),动态调整,内存消耗小。

调度方式:

线程:由操作系统控制,抢占式调度,涉及内核态切换。

协程:由应用程序控制,协作式调度,在用户态进行。

上下文切换:

线程:涉及内核态和用户态切换,开销大。

协程:只在用户态进行,开销小。

并发粒度:

线程:适用于处理多个相对独立的任务。协程:适用于在单个线程内实现多个任务的协作和切换。

线程开销大的原因

内存分配:

每个线程需要固定大小的栈空间,占用大量内存。

上下文切换:

涉及内核态和用户态切换,需要保存和恢复大量寄存器状态和栈指针。

调度开销:

操作系统维护复杂的调度算法和数据结构,增加系统开销。

同步机制:

使用锁、信号量等机制,高并发场景下可能导致性能瓶颈。

协程消耗更少CPU资源的原因

上下文切换简单:

只在用户态进行,不需要内核态介入,开销小。

调度灵活:

开发者控制调度,按需切换,减少不必要的上下文切换。

内存管理高效:

栈空间小且动态调整,内存利用率高。

同步机制简单:

通常通过通道(如Go语言中的channel)实现同步,避免锁的竞争。

(四)算法与反问

算法手撕

反问

#腾讯##腾讯面试##Go##面经##腾讯音乐#
Go面试题 文章被收录于专栏

这里汇总了大量了跟Go相关的面试题和面经,希望对大家有所帮助!

全部评论
这是问了多久
点赞 回复 分享
发布于 2024-10-30 00:31 湖北

相关推荐

04-24 16:42
已编辑
南京林业大学 后端工程师
发面经攒人品前几天面的,一直卡审核发不出来,今天重发太难了,被疯狂拷打1. 自我介绍2. 实习干了什么3. 实习的时候怎么修复bug的4. 实习的时候数据库、redis用的集群吗?5. 你觉得微信推送功能是怎么做的?是依赖于每个手机厂商提供的push服务吗?还是说每个app只接受其服务端的push?(完全不会)6. 实习的时候,你怎么写代码那,有没有开发机,怎么测试?怎么发布?日志怎么看?7. agent项目的向量数据库用的什么?你了解这个向量数据库内部怎么存储的吗?你怎么部署的这个向量数据库?(底层原理不知道)8. 你有没有自己开发过mcp?(没有)9. react模式是什么?10. 你这个agent做完后最后是一个什么形式?11. 你是用了spring ai alibab里面封装好的吗?是不是就调用了几个接口?12. rag切片怎么做?13. 有没有测试过准确率和召回率?(没做)14. 你主要是java吗?有没有用过其他语言?15. 讲一下synchronize关键字16. synchronize关键字锁的到底是什么?17. 讲一下synchronize的底层原理18. 你知道锁监视器对象是怎么用的吗?线程怎么抢锁?19. 有很多线程,他们怎么抢这个锁,能不能讲一下具体过程?20. 堆怎么管理?怎么回收垃圾?21. 你了解协程吗?(不知道)22. 讲一下输入qq.com到最后显示页面的过程23. HTTPS握手具体怎么做?24. (从这里开始抽象起来了,面试官一直问我ECDHE的会话密钥怎么计算,私钥怎么计算,怎么交换公钥,我完全不知道,之前背的小林coding,我感觉他好像认为小林coding上的是错的,然后一直追问,我压根听不懂他问的到底是什么意思)25. 客户端和服务器要交换公钥,这些公钥要用来干什么?26. 这个会话密钥到底是怎么协商的?讲一下具体过程27. 客户端和服务器交换的到底是什么?28.  此处省略一堆,全是问这个怎么公钥生成的,怎么交换,为什么这样能行,怎么计算会话密钥的,我完全听不懂面试官想问什么29. 讲一下大模型的工作原理(到这里已经彻底绷不住了,我明明投的是后台开发啊)30. 你不觉得这很神奇吗?他为什么根据上下文就能回答?反问:1. ECDHE那里到底是什么?- 你混淆了很多概念,比如随机数、私钥、公钥。随机数不能用来直接做私钥,你去问一下gpt。(但是小林coding上说那个随机数就是私钥)2. 到底是做什么业务的- 做存储和下发。数据要处理后再存储,然后用户访问时下发。最后面试官说了一句“感谢你参加腾讯的面试”。🤡
查看28道真题和解析
点赞 评论 收藏
分享
04-22 16:17
已编辑
电子科技大学 算法工程师
看了大家不少面经,我也发发面经攒人品✉️投递:3.18💬面试:一面 3.23 二面 3.25 三面 4.3 HR面 4.13📝offer:4.21🎙️我的感受:我由于测评不高,面到HR面的时候非常的焦虑,很怕因为测评给我挂了我投的淘天全挂了,可能就是因为测评不行吧总体下来阿里的面试官还是挺尊重的,拷打的很详细bg:双九,一段小厂对口实习面试主要内容狠狠拷打简历,实习内容,问的非常详细,会问到你负责了什么,用了多少张卡,学习率怎么样,训练了多久,用了多少数据,数据是怎么准备的,显存占用怎么样场景题:如果我目前有一个数字人的模型,我想训练成只生成一个人的,可以怎么做你看过什么别的 SOTA 模型的 ref image 注入方式,有什么优劣八股:如何判断模型是否收敛如果训练的时候梯度消失或者爆炸,你怎么解决如何系统判断是否训练完成,特别是在视频生成模型中有哪些常见的蒸馏方法LoRA 微调的原理DiT 的框架流程,如何时间注入,讲一讲 AdaLN讲一下 flow Matching,原理,优势现在为什么大家都用 RMSNorm 而不是 LayerNormAdam 和 AdamW 的原理,有什么改进手撕:1. 二叉树的右视图2. 非 hot 100,滑动窗口3. 扎破所有气球的最少箭数暑期实习还是太折磨了,我面了好多场,一直在泡池子。。。腾讯二面给我泡了13天然后挂,米哈游一面挂,快手简历挂。。。看到身边同学都拿到offer了,那是一个焦虑啊,本来都想转日常了。最后总算是有一个结果了
查看15道真题和解析
点赞 评论 收藏
分享
评论
13
43
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务