找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

553

积分

1

好友

67

主题
发表于 19 小时前 | 查看: 2| 回复: 0

在技术面试中,尤其是面向后端开发岗位的面试,面试官往往会围绕核心中间件和数据库知识进行深度考察。以下是对一系列典型面试问题的梳理与解析,涵盖了从项目难点到系统设计等多个维度,旨在帮助你构建完整的知识体系。

1. 实习项目中的难点与解决方案

问题背景:描述一个你在过往项目中遇到的具体技术挑战。 解决思路:清晰阐述问题根源,例如是性能瓶颈、数据一致性或是系统扩展性问题。然后说明你的分析过程、方案选型(比如是引入缓存、优化查询还是重构部分架构)及权衡取舍。 最终效果:用量化指标说明优化成果,如接口响应时间降低X%、系统吞吐量提升Y%,或错误率下降Z%。

2. Redis高并发场景下的优化策略

项目中如何使用Redis? 通常用作缓存层(减轻数据库压力)、会话存储(Session Store)或计数器等。 并发过高Redis扛不住怎么办?

  1. 架构升级:采用Redis Cluster进行分片,将数据分布到多个节点,实现水平扩展。
  2. 读写分离:配置主从复制,将读请求分流到多个从节点。
  3. 多级缓存:在应用本地内存(如Caffeine)和Redis之间增加一层本地缓存,拦截大量热点读请求。
  4. 连接优化:使用连接池避免频繁创建销毁连接,优化客户端配置。
  5. 命令与数据结构优化:避免使用KEYSSMEMBERS等阻塞或低效命令,合理使用Pipeline、批量操作,并根据场景选择最合适的数据结构。

3. 保障多层缓存数据一致性的方案

如何解决? 常见的方案是发布/订阅(Pub/Sub)机制。当数据库数据更新后,发布一个缓存失效事件,所有订阅该消息的应用节点监听并删除本地/分布式缓存中的旧数据。 其他方案?

  • 设置合理的缓存过期时间:最终一致性策略,适用于对一致性要求不非常严格的场景。
  • 基于数据库日志(如MySQL Binlog)的增量同步:通过Canal等中间件监听Binlog,解析后精准失效或更新缓存。此方案耦合度低,对业务代码无侵入。

4. MySQL索引原理与扩展

讲讲MySQL(InnoDB)索引的原理? 核心是B+Tree数据结构。

  • 聚簇索引:表数据本身按主键顺序构建的B+Tree,叶子节点存储完整行数据。
  • 非聚簇索引(二级索引):叶子节点存储的是主键值。通过二级索引查询时,需要先查到主键,再回表到聚簇索引中查找行数据(除非索引覆盖)。
  • 联合索引:遵循最左前缀匹配原则。 了解其他引擎或数据库的索引吗?
  • Memory引擎:默认使用哈希索引。
  • PostgreSQL:支持B-Tree、Hash、GiST(通用搜索树)、GIN(倒排索引)等多种索引类型,应对不同场景(如全文检索、地理数据)。
  • Elasticsearch:使用倒排索引(Inverted Index)实现全文搜索。

5. MySQL主从同步延迟的处理

如何处理?

  1. 定位原因:网络延迟、从库机器性能差、大事务、从库并行复制配置不当等。
  2. 优化方案
    • 硬件/网络:提升从库硬件配置,保证网络质量。
    • 架构:将从库的半同步复制改为并行复制(MTS),并优化相关参数。
    • 业务规避
      • 写后立即读的场景,强制走主库。
      • 将更新操作与后续查询在逻辑上解耦。
    • 分库分表:从根本上降低单库单表的压力。

6. MySQL查询压力大的优化思路

  1. SQL与索引优化:这是首要步骤,通过分析慢查询日志,优化低效SQL语句和索引设计
  2. 架构优化
    • 读写分离:引入从库分担读压力。
    • 缓存:使用Redis等缓存高频查询结果。
    • 垂直/水平分库分表:拆分大表,分散压力。
  3. 硬件/配置升级:升级CPU、内存、使用SSD硬盘,优化innodb_buffer_pool_size等关键参数。

7. 慢SQL的排查与优化流程

排查

  1. 开启并监控慢查询日志 (slow_query_log)。
  2. 使用EXPLAINEXPLAIN ANALYZE命令分析SQL执行计划,关注type(访问类型)、key(使用索引)、rows(扫描行数)、Extra(额外信息)等字段。 优化
  3. 优化查询语句:避免SELECT *,减少联表,优化子查询。
  4. 优化索引:检查是否命中索引,创建缺失索引,删除冗余索引。
  5. 考虑业务逻辑优化:是否可以通过分批查询、数据归档等方式减轻单次查询压力。

8. 如何创建正确高效的索引?

  1. 考虑查询频率:为WHEREORDER BYGROUP BYJOIN条件中的高选择性列创建索引。
  2. 遵循最左前缀原则:设计联合索引时,将最常用作查询条件的列放在最左边。
  3. 避免过多索引:索引会增加写操作开销。定期审查并删除未使用或重复的索引。
  4. 选择索引类型:默认使用B+Tree。对于等值查询且数据离散度极高的列,可考虑哈希索引(如Memory引擎)。
  5. 使用覆盖索引:让索引包含查询所需的所有字段,避免回表。

9. 索引数据量庞大的影响

数据插入和更新的角度看:

  • 插入变慢:每次插入都需要维护B+Tree结构,进行节点的分裂与平衡,索引越多开销越大。
  • 更新(尤其是更新索引键值)变慢:等同于先删除旧索引项,再插入新索引项,成本很高。
  • 页分裂与空间浪费:频繁更新可能导致页分裂,产生碎片,降低空间利用率。
  • 缓冲池效率:庞大的索引会挤占InnoDB Buffer Pool空间,影响热数据的缓存命中率。

10. RabbitMQ与Kafka的核心区别

  • 设计模型与吞吐量:RabbitMQ是传统的企业级消息代理(Broker),注重消息的可靠投递和复杂路由;Kafka是分布式流式数据平台,为高吞吐、持久化日志而设计,吞吐量通常更高。
  • 消息消费模式:RabbitMQ基于队列,消息被消费后即删除(或进入死信队列);Kafka基于主题分区和消费者组,消息按偏移量消费并可被多个消费者组重复消费,具备消息回溯能力。
  • 消息顺序:RabbitMQ单个队列内保证顺序;Kafka单个分区内保证严格顺序。
  • 协议与功能:RabbitMQ支持AMQP等丰富协议,功能全面(如死信队列、优先级队列);Kafka协议相对简单,核心功能围绕流处理。

11. Kafka实现延迟消息的方案

Kafka本身不直接支持延迟消息。常见实现方式:

  1. 外部调度器:将消息先持久化到数据库,由调度任务在到达指定时间后,再将消息投递到Kafka目标主题。
  2. 多级主题+时间轮:创建多个不同延迟级别的主题(如delay_1s, delay_5s)。生产者将消息按延迟时间投递到对应主题,消费者组监听这些主题,并在消息到期后将其转发到真实业务主题。这需要自行实现一个中继服务。

12. MQ如何保证消息可靠消费?

这是一个端到端的保证,需生产者、Broker、消费者共同参与:

  1. 生产者确认:开启publisher confirm(RabbitMQ)或设置acks=all(Kafka),确保消息成功到达Broker。
  2. Broker持久化:消息在Broker端写入磁盘,防止Broker宕机丢失。
  3. 消费者确认
    • RabbitMQ:手动ACK,业务处理成功后再确认,失败可NACK重入队列。
    • Kafka:手动提交偏移量(enable.auto.commit=false),确保业务处理完成后再提交,避免消息丢失。

13. MQ宕机了怎么办?

  • 生产者端:应有重试机制和降级策略(如将消息暂存本地、记录日志、告警)。
  • 消费者端:通常暂停消费,等待MQ恢复。需确保消费逻辑的幂等性,因为恢复后可能有重复消息。
  • 高可用架构:生产环境必须部署集群(如RabbitMQ镜像队列、Kafka多副本),单个节点宕机不影响整体服务。

14. MQ队列满了怎么办?

  1. 紧急扩容:增加消费者数量,提高消费能力。
  2. 生产者限流/降级:立即对生产者进行限流,并反馈失败或引导至降级流程。
  3. 排查积压原因:是消费端故障(如Bug、性能问题)还是流量洪峰?针对处理。
  4. 临时方案:对于RabbitMQ,可设置队列最大长度或溢出行为(如丢弃队头消息drop-head);对于Kafka,可增加分区数并扩容消费者实例,但长期来看需根据存储和性能规划分区大小。

15. Golang内存泄漏的排查与优化

常见场景

  1. Goroutine泄漏:Goroutine启动后未退出,常见于channel操作阻塞、缺少退出条件。
  2. 全局变量或长生命周期对象持有引用:如将大量数据塞入全局map且只增不减。
  3. 未关闭的资源:如os.File, net.Conn, time.Ticker排查与优化
    • 使用pprof工具:go tool pprof http://localhost:6060/debug/pprof/heap分析堆内存,goroutine分析协程数量。
    • 使用runtime.ReadMemStats监控内存增长。
    • 代码审查:确保defer关闭资源,为Goroutine设计明确的退出通道(context.Context),避免循环引用。

16. 文档去重推荐场景题

目标:保证用户在一定时间窗口或历史范围内不被重复推荐同一文档。 方案

  1. 布隆过滤器 (Bloom Filter):将用户已推荐文档ID集合存入一个布隆过滤器。推荐前先查询,若可能存在(存在误判),则进行二次精确校验(方案2);若绝对不存在,则推荐。适用于海量数据、可接受极低误判率的场景。
  2. Redis Set/ Bitmap:每个用户维护一个已推荐文档ID的集合。推荐时使用SISMEMBER命令判断。此方案精确,但存储开销随推荐历史增长而增加,需设置过期策略。
  3. 混合策略:近期推荐记录(如最近1万条)用精确的Redis Set存储,远期历史用布隆过滤器存储,平衡精度与空间。

17. 算法题:二叉树的右视图

题目:给定一棵二叉树,想象你站在它的右侧,返回你从顶部到底部能看到的节点值。 思路(BFS层次遍历): 对二叉树进行层次遍历,在遍历每一层时,记录该层的最后一个节点值,即为右视图能看到的值。 Golang代码示例


func rightSideView(root *TreeNode) []int {
    var res []int
    if root == nil {
        return res
    }
    queue := []*TreeNode{root}
    for len(queue) > 0 {
        levelSize := len(queue)
        for i := 0; i < levelSize; i++ {
            node := queue[0]
            queue = queue[1:]
            // 如果是当前层的最后一个节点,加入结果集
            if i == levelSize-1 {
                res = append(res, node.Val)
            }
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
    }
    return res
}



上一篇:Proxmox VE 9.1.1实战:通过OCI原生运行Docker镜像指南
下一篇:Linux驱动开发中DMA编程实战:一致性映射与流式映射详解
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-8 23:07 , Processed in 1.086997 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表