腾讯 C++ 后台开发 二面总结

1. 做个简单的自我介绍

您好,我是XXX,XX大学计算机科学与技术专业研究生在读,预计明年6月毕业。本科期间我系统学习了数据结构、算法、操作系统、计算机网络等基础课程,研究生阶段主要研究方向是分布式系统和高性能计算。技术栈方面,我主要使用C++进行后端开发,熟悉多线程编程、网络编程和性能优化,熟练使用MySQL、Redis等中间件,了解分布式系统设计。项目经历上,我在XX公司实习期间参与了分布式存储系统的开发,负责元数据管理模块的设计和实现,这个系统目前已经上线运行,服务于公司内部多个业务部门。我的优势是对底层技术有深入研究,读过Redis、Nginx等开源项目的部分源码,注重代码质量和工程实践。今天很高兴有机会和您交流,希望能加入腾讯。

2. 你的项目是在公司实习做的还是学校课题?用户规模有多大?

这个项目是我在XX科技公司实习期间参与的真实商业项目,已经上线运行了半年多。用户主要是公司内部的各个业务系统,包括推荐系统、广告系统、用户画像系统等大约15个业务方。日活跃请求量在千万级别,峰值QPS能达到5万左右。系统存储的数据规模在PB级别,单集群管理的文件数量超过10亿个。这不是一个demo项目,而是承载了公司核心业务数据的生产系统,对可靠性和性能要求都很高,任何故障都会直接影响业务,所以我们在设计和开发过程中非常注重系统的稳定性和容错能力。

3. 讲讲你项目中的一个技术亮点,重点说说你的分析和设计思路

我重点讲一下元数据管理模块的设计。这个模块的核心挑战是在海量文件场景下,如何快速定位文件元数据并保证高可用。

问题分析:

  • 文件数量超过10亿,单机内存无法存储全部元数据
  • 查询QPS高达5万,需要毫秒级响应
  • 元数据修改频繁,需要保证一致性
  • 不能有单点故障,要求99.99%可用性

设计思路:

  • 采用分片架构,按文件路径hash将元数据分散到多个节点,每个节点负责一部分数据
  • 使用跳表作为内存索引结构,相比红黑树实现更简单,性能相当,支持范围查询
  • 引入WAL预写日志保证数据持久化,元数据修改先写日志再写内存,宕机后可以从日志恢复
  • 实现主从复制,每个分片有一主两从,主节点故障时从节点自动接管
  • 使用Raft协议保证主从数据一致性,写操作需要多数派确认才返回成功

优化细节:

  • 批量操作支持,将多个小请求合并成一个大请求,减少网络开销
  • 读写分离,读请求可以打到从节点,分散主节点压力
  • 热点数据识别,对频繁访问的元数据做本地缓存,命中率达到80%以上

效果:

  • 查询延迟P99在10毫秒以内
  • 支持单节点5万QPS
  • 主节点故障切换时间小于3秒
  • 半年来系统可用性达到99.995%

4. 你们的系统做了哪些容灾措施?

我们的容灾设计是多层次的。

数据层容灾:

  • 主从复制架构,每个分片一主两从,数据三副本存储
  • 跨机房部署,主从节点分布在不同机房,防止单机房故障
  • WAL日志持久化到磁盘,支持故障恢复
  • 定期全量备份和增量备份,备份数据异地存储

服务层容灾:

  • 无状态的接入层,任意节点故障不影响服务
  • 负载均衡自动摘除故障节点
  • 熔断机制,某个分片故障时自动熔断,不影响其他分片
  • 降级策略,极端情况下关闭非核心功能保证核心读写

故障检测和切换:

  • 心跳检测机制,每秒检测节点健康状态
  • 使用Raft协议自动选主,主节点故障3秒内完成切换
  • 脑裂保护,通过多数派机制防止出现双主

演练验证:

  • 定期进行故障演练,模拟各种故障场景
  • 验证过主节点宕机、从节点宕机、网络分区、机房断电等场景
  • 每次演练后总结问题并改进

实际运行中经历过两次主节点故障,都在3秒内完成了自动切换,业务基本无感知。

5. 你们做过压力测试吗?发现了什么问题?

做过多轮压力测试。

测试方法:

  • 使用自研的压测工具,模拟真实业务场景
  • 逐步增加并发,从1000 QPS到10万QPS
  • 持续压测24小时验证稳定性
  • 监控CPU、内存、网络、磁盘IO等指标

发现的主要问题:

第一个问题是内存泄漏。压测几个小时后内存持续增长,最终OOM。通过Valgrind定位发现是日志模块的缓冲区没有正确释放,异常情况下跳过了清理逻辑。修复后改用RAII封装,确保异常安全。

第二个问题是锁竞争。QPS超过3万时性能不再线性增长,通过perf分析发现是全局锁竞争严重。优化方案是将全局锁改为分段锁,每个分片独立加锁,锁粒度降低后性能提升了60%。

第三个问题是网络瓶颈。单机网络带宽打满,成为瓶颈。优化方案是启用数据压缩,对传输的元数据进行压缩,带宽使用降低40%,同时优化序列化协议,从JSON改为Protobuf,序列化性能提升3倍。

第四个问题是磁盘IO。WAL日志写入成为瓶颈,每次写入都fsync导致性能差。优化方案是批量刷盘,积累一批日志再统一刷盘,同时使用SSD替换机械硬盘,IO性能提升10倍。

经过这些优化,单节点QPS从3万提升到5万,P99延迟从50毫秒降到10毫秒。

6. 遇到过什么比较难排查的问题吗?不是通过日志能简单发现的那种

遇到过一个很诡异的问题,系统运行一段时间后偶尔出现请求超时,但日志里看不出任何异常,监控显示CPU、内存、网络都正常,重启后问题消失但过几天又出现。

排查过程:

一开始怀疑是网络问题,抓包分析发现网络层面没问题,数据包正常收发。然后怀疑是锁等待,加了锁监控发现也不是。查看系统调用发现某些请求的read系统调用耗时异常长,达到几百毫秒,但磁盘IO监控显示没有慢IO。

后来用strace跟踪进程,发现问题出在DNS解析上。我们的日志系统会异步上报到远程服务器,使用域名访问,系统会做DNS解析。由于DNS解析是阻塞的,当DNS服务器响应慢时,虽然是在异步线程里,但由于线程池满了,新的日志请求会阻塞,进而影响主线程。

解决方案:

  • 将域名改为IP地址,避免DNS解析
  • 日志上报改为完全异步,使用无锁队列,主线程只负责写队列
  • 增加日志线程池大小,并设置超时机制
  • 添加DNS解析耗时监控

这个问题的难点在于现象不明显,影响范围小,而且涉及到系统底层的DNS解析机制,超出了应用层的范畴。最终通过系统调用跟踪才定位到根因。

7. 系统有没有发生过崩溃?你是如何通过coredump文件分析的?

发生过一次段错误导致的崩溃。线上服务突然挂掉,自动重启后又挂掉,反复几次。

分析过程:

首先确认开启了coredump,通过ulimit -c unlimited设置。拿到coredump文件后用gdb加载,使用gdb ./program core.xxx命令。

执行bt命令查看调用栈,发现崩溃在一个字符串操作函数里,访问了空指针。但这个函数被很多地方调用,不确定是哪个调用路径触发的。

使用frame命令切换到上层栈帧,查看局部变量的值,发现传入的指针确实是NULL。继续往上追溯,发现是从一个map里查询数据,没有判断返回值就直接使用了。

使用info threads查看所有线程状态,发现有个线程在等锁,怀疑是并发问题。打印相关变量的值,发现map在

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

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

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

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

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