腾讯秋招面试,人麻了。。。
💼 岗位职责:
- 负责腾讯蓝鲸后台相关的开发工作;
- 负责腾讯游戏相关底层支撑平台的开发工作。
📋 任职要求:
- 计算机相关专业,3 年及以上相关工作经验,有扎实的计算机理论基础;
- 三年以上 Linux 环境服务器开发的经验,精通 Socket 网络编程、服务器开发工作;
- 三年以上使用 Golang 语言开发的经验,熟悉 IO 复用、多线程、RPC 等基础技术和框架;
- 熟悉分布式系统,微服务系统架构设计及开发;熟练使用 MongoDB、Redis 等 NOSQL;
- 良好的学习能力、沟通能力、适应能力,责任心强,能在压力下独立解决问题;熟悉容器技术,了解微服务的优先;热爱互联网,喜欢挑战者优先。
✨ 面试问题回顾:
1. 自我介绍
自我介绍是面试的开场环节,要简洁明了地介绍自己的姓名、工作经验、擅长的技术领域以及个人优势。
2. 为什么离职
离职原因要真诚且合理,可以从职业发展、个人成长、工作环境等方面来回答。
3. 会哪些语言
主要使用 Golang,Java 等等,按自己的技术栈说明,尤其是说明自己的擅长的地方
4. 职业规划
职业规划要体现出自己的目标和努力方向。例如:在短期内,我希望能够深入学习 Golang 的高级特性和优化技巧,提升自己的开发效率和代码质量。长期目标是能够带领团队,为公司的技术发展做出更大的贡献。
5. 对未来从事行业的看法
可以结合行业趋势和自己的兴趣来回答。
6. 实现一个 golang 版简易内存缓存
实现一个简易的内存缓存,要求如下:
- 支持存储任意对象
- 支持指定 key 的过期时间,过期自动删除
go代码解读复制代码package main import ( "time" ) type CacheItem struct { value interface{} expiration time.Time } type MemoryCache struct { items map[string]*CacheItem } func NewMemoryCache() *MemoryCache { return &MemoryCache{ items: make(map[string]*CacheItem), } } func (c *MemoryCache) Set(key string, value interface{}, expiration time.Duration) { c.items[key] = &CacheItem{ value: value, expiration: time.Now().Add(expiration), } } func (c *MemoryCache) Get(key string) (interface{}, bool) { item, ok := c.items[key] if!ok { return nil, false } if time.Now().After(item.expiration) { delete(c.items, key) return nil, false } return item.value, true }
7. 遍历 map 的时候为什么不直接删除元素
在遍历map
的时候直接删除元素可能会导致遍历的顺序受到影响,或者某些元素可能会被跳过。这是因为map
的遍历是无序的,并且在遍历过程中直接删除元素可能会导致内部数据结构的变化,从而影响遍历的结果。
8. map 的 value 使用指针和不使用指针有什么区别
- 指针的优点:map大对象可以减少内存 copy,因为只需要存储指针而不是整个对象。允许修改数据,通过指针可以直接修改指向的对象。可以方便的判断是否是nil。
- 指针的缺点:额外的访问开销,需要通过指针间接访问对象。内存管理复杂,可能存在空指针问题。
- 不使用指针的优点:不需要间接访问内存,访问速度更快。避免空指针的引用,更加安全。
- 不使用指针的缺点:增加内存开销,因为需要存储整个对象。不方便修改,需要重新赋值整个对象。
9. map 中 key 可以使用的类型
不能作为map
中key
的类型有slice
、map
、func
。这是因为这些类型不满足map
的key
必须是可比较类型的要求。而基本数据类型(如int
、string
等)和结构体(如果结构体的字段都是可比较类型)可以作为map
的key
。
10. go 的指针和 C/C++的区别
- Go 指针:强调安全性,避免指针运算,减少了因指针运算导致的错误。有垃圾回收机制,不需要手动管理内存,降低了内存泄漏的风险。使用切片代替数组进行灵活的内存操作,更加方便和安全。
- C/C++ 指针:支持指针运算,可以直接对指针进行加减操作,灵活性高但也容易出错。需要手动管理内存,容易导致内存泄漏和悬空指针问题。C++ 有引用机制,但与 Go 的指针还是有很大的不同。
11. go 的并发模型
Go 的并发模型主要是协程和通道(channel)。协程是一种轻量级的线程,由 Go 运行时管理,创建和切换开销极小,适合高并发场景。通道用于协程之间的通信,可以保证数据的安全传递。
12. 说一下进程,线程,协程
- 进程:独立运行的程序实例,拥有自己的内存空间和系统资源。进程切换开销较大,因为需要切换内存空间、寄存器等。
- 线程:进程中的执行单元,共享进程的内存空间。线程切换开销较小,因为不需要切换内存空间。
- 协程:比线程更轻量级的并发单元,由 Go 运行时管理。协程创建和切换开销极小,适合高并发场景。协程之间通过通道进行通信。
13. 协程切换是在用户态还是内核态
协程切换是在用户态进行的。这意味着协程的切换不需要进行系统调用,切换开销极小。相比之下,线程切换通常需要在内核态进行,开销较大。
14. channel 被关闭了,读和写有什么问题
- 写:如果向一个已关闭的通道写数据,会导致 panic。
- 读:如果从一个已关闭的通道读数据,会返回通道类型的零值。如果通道中还有未读取的数据,会先读取完这些数据,然后再返回零值。
15. 聊项目
- 消息队列:数据倾斜问题:可以通过负载均衡、分区等方式来解决数据倾斜问题。数据不丢:可以使用持久化存储、确认机制等方式来保证数据不丢失。重复消费:可以通过幂等性处理、唯一标识等方式来解决重复消费问题。
- Redis:使用hash:可以将一个复杂的对象存储在一个hash结构中,方便管理和查询。使用Pipline:可以将多个命令打包发送给 Redis 服务器,提高性能。bigkey拆解:对于大的键值对,可以进行拆解,例如将一个大的列表拆分成多个小的列表,或者将一个大的字符串拆分成多个小的字符串。
- 数据库:性能优化:可以通过索引、缓存、优化查询语句等方式来提高数据库的性能。分库分表:当数据量较大时,可以进行分库分表,将数据分散到多个数据库或表中,提高查询效率。
16. 云平台的主要功能
- 快速接入设备:提供方便的接口和工具,让设备能够快速接入云平台。
- 第三方接入方便:支持第三方应用接入云平台,提供开放的 API 和 SDK。
- 监控告警:实时监控设备和应用的运行状态,当出现异常情况时及时发出告警。
- 报表生成:生成各种报表,帮助用户了解设备和应用的运行情况。
17. 设备是怎么发现服务的
设备添加流程中,会告诉设备要连接哪些服务。例如,可以通过配置文件、网络广播、DNS 服务等方式让设备知道要连接的服务地址和端口号。
18. 为什么使用 TCP 长连接
- 减少连接建立和拆除的开销:TCP 连接的建立和拆除需要进行三次握手和四次挥手,开销较大。使用长连接可以避免频繁的连接建立和拆除,提高性能。
- 保持实时通信:长连接可以保持客户端和服务器之间的通信通道,方便实时数据的传输。
- 减少带宽消耗:对于频繁通信的场景,使用长连接可以减少每次连接建立和拆除时的网络开销。
- 心跳机制:可以通过心跳机制检测连接的有效性,及时发现和处理连接故障。
- 节约资源:长连接可以减少服务器的资源消耗,因为不需要频繁地创建和销毁连接。
19. TCP 长连接对服务器那些资源有消耗
- 内存消耗:每个连接都需要占用一定的内存空间,用于存储连接状态、数据缓冲区等。
- 文件描述符:每个连接都需要一个文件描述符,当连接数量较多时,可能会耗尽服务器的文件描述符资源。
- CPU 使用:处理连接的读写操作、心跳检测等都需要消耗 CPU 资源。
- 网络带宽:长连接可能会占用一定的网络带宽,特别是在数据传输频繁的情况下。
- 连接表:服务器需要维护一个连接表,记录所有的连接信息,这也会占用一定的内存空间。
- 网络栈资源:包括 TCP 协议栈的各种缓冲区、定时器等资源。
20. linux 系统 fd 的上限是多少?
在 Linux 系统中,文件描述符(fd)的上限可以通过系统配置进行修改。一般来说,默认的上限是比较小的,但可以通过修改系统参数来提高上限。例如,可以通过修改/proc/sys/fs/file-max
文件来增加文件描述符的上限。理论上,根据机器的配置,可以说没有限制。
21. TCP 长连接是怎么维持的
- 传输层心跳机制:TCP 协议本身有保活机制,可以通过设置
SO_KEEPALIVE
选项来启用。当连接在一段时间内没有数据传输时,TCP 会发送保活探测报文,检测连接的有效性。 - 应用层心跳机制:在应用层实现心跳机制,可以更加灵活地控制连接的状态。例如,可以定期发送心跳报文,检测连接是否正常。
- SO_KEEPALIVE 选项:这是一种由操作系统提供的保活机制,可以在一定时间内没有数据传输时,自动发送探测报文,检测连接的有效性。
22. mqtt 负载均衡怎么做的?
- DNS 负载均衡:通过 DNS 服务器将客户端的请求分发到不同的 MQTT 服务器上。
- 代理层负载均衡:使用代理服务器,将客户端的请求转发到不同的 MQTT 服务器上。
- 集群负载均衡:将多个 MQTT 服务器组成一个集群,通过负载均衡算法将客户端的请求分发到不同的服务器上。
23. 服务器故障了怎么处理
- 故障转移:当服务器发生故障时,将客户端的连接转移到其他正常的服务器上。
- 监控检查和监控:通过监控系统及时发现服务器故障,并进行报警。
- 数据复制和同步:保证数据的冗余备份,当服务器故障时,可以从其他服务器恢复数据。
- 隔离修复:将故障服务器隔离,进行修复和调试。
- 重新加入集群:修复后的服务器可以重新加入集群,继续提供服务。
24. 为什么选择 kafka
选择 Kafka 的原因可能有以下几点:
- 高吞吐量:Kafka 能够处理大量的消息,具有很高的吞吐量。
- 分布式架构:Kafka 是分布式的,可以水平扩展,适应大规模的数据处理需求。
- 持久性:Kafka 可以将消息持久化存储,保证数据的可靠性。
- 高可用性:Kafka 具有高可用性,能够自动进行故障转移,保证系统的稳定性。
- 灵活的订阅模式:Kafka 支持多种订阅模式,可以满足不同的业务需求。
25. Apache pulsar 知道吗?
Apache Pulsar 是一个开源的分布式消息流平台,具有高吞吐量、低延迟、可扩展性强等特点。它与 Kafka 类似,但也有一些不同之处,例如 Pulsar 支持多租户、分层存储等功能。
26. 消息积压怎么办?
- 新 topic 去处理:可以创建一个新的 topic,将积压的消息转移到新的 topic 中进行处理。
- 增加消费者:增加消费者的数量,提高消息的处理速度。
27. 给 app 推消息是怎么实现的
给 app 推消息可以通过多种方式实现,例如使用推送服务提供商(如极光推送、个推等),或者自己搭建推送服务器。一般来说,推送消息需要以下步骤:
- 注册推送服务:在推送服务提供商处注册应用,获取应用的唯一标识。
- 集成推送 SDK:在 app 中集成推送服务提供商的 SDK,实现推送功能。
- 发送推送消息:通过推送服务提供商的接口或者自己搭建的推送服务器,向 app 发送推送消息。
28. 为什么要把推送服务分开
将推送服务分开可以实现解耦,提高系统的可维护性和可扩展性。如果将推送服务与其他业务逻辑混合在一起,会增加系统的复杂性,不利于维护和扩展。同时,将推送服务分开还可以提高推送的效率和稳定性,因为可以专门针对推送服务进行优化和管理。
欢迎关注 ❤
我们搞了一个**********,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:"*****************",备注:牛客。
#面经##Go语言##腾讯##面试题##面试#汇总高频且经典的Go面试题,Go面试不用东奔西走,看这个面试题就Go了。