不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • Python

  • GO

  • Java

  • 业务问题

  • 关键技术

  • 项目常识

    • 01.DDD领域驱动设计
    • 02.Redis_JWT_三方登录
    • 03.Restful风格
    • 04.三方支付
    • 21.后端场景题Part1
      • 01.场景题Part1
        • 1、订单取消时刚好付款
        • 2、避免重复下单
        • 3、Redis 机器爆了
        • 4、导出excel慢
        • 5、百万数据导入数据库
        • 6、1000亿数据插入HashMap
        • 7、数据库连接池爆满
        • 8、消息队列故障兜底
        • 9、CPU 飙高排查
        • 10、Redis 内存溢出 排查
        • 11、select 百万行 内存会飙升么
        • 12、10亿个数据中找出最大的10000个
        • 13、几亿日志 搜索热度最高十个
        • 14、推送已读和未读消息
        • 15、一个文件快速下发到100w个服务器
    • 22.后端场景题Part2
  • 计算机基础

  • 常识
  • 项目常识
xiaonaiqiang
2024-12-19
目录

21.后端场景题Part1

# 01.场景题Part1

# 1、订单取消时刚好付款

一笔订单,在取消的那一刻用户刚好付款了,怎么办?

  • 分布式锁,若已支付,则拒绝取消
  • 若订单取消和支付同时发生,则优先处理取消逻辑,支付操作触发退款
  • 若支付成功,订单状态需回滚为已支付,取消逻辑自动失效

# 2、避免重复下单

  • 如何避免用户重复下单(多次下单未支付,占用库存)
  • 给每次下单请求生成唯一标识(如 UUID),确保同一请求只被提交一次
  • 当用户发起下单请求时,检查 Redis 是否存在未完成的订单
    • SET user:order:<user_id>:<product_id> true NX EX 300

# 3、Redis 机器爆了

线上发现 Redis 机器爆了,如何优化?

  • **原因1:**缓存数据超出内存容量,Redis 触发 OOM

    • 将数据分片(Sharding)到多个 Redis 实例,分担单节点内存压力
    • 调整淘汰策略,使用 volatile-lru ,确保热点数据优先保留
  • **原因2:**大量慢查询导致 CPU 处理过载,突发流量导致网络带宽耗尽

    • 开启慢查询日志,优化耗时较长的命令(如 ZUNIONSTORE 或 KEYS)
    • 主节点处理写请求,从节点分担读流量
  • **原因3:**某些 key 的访问频率过高,导致单节点资源耗尽

    • 使用一致性哈希将热点数据分布到多个节点
    • 将热点数据缓存在客户端
    • 在 Redis 节点启动时预加载热点数据,避免高并发初始加载

# 4、导出excel慢

项目上有个导出 excel 场景发现很慢,怎么优化?

  • 原因1:数据库查询速度慢?例如:未加索引、查询过多冗余数据等
    • 优化SQL查询,并结合redis缓存
  • 原因2:数据处理逻辑复杂?例如:内存占用过高、循环操作导致性能问题
    • 将 Excel 导出改为异步任务,用户提交导出请求后,后台生成文件,完成后通知用户下载

# 5、百万数据导入数据库

项目上需要导入一个几百万数据 excel 文件到数据库中,有哪些注意点?

  • 将 Excel 数据按 1,000 行为一批解析,逐步加载到内存
  • 在解析过程中检查数据格式,并将不合法的数据写入日志,生成错误报告
  • 每 1,000 行使用 LOAD DATA INFILE 提交到数据库,保证写入效率
  • 用户提交导入任务后,通过消息队列将任务下发至后台服务,完成后通知用户
  • 记录导入进度及错误数据行号,支持任务失败时重新导入

# 6、1000亿数据插入HashMap

如果没有内存限制,如何快速、安全地将 1000 亿条数据插入到 HashMap 中?

  • 去重

    • 将数据分割成1000份,1000个线程并发对数据hash并对1000取余,均分到1000个map中
  • 直接初始化一个足够大的容量,避免多次扩容

    • myMap := make(map[int]string, 100_000_000_000)
  • 数据上可以选择使用 concurrent-map(concurrent-map 将一个 map 分为多个小 map(分片),每个分片有自己的读写锁)

    • 将这1000个map并发写入到 concurrent-map 对象中

# 7、数据库连接池爆满

线上数据库连接池爆满问题排查

  • 查看数据库的慢查询日志:是否存在大量慢查询
  • 是否存在非预期的大量查询、复杂查询或死锁
  • 检查代码逻辑,是否有连接未关闭(如使用了连接池但忘记释放 conn.close())
  • 是否因异常流量或特定用户行为导致(某些 IP 突增请求)
  • 查看 CPU、内存、磁盘 I/O 是否是瓶颈
  • 最大连接数(max_connections)是否过小?是否适应当前的流量?
  • 最大连接数(max_connections)是否过小?是否适应当前的流量?

# 8、消息队列故障兜底

线上消息队列故障,兜底改造方案

  • 短期内,通过 Redis 缓存消息,批量重试写入 RabbitMQ,同时暂停非核心业务流量,缓解系统压力
  • 长期来看,我们升级 RabbitMQ 到镜像队列模式,确保节点高可用
  • 同时增强消费者的幂等机制,避免重复消费
  • 还增加了监控告警,防止类似问题复发

# 9、CPU 飙高排查

  • 通过 top 定位高 CPU 的进程,并使用 pprof 采集 CPU Profiling 数据
  • 分析 Profiling 火焰图发现某个 Goroutine 在执行死循环,且未能正确退出
  • 检查代码,发现问题出在任务分片处理逻辑中,循环条件遗漏了退出判断

# 10、Redis 内存溢出 排查

排查过程

  • 使用 info memory 确认内存使用超出 maxmemory 限制
  • 使用 --bigkeys 和 memory stats 命令分析大 Key,发现一个 List 类型 Key 超过 500MB
  • 检查过期策略,发现部分 Key 未设置 TTL,导致长期堆积
  • 检查碎片率,fragmentation_ratio 超过 1.5,表明存在内存碎片

解决方案:

  • 删除超大 Key,并对集合数据进行分片存储
  • 调整淘汰策略为 allkeys-lru,确保超内存时自动淘汰低频 Key
  • 批量为无 TTL 的 Key 设置合理过期时间
  • 扩展 Redis 实例内存至 4GB,并计划迁移到 Redis Cluster

预防措施:

  • 引入 Prometheus + Grafana 监控 Redis 内存使用情况
  • 定期清理冷数据,并设定内存使用报警阈值
  • 在代码层面优化数据结构和存储策略,避免大 Key 和过量 Key 问题

# 11、select 百万行 内存会飙升么

  • 当我们执行 SELECT * FROM 一个有 1000 万行的表时,MySQL 并不会直接将所有数据加载到内存,而是使用流式处理机制逐行读取结果
  • 然而,以下两种情况可能导致内存飙升
    • 客户端一次性缓存了整个结果集
    • 查询中包含复杂操作(如排序、聚合)导致临时表溢出
  • 优化措施
    • 避免 SELECT *,只查询必要字段
    • 通过 LIMIT 和 OFFSET 分批加载数据
    • 为查询添加索引,减少扫描行数
    • 在客户端使用流式读取逐行处理结果

# 12、10亿个数据中找出最大的10000个

  • 如果含较多重复值,先用hash / 依图法去重,可大大节省运算量

  • 使用Hash方法将数据划分成n个partition,每个partition交给一个线程处理

  • 线程的处理逻辑可以采用最小堆,最后一个线程将结果归并

  • 进一步优化:每个线程的处理速度可能不同,快的线程需要等待慢的线程

    • 将数据划分成c×n个partition(c>1),每个线程处理完当前partition后主动取下一个partition继续处理

# 13、几亿日志 搜索热度最高十个

  • 拆分成n多个文件,通过哈希函数 hash(query) % N 将词分成 N 组
  • 对于每个文件,使用map字典进行词频统计
  • 小顶堆排序,依次处理每个文件,并逐渐更新最大的十个词

# 14、推送已读和未读消息

  • 消息内容表 (messages),存储每条站内信的基本信息(消息 ID、内容、发送时间等)

  • 消息偏移表 (message_offset),维护每个用户的消息读取进度(即最后一次已读的消息 ID)

  • 用户获取未读消息时,只需从 messages 表中查询 message_id > last_read_message_id 的记录

  • 更新 message_offset 表,将 last_read_message_id 更新为用户已读的最新消息 ID

# 15、一个文件快速下发到100w个服务器

  • 推荐方案:P2P + 树形分发

初始分发:

  • 文件分片,通过中心服务器向少数(如 1000 台)一级种子服务器分发

树形扩散:

  • 一级种子服务器继续分发文件到二级种子(如 10,000 台)
  • 各节点只需分发文件到下一层,形成分发树,逐步扩散到 100 万台服务器

P2P 加速:

  • 二级种子服务器形成 P2P 网络,服务器间共享文件分片
  • 各节点完成文件后可作为新种子,提高分发速度

优化细节

  • 使用 文件哈希值(如 MD5 或 SHA-256) 校验,确保文件传输无误
  • 限制单节点的并发连接数和传输速率,避免带宽过载
  • 对丢包或未完成的服务器任务,定期重试
  • 允许部分节点通过中心服务器重新获取文件
上次更新: 2025/2/19 16:42:39
04.三方支付
22.后端场景题Part2

← 04.三方支付 22.后端场景题Part2→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式