置顶

分布式系统与微服务、数据库、中间件及性能优化全解析

作者:admin | 分类:一年之最 | 浏览:118 | 日期:2025年04月19日

分布式系统与微服务、数据库、中间件及性能优化全解析——以秒杀系统为例》

以下是按照你提供的面试题大纲进行的详细解答,采用清晰的格式便于复制学习:

一、分布式系统 & 微服务

1. 分布式事务模型

出现原因分布式系统中跨服务 / 跨数据库操作时,传统单机事务(ACID)无法保证一致性,需引入分布式事务。

解决方案

2PC(两阶段提交):协调者 + 参与者模式,保证强一致性但性能低(如 XA 协议)。

3PC(三阶段提交):增加 预询问阶段,降低阻塞但仍存在脑裂风险。

TCCTry-Confirm-Cancel:业务自定义补偿逻辑,适用于高并发场景(如支付宝交易)。

本地消息表:通过消息表异步同步状态,保证最终一致性(需定时任务对账)。

消息事务(MQ:利用 RocketMQ 等中间件的事务消息机制,异步确保一致性。

CAP 理论

Consistency(一致性):所有节点数据一致。

Availability(可用性):非故障节点可正常响应请求。

Partition tolerance(分区容错性):网络分区时系统仍能运行。结论:三者不可兼得,分布式系统通常优先 AP(如微服务)或 CP(如 ZooKeeper)。

最终一致性通过异步机制(如 MQ 重试、定时对账)逐步达到一致,适用于非实时场景(如订单状态更新)。

2. 微服务组件(Spring Cloud

技术选型

 

功能

Spring Cloud 方案

替代方案

服务注册 / 发现

Nacos/Eureka

Consul/Zookeeper

网关

Spring Cloud Gateway

Zuul/NGINX

配置中心

Spring Cloud Config

Apollo/Nacos

限流熔断

Sentinel/Hystrix

Resilience4j

Gateway

核心功能:路由转发、请求过滤、限流、熔断、灰度发布。

断言(Predicate)匹配请求条件(如路径、Header),过滤器(Filter)修改请求 / 响应。

Nacos

动态服务发现:支持 DNS/HTTP 协议,客户端主动拉取服务列表(默认 30 秒更新)。

配置中心:支持动态刷新配置(@RefreshScope),配置版本管理。

Sentinel

功能:流量控制(QPS / 线程数限流)、熔断降级(慢响应 / 异常比例 / 异常数熔断)、系统保护。

资源定义:通过 @SentinelResource 注解或 API 定义保护资源。

3. 服务链路追踪(Skywalking

实现原理

数据采集:通过 Agent 探针(如 Java Agent)拦截服务调用,生成 TraceID Span(记录请求路径、耗时、参数等)。

数据传输:将 Span 数据通过 HTTP/gRPC 发送至 Collector

存储与分析:数据存储于 Elasticsearch/MySQL,提供链路拓扑、慢请求分析、服务依赖图。

核心概念

Trace:一次完整请求的链路(跨服务调用)。

Span:单个服务内的调用单元(如方法调用、数据库操作)。

4. 服务注册发现(Nacos

心跳检测

客户端默认每 5 秒向 Nacos 发送心跳,服务端 15 秒未收到标记为 不健康30 秒未收到则剔除。

支持 TCP/HTTP 心跳,可通过spring.cloud.nacos.discovery.heart-beat-interval配置间隔。

服务列表更新

客户端拉模式:定时(30 秒)从 Nacos 拉取全量服务列表,对比本地缓存差异更新。

服务端推模式:Nacos 通过长连接(HTTP/2)主动推送变更通知(需客户端支持)。

5. 分布式锁

Redis 实现

单节点方案

命令:SET key value NX PX 5000(原子性加锁,设置过期时间防死锁)。

释放锁:用Lua脚本验证并删除(保证原子性)。

Redisson

基于 Java 对象封装,实现可重入锁、公平锁、读写锁。

原理:通过RedissonLock对象在 Redis 存储锁信息(UUID + 线程 ID),支持自动续期(看门狗机制)。

RedLock 算法

在多个 Redis 节点(>=3)上加锁,多数节点成功则认为加锁成功,避免单节点故障。

缺点:网络分区时可能出现锁失效,需配合时钟同步。

ZooKeeper 对比

实现:通过临时顺序节点(EPHEMERAL_SEQUENTIAL)实现公平锁,利用 Watcher 机制监听锁释放。

优点CP 模型,故障恢复后锁仍有效;天然支持公平锁。

缺点:性能低于 Redis(尤其写场景),适合强一致性场景。

6. 服务限流熔断(Sentinel

滑动窗口

将时间划分为多个固定大小的窗口(如 1 秒分 10 个窗口,每个窗口 100ms),请求计数在窗口内累加。

窗口切换时,保留前一个窗口的部分计数(如滑动比例),平滑统计流量。

熔断策略

慢响应熔断:请求耗时超过阈值且比例达标,触发熔断(如慢请求比例 > 50%)。

异常比例熔断:异常请求比例超过阈值(如 1 分钟内异常率 > 50%)。

异常数熔断:指定时间内异常数超过阈值(如 10 秒内 5 次异常)。

7. 服务鉴权设计

网关鉴权分离

Gateway 统一处理认证(如 JWT 解析),通过 Filter 链校验 token 有效性,失败则拒绝请求。

优点:集中式管理,避免每个服务重复开发鉴权逻辑。

JWT 实现

结构Header(算法)+Payload(用户信息)+Signature(加密签名,防篡改)。

流程

用户登录,服务端生成 JWT(含过期时间、权限信息)。

客户端携带 JWT 至网关,网关验证签名并解析 Payload,传递用户信息至下游服务。

服务端可通过 Payload 直接获取权限,无需多次查询数据库。

二、数据库

1. MySQL 索引优化

B + 树结构

叶子节点存储数据指针(InnoDB 聚簇索引存数据行),非叶子节点仅存键值,便于范围查询。

最左前缀原则

组合索引按顺序匹配查询条件的最左字段(如索引 (a,b,c) 支持 aa+ba+b+c 查询)。

覆盖索引

查询字段均在索引中(如 EXPLAIN Extra 显示 “Using index”),避免回表查询。

索引失效场景

条件中使用函数(如DATE(create_time))、模糊查询左匹配(%abc)、类型转换(字符串列传数字)。

联合索引未满足最左前缀、OR 条件中有非索引字段。

2. 分库分表策略

数据分片方案

垂直分片:按业务拆分(如订单库、用户库),解决单库业务压力。

水平分片:按字段哈希(如 user_id % 1024)或范围(如按时间分库),分散单表数据量。

冷热数据分离

热数据(近期活跃)存于高性能存储(如 SSD),冷数据(历史数据)归档至 Hive/OSS,定期删除或迁移。

3. 事务机制

隔离级别

 

级别

脏读

不可重复读

幻读

Read Uncommitted

Read Committed

Repeatable Read

Serializable

MVCC 解决幻读

通过版本号(隐藏字段trx_id)和 undo 日志,事务读取时根据可见性规则(如低水位、高水位)过滤数据,避免幻读。

锁表排查

查看锁状态:SHOW ENGINE INNODB STATUS,定位LOCK WAIT的事务 ID

杀死事务:KILL [事务ID],分析业务逻辑是否存在锁竞争(如大量行锁升级为表锁)。

4. 慢查询优化

Explain 执行计划

重点关注:type(最好为const/eq_ref,最差为ALL)、key(使用的索引)、rows(扫描行数)。

慢日志分析

开启慢日志:set global slow_query_log=on;,设置阈值(long_query_time默认 10 秒)。

工具:用mysqldumpslow按频率 / 耗时排序慢 SQL,或用pt-query-digest生成分析报告。

5. 大数据量处理

3000w 数据清理

分批删除:DELETE FROM table WHERE id < 10000 LIMIT 1000;,避免锁表时间过长。

建新表迁移:新建空表,插入过滤后的数据,重命名表替换原表。

分页查询优化

避免SELECT * FROM table LIMIT 1000000, 10(扫描 1000010 行),改用覆盖索引 + 子查询:

 

SELECT * FROM table t1

JOIN (SELECT id FROM table LIMIT 1000000, 10) t2 ON t1.id = t2.id;

6. 高可用方案

读写分离

主库(Master)处理写请求,从库(Slave)处理读请求,通过中间件(如 MyCat/MaxScale)路由。

延迟问题:业务允许时读从库,否则强制读主库(如订单详情页)。

主从同步

异步复制:主库写入 Binlog 后立即返回,从库异步拉取(性能高,可能丢数据)。

半同步复制:主库等待至少一个从库确认接收 Binlog 后返回(强一致性,性能略降)。

7. 存储引擎差异(InnoDB vs MyISAM

 

特性

InnoDB

MyISAM

事务支持

支持(ACID

不支持

锁粒度

行锁(默认)

表锁

外键支持

支持

不支持

存储结构

聚簇索引(数据文件 *.ibd

非聚簇索引(*.frm/.MYD/.MYI

适用场景

高并发写、事务场景

读多写少、非事务场景

三、中间件

1. Redis

缓存异常场景

穿透:查询不存在的数据(如恶意请求),解决方案:布隆过滤器拦截、空值缓存(设置短过期时间)。

击穿:热点 Key 过期瞬间大量请求打穿缓存,解决方案:互斥锁(如 Redisson)、逻辑过期(异步刷新)。

雪崩:大量 Key 同时过期,解决方案:随机过期时间、限流熔断、主从 + 哨兵高可用。

预热方案:启动时批量加载热点数据(如RedisPipeline批量写入),或通过异步任务预热。

持久化机制

RDB:定时快照(如save 900 1),恢复速度快但可能丢失最近数据。

AOF:记录写命令日志(如appendfsync everysec),数据更安全但文件体积大。抉择:默认两者结合,重要业务优先 AOF,性能敏感场景可仅用 RDB

数据结构应用

Zset:排行榜(如用户积分排序,ZADD rank 100 user1)。

Hash:购物车(HSET cart:123 item:1 count 2 price 10.9)。

内存淘汰策略

LRU(最近最少使用):淘汰长时间未访问的数据(如volatile-lru/allkeys-lru)。

过期键删除:定期扫描 + 惰性删除,结合内存淘汰策略处理内存不足。

2. Kafka

消费延迟处理

分区扩容:增加分区数提升消费并行度(需注意有序性场景)。

Flink 并行消费:通过 Flink Parallelism 设置并行度,配合 Kafka 分区数实现负载均衡。

高可用设计

副本同步:每个分区多个副本(Replica),Leader 处理读写,Follower 异步复制数据。

零拷贝原理:通过 Linux 内核sendfile直接将数据从内核缓冲区传输到 Socket,避免用户态拷贝。

消息积压解决方案

批量消费:增大fetch.max.bytesmax.poll.records,减少拉取次数。

异步处理:消费后将消息存入本地队列(如 Disruptor),后台线程异步处理业务逻辑。

3. RocketMQ

消息可靠性

事务消息:两阶段提交(发送 Half 消息执行本地事务提交 / 回滚消息),确保最终一致性。

重试机制:消费失败后自动重试(默认 16 次),可配置死信队列(DLQ)处理无法消费的消息。

顺序消费保证

通过MessageQueue分区 +HashKey路由(如同一订单 ID 路由到同一分区),确保分区内顺序。

延时消息实现

发送时设置延迟级别(如setDelayTimeLevel(3)表示延迟 10 秒),Broker 将消息存入延迟队列,到期后投递到目标队列。

五、性能优化

1. 压测工具(JMeter

参数配置

线程组:设置Number of Threads(并发数)、Ramp-Up Period(启动时长,避免瞬间压垮系统)。

采样器:添加 HTTP 请求,设置HTTP Header Manager(如 Content-Type)、Cookie Manager

监听器:添加Aggregate Report(查看 QPS、响应时间、错误率)、Backend Listener(实时监控服务器指标)。

QPS 控制

通过Constant Throughput Timer固定每秒请求数,模拟真实流量波动。

2. 慢接口定位

SQL 优化:用 Explain 分析执行计划,添加缺失索引,避免 Select *

索引分析:检查是否存在冗余索引,分析慢日志中的 SQL 是否命中索引。

缓存失效:排查缓存穿透 / 击穿,调整缓存过期时间,使用本地缓存(如 Caffeine)减少 Redis 访问。

3. 系统瓶颈排查

CPU 打满

工具:top定位高 CPU 进程top -Hp [pid]查看线程printf "%x\n" [tid]转十六进制jstack [pid] | grep 0x...分析线程栈(如死循环、锁竞争)。

GC 频繁

工具:jstat -gcutil [pid] 1000查看 GC 频率和耗时jmap -histo [pid]查看对象分布调整堆内存大小(-Xms/-Xmx)或优化大对象创建。

连接池耗尽

检查数据库连接数(show variables like 'max_connections'),调整连接池参数(如 HikariCP maxPoolSize),排查未释放的连接(如事务未提交)。

4. 异步化设计

MQ 削峰填谷:将非核心流程(如日志记录、短信通知)通过 MQ 异步处理,降低请求响应时间。

线程池异步处理:对耗时任务(如文件上传、复杂计算)提交到线程池,避免阻塞主线程。




发表评论

取消
微信二维码
支付宝二维码