服务治理
mysql死锁: juejin.cn/post/733734…
ng问题: juejin.cn/post/684490… juejin.cn/post/711447…
海量数据问题: juejin.cn/post/684490…
服务治理 可用性:超时,重试,并发,幂等,防重,限流,熔断,负载均衡,降级, 可观察性:接口性能埋点上报(流量入口,出口),方法执行时间,全链路追踪,机器监控报警,trace 全链路日志追踪,智能分析推断 可动态性:动态热更新【动态限流,降级,动态负载,以及各种策略配置】 安全性:鉴权,防刷,数据加密。安全生产。
二、服务治理的核心组件
| 组件 | 功能 | 典型工具/框架 |
|---|---|---|
| API 网关 | 统一入口、路由、鉴权、流量控制 | Spring Cloud Gateway |
| 配置中心 | 集中管理配置,支持动态更新 | Nacos、Apollo、Spring Cloud Config |
| 服务注册与发现 | 动态管理服务实例地址 | Nacos、Zookeeper |
| 熔断与降级 | 防止故障扩散,快速失败 | Sentinel、Resilience4j |
| 负载均衡 | 分配请求到健康实例,提升吞吐量 | Ribbon、LoadBalancer、Istio |
| 链路追踪 | 分析请求路径,定位性能瓶颈 | SkyWalking、Zipkin、Jaeger |
| 监控告警 | 采集指标(QPS、延迟、错误率)并触发告警 | Prometheus + Grafana、Micrometer |
超时和重试
超时
1、在分布式系统中,基于压测的TP99(99th百分位响应时间)设置超时时间是一种科学且实践验证有效的方法。它既能避免因超时过短导致大量正常请求被误杀(影响用户体验),又能防止超时过长造成资源浪费或级联故障。
2、在分布式调用链路的不同层级(从前端到后端、从入口到执行端),超时时间逐层收敛(逐渐缩短),形成类似“漏斗”的结构。防止上层业务已失败,下层业务还在执行中。数据不一致问题。给用户感知异常,实际执行成功。
重试
1、基于固定时间间隔重试
2、随机重试
3、基于指数退让重试
4、基于条件的重试
5、设置重试次数,避免无限重试,并进行报警
6、 确保幂等性 :重试操作必须支持幂等(如通过唯一请求ID去重),避免重复操作导致数据错误(如重复扣款)。
1、用户操作同步接口重试,要看接口超时时间配置,防止重试还没结束超时了。
2、任务管理模块重试,一般用固定重试间隔重试,重试一定次数,死信。
3、异步任务重试,一般指数避让两次就不重试报警。 【失败基本分两种 1、偶尔异常如机器gc,网络抖动 2、业务校验失败,或者服务一直不可用,永远重试不成功】,遵循,临时异常可恢复、永久异常不浪费资源。
. 重试风暴(Retry Storm)
-
1、问题:重试导致下游服务负载激增,形成恶性循环。
-
解决:
- 限制最大重试次数(如最多3次),指数退让。
幂等:关注的是结果的最终一致性(多次执行结果一致),允许重复执行,但要求结果不变化。
根据业务主键(性别+年龄)先查出来,如果没有在插入。读接口天然幂等,
防重 关注的是请求的次数控制(减少或避免重复请求),目标是“不让重复请求发生”。
长期的还是要存到数据库里的
1. 唯一索引(Business Deduplication Key)
- 根据业务主键(如性别+年龄),生成一唯一字段索引,数据库表中为去重键添加唯一索引。
不是存在数据库永久的方案。仅一次会话一段时间有效
1. 唯一标识符(Unique ID) kafka
- 原理:为每个请求分配唯一标识符(如 UUID、业务流水号),服务端根据该 ID 判断请求是否已处理。
- 实现:
- 客户端生成唯一请求 ID,随请求发送给服务端。
- 服务端通过缓存(如 Redis)或数据库记录已处理的 ID,重复请求直接返回已有结果。
- 适用场景:HTTP 接口、支付交易、订单提交等。
- 示例:
CREATE TABLE request_log ( request_id VARCHAR(64) PRIMARY KEY, result TEXT, created_at TIMESTAMP );
2. Token 机制(Token Bucket)
- 原理:客户端在操作前获取一个一次性 Token,服务端校验 Token 有效性后执行操作并标记 Token 失效。
- 实现:
- 客户端发起请求获取 Token(如页面加载时生成)。
- 提交业务请求时携带 Token,服务端校验后删除或标记 Token 为已使用。
- 适用场景:防止表单重复提交、前端防重操作。
- 工具支持:Redis 存储 Token 并设置过期时间。
3. 分布式锁(Distributed Lock) 最常用,还能防并发。
- 原理:通过锁机制确保同一操作在分布式环境下仅执行一次。
- 实现:
- 使用 Redis 的
SET key value NX EX(RedLock 算法)或 ZooKeeper 临时节点。 - 获取锁后执行操作,完成后释放锁。
- 使用 Redis 的
- 适用场景:高并发场景(如秒杀、抢购)。
- 缺点:锁竞争可能影响性能。
4.状态机。
限流:
1. 固定窗口限流(Fixed Window)
- 原理:在固定时间窗口(如1秒、1分钟)内统计请求次数,超过阈值则拒绝请求。
- 示例:1分钟内允许100次请求,超限后拒绝后续请求,直到下一分钟重置计数。
- 优点:实现简单,内存消耗低。
- 缺点:窗口切换时可能产生突发流量(如窗口边界瞬间大量请求)。
2. 滑动窗口限流(Sliding Window)
- 原理:将时间窗口细分为更小的区间(如秒级),通过滑动窗口动态统计请求量,解决固定窗口的边界突发问题。
- 示例:1分钟滑动窗口,每10秒为一个子窗口,统计最近6个子窗口的请求总数。
- 优点:平滑流量,更精准控制请求速率。
- 缺点:实现复杂,计算开销较高。
3. 漏桶算法(Leaky Bucket)
- 原理:以恒定速率处理请求(类似水桶漏水),请求先进入桶中,若桶满则拒绝新请求。
- 示例:桶容量100,处理速率10次/秒,超出100的请求被丢弃。
- 优点:平滑流量,输出速率恒定。
- 缺点:无法应对突发流量,可能造成请求延迟。
4. 令牌桶算法(Token Bucket)
- 原理:系统以固定速率向桶中添加令牌,请求需获取令牌才能执行,无令牌时拒绝请求。
- 示例:令牌桶容量100,每秒添加10个令牌,突发流量最多允许100次请求。
- 优点:允许一定突发流量,灵活性高。
- 缺点:实现相对复杂。
| 算法 | 核心原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 固定窗口限流 | 按固定时间窗口(如1分钟)计数,超限拒绝。 | ✅ 实现简单 ✅ 内存消耗低 | ❌ 窗口边界突发流量难以控制 ❌ 精度较低 | 简单场景,如低频API限流 |
| 滑动窗口限流 | 将时间窗口细分为子窗口(如10秒),动态统计最近N个子窗口的总请求量。 | ✅ 平滑流量 ✅ 解决固定窗口的边界问题 | ❌ 实现复杂 ❌ 计算和存储开销较高 | 需要精准控制的场景,如高频API限流 |
| 漏桶算法 | 请求进入桶中,以恒定速率处理,桶满则拒绝。 | ✅ 强制流量平滑 ✅ 保护下游系统 | ❌ 无法应对突发流量 ❌ 可能引入延迟 | 严格流量整形场景,如音视频传输、老旧系统保护 |
| 令牌桶算法 | 系统生成令牌,请求需获取令牌才能执行,支持突发消耗预存令牌。 | ✅ 允许突发流量 ✅ 灵活性高 | ❌ 实现复杂 ❌ 突发后可能造成短暂过载 | 弹性限流场景,如秒杀接口、突发流量处理 |
选型建议
- 简单低频场景 → 固定窗口(如内部管理后台API)。
- 高频精准控制 → 滑动窗口(如支付接口限流)。
- 严格平滑流量 → 漏桶(如视频流控、老旧系统保护)。
- 弹性应对突发 → 令牌桶(如电商秒杀、社交平台热点事件)。
Sentinel
一、熔断(Circuit Breaking)
定义:当某个服务出现异常(如响应超时或错误率飙升),暂时中断对该服务的调用,避免故障扩散。
1. 熔断策略
Sentinel 支持三种熔断规则:
| 熔断类型 | 触发条件 | 适用场景 |
|---|---|---|
| 慢调用比例 | 请求响应时间 > 阈值(RT)且慢调用占比超过阈值(比例) | 接口性能波动(如数据库查询变慢) |
| 异常比例 | 单位时间内异常请求数占比超过阈值 | 下游服务不稳定(如频繁抛出异常) |
| 异常数 | 单位时间内异常请求数超过阈值 | 明确异常数量的场景(如连接超时) |
2. 熔断状态流转
-
Closed:正常状态,所有请求放行。
-
Open:触发熔断,拒绝所有请求。
-
Half-Open:经过熔断时长后,尝试放行部分请求探测恢复情况。
- 若探测成功 → 转为 Closed。
- 若探测失败 → 保持 Open。
二、降级(Degradation)
定义:在系统高负载或异常时,暂时关闭非核心功能或返回兜底结果,保障核心链路可用性。
1. 降级策略
| 降级方式 | 实现逻辑 | 适用场景 |
|---|---|---|
| 返回默认值 | 触发降级时返回预设的静态值(如 null、空列表)。 | 查询类接口(如商品详情) |
| 调用备用服务 | 降级时切换到备用服务(如缓存数据或简化逻辑)。 | 订单支付失败时切到本地队列 |
| 延迟处理 | 将请求暂存队列,同步改异步,待系统恢复后异步处理。 | 秒杀场景的订单排队 |
三、熔断与降级的核心区别
| 维度 | 熔断(Circuit Breaking) | 降级(Degradation) |
|---|---|---|
| 触发条件 | 基于异常比例、慢调用等统计指标 | 基于系统负载(如 CPU 使用率)或手动触发 |
| 保护目标 | 防止故障服务拖垮上游调用方 | 保障核心功能,牺牲非关键业务 |
| 实现层级 | 通常作用于服务间调用(RPC/HTTP) | 可作用于方法级别或功能模块 |
| 恢复机制 | 自动探测恢复(Half-Open 状态) | 需人工干预或系统负载降低后恢复 |
分布式系统(CAP理论)
C一致性
C(一致性)要求所有节点在同一时刻对数据的读写操作保持完全一致
共识算法(Consensus Algorithms)
共识算法通过多节点协作达成数据一致性,是强一致性的核心保障。典型算法包括:
- Raft****协议
-
- 机制 ****: 领导选举:在集群中选举出唯一领导者(Leader),负责处理客户端请求和日志同步。
日志复制:确保所有节点的日志(记录状态变更)保持一致。
安全性:在节点故障或网络分区时,仍能保证系统的一致性。
- **应用** ****:Etcd、TiKV等分布式数据库,Kubernetes配置管理。
- **优势** ****:逻辑简单,易于理解和实现。
- Paxos****协议
-
- 机制 ****:通过“准备-接受-学习”三阶段提案流程,确保多数节点接受同一值。
- 变体 ****:Multi-Paxos(支持多提案)、Fast Paxos(优化通信开销)。
- 应用 ****:Google Spanner、Chubby分布式锁服务。
- ZAB****协议( ZooKeeper Atomic Broadcast )
-
- 机制 ****:专为ZooKeeper设计,将事务广播与崩溃恢复分离,保证数据强一致。
- 应用 ****:ZooKeeper的分布式协调服务
主从复制,同步复制,共识算法半同步
分布式事务,数据一致性问题
数据版本一致性
可用性
CAP理论中的可用性(Availability)要求系统在任意时刻对请求都能返回响应(无论是否最新数据)。为实现高可用性,通常需牺牲强一致性(C)或容忍网络分区(P)
故障诊断,故障转移,主节点选取
服务治理中的可用性
异步复制与最终一致性
多活架构:多个数据中心独立处理请求,数据最终同步(如亚马逊的全球数据库)
- 主从复制:主节点处理写请求,异步同步到从节点(如MySQL半同步复制)。
读修复
核心思想:读取时检测数据不一致,自动修复副本。
夸分区部署与流量切换
DNS重定向:根据网络状态切换用户流量 负载均衡策略:动态剔除故障节点,仅路由至健康节点
CAP理论中的分区容错性(Partition Tolerance, P)要求系统在网络分区(节点间通信中断)时仍能继续提供服务。****
C分区容错性
CP架构(一致性优先)
核心思想 :在分区发生时,优先保证数据一致性,牺牲部分可用性。
实现方式 :
-
阻塞写入 :当检测到分区时,拒绝部分节点的写入请求,确保数据一致性。
-
- 示例 :ZooKeeper在Leader选举期间暂停非关键操作。
-
强同步机制 :通过共识算法(如Raft、Paxos)确保多数节点确认写入后再响应。
-
-
示例 :HBase在RegionServer故障时,通过ZooKeeper选举新Leader并同步数据。 适用场景 :
-
金融交易(如银行转账需强一致性)。
-
配置管理系统(如Consul的KV存储)。
-
AP架构(可用性优先)
核心思想 :在分区发生时,优先保证服务可用性,允许数据暂时不一致。
实现方式 :
-
异步复制 :写入本地节点后立即响应,异步传播到其他节点。
-
- 示例 :Cassandra的QUORUM策略,写入多数节点后返回成功。
-
最终一致性 :分区恢复后,通过日志同步或补偿机制修复数据差异。
混合架构(动态切换CP/AP)**
- 分级响应 :
-
- 轻度分区 :继续提供读写服务,但标记数据可能不一致(如Elasticsearch的read_uncommitted)。
- 重度分区 :降级为CP模式,暂停部分节点。
2、多活数据中心 :
- 各数据中心独立处理请求,分区恢复后通过异步复制同步差异。
数据修复
- 核心思想 :在分区解决后,通过机制修复数据差异,恢复全局一致性。
实现方式 : -
- 读修复(Read Repair) :
-
- 读取时检测副本不一致,自动修复(如Riak的后台修复任务)。
- 反熵协议(Anti-Entropy Protocol) :
-
- 定期校验副本差异并同步(如Cassandra的Merkle Tree校验)
- 人工干预