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