分布式系统与微服务、数据库、中间件及性能优化全解析
作者:admin | 分类:一年之最 | 浏览:118 | 日期:2025年04月19日《分布式系统与微服务、数据库、中间件及性能优化全解析——以秒杀系统为例》
以下是按照你提供的面试题大纲进行的详细解答,采用清晰的格式便于复制学习:
一、分布式系统 & 微服务
1. 分布式事务模型
出现原因分布式系统中跨服务 / 跨数据库操作时,传统单机事务(ACID)无法保证一致性,需引入分布式事务。
解决方案
2PC(两阶段提交):协调者 + 参与者模式,保证强一致性但性能低(如 XA 协议)。
3PC(三阶段提交):增加 “预询问” 阶段,降低阻塞但仍存在脑裂风险。
TCC(Try-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) 支持 a、a+b、a+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.bytes和max.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 异步处理,降低请求响应时间。
线程池异步处理:对耗时任务(如文件上传、复杂计算)提交到线程池,避免阻塞主线程。
