米哈游 服务器开发方向 C++ 二面 面经

1. 自我介绍,介绍一下你做过的最有挑战性的项目

这道题考察的是表达能力和技术深度,回答框架建议用 STAR 法则:

答:我参与过一个游戏服务器的高并发架构重构项目。背景是原有服务器在日活 50 万时出现明显卡顿,延迟峰值达到 800ms。我负责的部分是网络层和消息队列的重新设计。

具体做了几件事:① 将原来的 select 模型换成 epoll ET 模式,配合非阻塞 IO,连接数从 1 万提升到 10 万;② 引入无锁 SPSC 队列替换原来加互斥锁的消息队列,热路径延迟降低了约 40%;③ 用内存池管理频繁分配的消息对象,减少了 GC 压力和内存碎片。最终上线后延迟峰值降到 120ms 以内,服务器 CPU 利用率下降了 25%。

挑战在于:无锁队列的内存序问题非常难调试,用 ThreadSanitizer 发现了两处 data race,最终通过仔细分析 acquire/release 语义解决。

2. 项目中遇到过内存泄漏吗?你是怎么定位和解决的?

答:遇到过。定位内存泄漏的常用手段:

① Valgrind Memcheck:运行程序后报告所有未释放的堆内存,精确到分配的调用栈。命令:valgrind --leak-check=full ./server,缺点是运行速度慢约 10-20 倍,适合测试环境。

② AddressSanitizer(ASan):编译时加 -fsanitize=address,运行时检测内存越界、use-after-free、内存泄漏,速度比 Valgrind 快很多,适合 CI 集成。

③ 自定义内存追踪:重载 operator new/delete,记录每次分配的地址、大小、调用栈,程序退出时打印未释放的记录。

我项目中的一次泄漏是:玩家断线时,持有该玩家 shared_ptr 的定时器没有被取消,导致玩家对象无法释放。用 Valgrind 定位到分配点后,发现是定时器回调里捕获了 shared_ptr 的 lambda,改成捕获 weak_ptr 后解决。

3. 如何设计一个支持百万并发连接的游戏服务器架构?

答:百万并发连接不能用单机单进程,需要分层架构:

网络接入层:多台 Gateway 服务器,每台用 epoll + 协程处理 IO,只负责连接维护和消息收发,不做业务逻辑。单机 epoll 支持 10 万级连接,10 台 Gateway 即可支撑百万连接。

逻辑层:按游戏功能拆分为多个服务(场景服、战斗服、社交服、背包服等),Gateway 根据消息类型路由到对应服务。服务间通过消息队列(如 Kafka)或 RPC(如 gRPC)通信。

数据层:Redis 做热数据缓存(玩家状态、排行榜),MySQL 做持久化存储,写操作异步落库,读操作优先走缓存。

关键设计点:① 无状态 Gateway,方便水平扩展;② 玩家 session 信息存 Redis,任意 Gateway 都能处理同一玩家的消息;③ 心跳检测 + 断线重连机制;④ 消息协议用 Protobuf,序列化效率高且跨语言。

4. 分布式系统中如何保证消息不丢失、不重复?

答:这是分布式系统的经典问题,核心是幂等性 + 持久化 + 确认机制。

不丢失:① 消息发送方持久化到本地 WAL(Write-Ahead Log)再发送;② 消息队列(Kafka)配置 acks=all,确保所有副本写入才返回成功;③ 消费方处理完业务后再提交 offset,而非收到就提交。

不重复:网络重试必然导致重复投递,解决方案是幂等处理。每条消息带唯一 message_id,消费方处理前先查 Redis 是否已处理过该 id,处理完后写入 Redis(设置过期时间)。这样即使消息重复投递,业务逻辑也只执行一次。

恰好一次(Exactly Once):Kafka 0.11+ 支持事务,配合幂等 Producer 可实现端到端 Exactly Once,但性能有损耗,游戏场景通常用 At Least Once + 幂等消费即可。

5. 数据库事务的隔离级别有哪些?可重复读是如何实现的?

答:四个隔离级别(从低到高):

  • 读未提交(Read Uncommitted):可读到其他事务未提交的数据,存在脏读。
  • 读已提交(Read Committed):只读已提交数据,解决脏读,但存在不可重复读(同一事务两次读结果不同)。
  • 可重复读(Repeatable Read):同一事务内多次读结果一致,解决不可重复读,MySQL InnoDB 默认级别。
  • 串行化(Serializable):完全串行执行,解决幻读,性能最差。

可重复读的实现(InnoDB MVCC):事务开始时创建一个 Read View,记录当前活跃事务列表。后续每次读操作都用这个 Read View 判断数据版本可见性,只读取在 Read View 创建时已提交的版本。因为 Read View 不变,所以同一事务内读到的数据始终一致。

幻读问题:InnoDB 在 RR 级别下通过 Gap Lock(间隙锁)+ Next-Key Lock 防止幻读,锁住查询范围内的间隙,阻止其他事务插入新行。

6. Redis 的持久化方式有哪些?AOF 重写的原理是什么?

答:两种持久化方式:

RDB(快照):定期将内存数据序列化为二进制文件。优点:文件紧凑,恢复速度快;缺点:两次快照之间的数据可能丢失,fork 子进程时有短暂阻塞。

AOF(追加日志):每条写命令追加到 AOF 文件。优点:数据更完整,最多丢失 1 秒数据(fsync every second);缺点:文件越来越大,恢复速度慢。

AOF 重写原理:AOF 文件会随时间膨胀(同一个 key 被修改多次,历史命令都保留)。重写时 fork 子进程,子进程遍历当前内存数据,将每个 key 的当前状态用最少的命令表示(如一个 list 用一条 RPUSH 替代多条操作),写入新 AOF 文件。重写期间父进程继续处理请求,新命令同时写入旧 AOF 和重写缓冲区,重写完成后将缓冲区追加到新文件,原子替换旧文件。

7. 什么是一致性哈希?它解决了什么问题?虚节点的作用是什么?

答:普通哈希取模(key % N)的问题:增减服务器节点时,N 变化导致几乎所有 key 重新映射,缓存大面积失效,引发缓存雪崩。

一致性哈希:将哈希空间组织成一个环(0 到 2^32-1),服务器节点映射到环上的某个位置,key 也映射到环上,顺时针找到的第一个节点就是负责该 key 的节点。增减节点时只影响相邻节点的数据,其他节点不受影响。

虚节点:真实节点少时,节点在环上分布不均匀,导致负载不均衡。虚节点是每个真实节点在环上的多个映射点(如每个节点对应 150 个虚节点),使数据分布更均匀。增减节点时,该节点的多个虚节点同时变化,数据迁移更均匀,不会集中压垮某个节点。

8. C++ 中的内存模型是什么?std::atomic 的 memory_order 有哪几种?

答:C++11 引入了多线程内存模型,定义了多线程环境下内存操作的可见性和顺序保证,解决了不同 CPU 架构(x86、ARM)的指令重排问题。

六种 memory_order:

  • memory_order_relaxed:只保证原子性,不保证顺序,性能最好,适合计数器累加。
  • memory_order_acquire:读操作,保证此操作之后的读写不会被重排到此操作之前,配合 release 使用。
  • memory_order_release:写操作,保证此操作之前的读写不会被重排到此操作之后。
  • memory_order_acq_rel:同时具有 acquire 和 release 语义,用于读-改-写操作(如 fetch_add)。
  • memory_order_seq_cst:顺序一致性,最强保证,所有线程看到的操作顺序一致,是默认值,性能最差。

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

C++八股文全集 文章被收录于专栏

本专栏系统梳理C++技术面试核心考点,涵盖语言基础、面向对象、内存管理、STL容器、模板编程及经典算法。从引用指针、虚函数表、智能指针等底层原理,到继承多态、运算符重载等OOP特性从const、static、inline等关键字辨析,到动态规划、KMP算法、并查集等手写实现。每个知识点以面试答题形式呈现,注重原理阐述而非冗长代码,帮助你快速构建完整知识体系,从容应对面试官提问,顺利拿下offer。

全部评论

相关推荐

03-30 21:35
吉林大学 Java
爱蜜莉雅碳劝退测开:裁员裁大动脉了
点赞 评论 收藏
分享
今天 11:25
门头沟学院 Java
发一下问题给大家参考,攒攒人品!有面试过同岗的朋友欢迎评论区交流1.redis集群环境下,你怎么保证你在lua脚本上操作的key在同一个实例上来保证原子性的2.这个令牌桶流量控制这块。你自己实现的吗?还是找了一个现成的实现组件去用的?3.你这个秒杀业务主要是用什么来保障它它的并发的?除了这个lua脚本之外。端到端的提升是怎么做的?4.前端上有做防秒杀,防并发的这种保护吗?5.点赞业务什么时候用的set,什么时候用的zset6.这里的zset为什么不使用内存来进行操作,不都是可以是合并写的作用7.那你这里的zset能存多少条点赞数量的数据8.Zset的数据结构了解吗,展开讲一下9.那你这个降低幻觉你是怎么发现的问题?然后你做完优化之后,实际的效果是怎么去观测衡量的?RAG这块,第二点对模块化RAG架构。10.你不是降低了幻觉吗?你怎么论证有效降低,实际效果怎么衡量的11.做这个所谓的衡量时候,为什么不考虑再引入一个agent来做?12.死循环监测能力,防止agent的无限循环。这里首先你是怎么识别到会有循死循环问题的?13.你现在日常在用AI工具是什么状态?只是coding吗?还是说也在做一些小的尝试,小的玩法有贡献过skill吗?14.你的ai规划的内容基于两部分,一个websearch搜索的,一个基于你的本地内容的方法调用,那你怎么综合这两部分的内容的呢,是直接一股脑扔给ai大模型吗15.你看你现在在做规划,假设给你扩展一下,你现在发布功能,我希望那个用户只传图片,然后其他文案让他自己生成,就不只是路线规划了。16.你觉得这个事该咋做呢?我想要给你这个功能再提点需求。17.用户编写文案的意图,这件事打算怎么写呢?这个skill。18.讲一下对openclaw的理解19.什么样的功能适合做成skl,什么样的不合适
查看19道真题和解析
点赞 评论 收藏
分享
我是腾讯26年的校招生,从去年8月开始我入职腾讯CDG某部门实习,因为目标就是转正,从进去第一天开始,我就是按全职的标准在干活的,一个人负责一个独立模块,整个8月到11月,我一个月最多请一天假,除了真的有考试,几乎天天都在,所有课余时间都奉献给了公司。在整个过程里,领导对我的评价一直很正面,甚至跟我说过,这里会是一个很好的起点。我当时其实手里不止腾讯一个选择,还有好几家好头部大厂和外企给了面试,有的已经到终面,有的已经拿到offer,有些薪资比腾讯还高。但我信任腾讯,觉得一个大厂不会对认认真真干了这么久得到转正的实习生做出撕offer的事。所以我签了腾讯的转正offer,其他的全部婉拒签完之后我的工作量没有任何变化,还照常推项目,甚至一直到被毁约前一周,我收到的是工作上的正面反馈。但就直到上周,我还在项目上工作,就在不久之前还在得到+1对工作质量的认可,在没有任何征兆的情况下,就突然得到HR的通知,说因为部门HC的原因,我的Offer会被撤回,我需要马上签字,不然就会被强行解约。面对这个情况,我至今想不通第一,部门并无大规模变动,同届校招生无一受影响,为何偏偏只对我一个海外院校学生没有三方协议的应届生下手?是不是因为我身份特殊、维权更难,就成了可以随意牺牲的软柿子?第二,腾讯是否算过我付出的巨大机会成本?我从大一就开始实习,辗转各个大厂和知名企业,牺牲了大量课余时间,前前后后做了至少7-8份实习,就是为了毕业能有一份工作。终于拿到腾讯的转正offer,我以为可以安心了。结果呢?春招已经过了大半,我对口的岗位招聘接近尾声,我现在面临的是毕业即失业,甚至可能要延长学业。区区几个月的实习薪水补偿,能弥补我错失的全部机会吗?能弥补这几个月的心血和精神上的打击吗?难道作为头部企业的腾讯,毁约一个校招生的offer就这么随便?我不知道怎么面对父母,怎么面对朋友,怎么面对努力了整整一个学生生涯的的自己!收到毁约通知当天,我在小红书如实发布经历,帖子迅速获得热度,但仅仅几个小时过后,却在无任何违规通知、账号显示正常的情况下,被悄无声息限流屏蔽——只有我自己能看见,外人完全无法点开,后续相关内容也全部被限制流量。我只是一个普通应届生,只是想说出自己的真实遭遇,腾讯到底动用了何种手段,让一个讲述事实的声音被如此压制?我为我的陈述承担一切法律责任收起
行则将至2026:如果事情已经不可改变,现在更重要的还是抓紧投简历,相信以你本身的实习经历,还是有很强的竞争力的
点赞 评论 收藏
分享
评论
2
5
分享

创作者周榜

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