分享
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
继续分享最新的面经,面试的岗位是**上海某公司的Golang开发岗,给的薪资范围是20~40K**,对`mongodb`要求熟练掌握,所以面试过程中对于`mongodb`也问的比较多。
**下面是我整理好的面经(去除了项目相关的问题)**:

1. 自我介绍?
### 2. mongodb查询优化讲一下?
可以从以下几个方面展开:
1. **索引的使用**:
- 索引是查询优化的核心。MongoDB支持多种索引类型(如单字段索引、复合索引、全文索引等)。合理创建索引可以显著提高查询性能。
- 使用`explain()`方法分析查询计划,查看是否使用了索引以及索引的效率。
2. **查询语句优化**:
- 避免全表扫描:确保查询条件能够命中索引。
- 尽量减少返回的数据量,使用`projection`只返回需要的字段。
- 对于复杂的查询,可以通过拆分查询或使用聚合管道来优化。
3. **分片与副本集**:
- 分片可以将数据分布在多个节点上,从而提高查询性能。
- 副本集主要用于高可用性,但读操作可以分担到从节点以减轻主节点的压力。
4. **硬件和配置优化**:
- 调整MongoDB的内存分配和缓存策略,充分利用服务器资源。
- 定期监控数据库性能,使用工具如MongoDB Atlas或第三方监控工具定位瓶颈。
5. **写操作优化**:
- 批量写入比单条写入更高效。
- 在高并发场景下,考虑调整写关注级别(Write Concern)以平衡性能和一致性。
---
### 3. mongodb和mysql的索引特性上有什么区别?
1. **索引类型**:
- MongoDB支持多种索引类型,包括单字段索引、复合索引、地理空间索引、全文索引和哈希索引。
- MySQL主要支持B+树索引(InnoDB和MyISAM引擎),此外还有全文索引、哈希索引(Memory引擎)等。
2. **索引存储结构**:
- MongoDB默认使用B树作为索引结构,适合范围查询和排序。
- MySQL的InnoDB引擎使用B+树,更适合范围查询和顺序访问。
3. **索引覆盖**:
- MongoDB支持索引覆盖查询(Index-Only Query),即如果查询的所有字段都在索引中,则无需访问文档本身。
- MySQL同样支持索引覆盖,但需要确保查询字段完全包含在索引中。
4. **唯一性约束**:
- MongoDB允许在集合中创建唯一索引,但分布式环境下的唯一性约束需要额外注意。
- MySQL的唯一索引在单机和分布式环境下都更容易实现。
5. **性能影响**:
- MongoDB的写操作会在写入文档的同时更新索引,可能会对性能产生一定影响。
- MySQL的索引维护成本较高,尤其是在大规模更新或插入时。
---
### 4. mongodb设计索引上跟mysql有什么区别?
1. **数据模型差异**:
- MongoDB是文档型数据库,数据以嵌套的JSON格式存储,因此可以在嵌套字段上创建索引。
- MySQL是关系型数据库,数据以表格形式存储,索引设计通常基于列。
2. **复合索引的设计**:
- MongoDB的复合索引顺序非常重要,查询条件必须按照索引定义的顺序匹配才能生效。
- MySQL的复合索引也有顺序要求,但其查询优化器会尝试重排条件以匹配索引。
3. **动态模式的支持**:
- MongoDB支持动态模式,索引设计需要考虑文档结构的多样性。
- MySQL的表结构是固定的,索引设计相对简单。
4. **分布式环境**:
- MongoDB的分片集群需要为分片键创建索引,且分片键的选择对性能有重大影响。
- MySQL在分布式环境中通常通过中间件(如ShardingSphere)实现分片,索引设计不受分片键限制。
5. **索引大小的考虑**:
- MongoDB的索引存储在内存中,过大的索引可能导致性能下降。
- MySQL的索引也占用内存,但其B+树结构更节省空间。
---
### 5. mongodb在创建索引和使用上有什么注意事项吗?
1. **选择合适的字段**:
- 根据查询频率和数据分布选择索引字段,避免为低频查询创建索引。
- 复合索引的字段顺序应根据查询条件的重要性排列。
2. **索引的维护成本**:
- 创建索引会增加写操作的开销,因为每次写入都需要更新索引。
- 删除不必要的索引以减少维护成本。
3. **索引的覆盖能力**:
- 尽量设计索引以支持覆盖查询,减少文档访问次数。
4. **内存限制**:
- 索引需要加载到内存中才能高效工作,因此索引大小不能超过可用内存。
5. **后台创建**:
- 在生产环境中创建索引时,建议使用后台模式(`background: true`),以避免阻塞其他操作。
6. **分片集群的特殊要求**:
- 分片集群需要为分片键创建索引,并确保分片键的选择均衡分布数据。
---
### 6. mongodb和mysql主键的区别?主键会带来什么影响?
1. **主键的生成方式**:
- MongoDB默认为主键字段`_id`生成一个唯一的ObjectId值,也可以自定义主键。
- MySQL的主键通常由用户指定,或者由自增列(AUTO_INCREMENT)生成。
2. **主键的作用**:
- MongoDB的主键用于唯一标识文档,同时也是集合的默认索引。
- MySQL的主键用于唯一标识行,同时是表的聚集索引(InnoDB引擎)。
3. **性能影响**:
- MongoDB的主键索引会影响查询和写入性能,尤其是当主键是随机生成的ObjectId时,可能导致频繁的页分裂。
- MySQL的主键直接影响数据存储的物理顺序,连续递增的主键有助于提高插入性能。
4. **分布式环境**:
- MongoDB的主键在分片集群中需要结合分片键使用。
- MySQL的主键在分布式环境中可能需要额外的协调机制。
---
### 7. kafka怎么保障kafka消息可靠性?
1. **持久化**:
- Kafka将消息持久化到磁盘,确保即使发生故障也能恢复数据。
- 通过配置`acks`参数,可以控制消息的确认级别(如`acks=1`、`acks=all`)。
2. **副本机制**:
- Kafka使用分区副本(Partition Replication)来保证数据的冗余。
- ISR(In-Sync Replica)机制确保只有同步完成的副本才能参与选举。
3. **消息确认**:
- 生产者可以通过`acks`参数设置消息的确认级别,确保消息被成功写入。
4. **消费者确认**:
- 消费者通过手动提交偏移量(Offset)确保消息被正确处理。
5. **事务支持**:
- Kafka支持事务性消息,确保跨分区的消息一致性。
---
### 8. kafka怎么保证消息幂等?
1. **生产者幂等性**:
- Kafka引入了幂等性生产者(Idempotent Producer),通过为每个生产者分配唯一的PID(Producer ID)和序列号(Sequence Number)来确保每条消息只被写入一次。
2. **事务支持**:
- Kafka支持事务性消息,允许跨分区和主题的消息原子性提交。
3. **消费者端处理**:
- 消费者可以通过去重逻辑(如基于消息ID)避免重复处理。
---
### 9. 怎么限制goroutine的上限?
1. **使用信号量(Semaphore)**:
- 使用`sync.WaitGroup`或`chan struct{}`实现信号量,限制并发goroutine的数量。
2. **使用Worker Pool模式**:
- 创建固定数量的worker goroutine,任务通过队列分发给这些worker。
3. **使用第三方库**:
- 使用类似`ants`这样的协程池库,直接设置最大goroutine数量。
---
### 10. sync.map的实现介绍一下?
`sync.Map` 是 Go 标准库中提供的一个并发安全的 map 实现,旨在优化高并发环境下的读写性能。它特别适合于读多写少的场景,并通过内部机制减少锁竞争来提高效率。
##### **核心数据结构**
- **`read`** :这是一个只读缓存,包含一部分或全部的数据副本。它是无锁访问的,因此读操作非常快。
- **`dirty`** :这是一个可写的缓存,包含了所有键值对(包括那些在 `read` 中没有但新添加的)。由于需要支持写入,访问 `dirty` 时会涉及到加锁操作。
- **`entry`** :这是存储实际键值对的结构体。它支持原子操作,允许高效地更新或删除值而无需锁。
##### **工作机制**
1. **读操作**
- 当进行读取时,优先从 `read` 中查找数据。因为 `read` 是无锁的,所以读取速度很快。
- 如果 `read` 中找不到且有未迁移至 `read` 的数据,则检查 `dirty`。这时需要加锁,但这种情况相对较少。
2. **写操作**
- 写入已存在的键值对时,尝试直接更新 `read` 中对应的条目。这通常可以通过原子操作完成,避免了加锁。
- 对于新增的键值对,则会添加到 `dirty` 缓存中。如果 `dirty` 尚未初始化,会先将 `read` 中的数据复制到 `dirty`。
3. **数据迁移**
- 随着时间推移,`dirty` 可能积累大量未迁移到 `read` 的数据。当达到一定条件时,`sync.Map` 会触发一次数据迁移,将 `dirty` 提升为新的 `read` 并清空旧的 `dirty`。
4. **删除操作**
- 删除操作不是立即从 `read` 或 `dirty` 中移除数据,而是标记相应的 `entry` 为已删除。这样可以延迟清理工作,减少内存分配和回收的开销。
##### **适用场景**
- **读多写少**:在这种情况下,`sync.Map` 的设计能够最大化利用其无锁读的优势。
- **动态数据集**:适用于键值对集合经常变化的应用场景。
- **高并发环境**:提供了一种高效的并发控制方式,减少了锁争用。
##### **注意事项**
- 虽然 `sync.Map` 在读多写少的情况下表现优异,但在写密集型应用中可能不如使用传统同步方法(如手动加锁)那样有效。
- 应谨慎评估你的应用场景是否适合使用 `sync.Map`,特别是当你预计会有大量的新键值对插入时。
## 欢迎关注 ❤
我们搞了一个**免费的面试真题共享群**,互通有无,一起刷题进步。
**没准能让你能刷到自己意向公司的最新面试题呢。**
感兴趣的朋友们可以加我微信:**wangzhongyang1993**,备注:面试群。
有疑问加站长微信联系(非本文作者))
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信612 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传