🚓 主要讲解流控模式 三种方式中的最后一种: 关联🚀
流量控制成为保障系统稳定性与可靠性的关键一环 🚒 。关联流控(Associated Flow Control)作为其中一项重要技术,能够巧妙地协调不同资源间的调用关系,避免因某个资源的过度使用而引发系统雪崩。本文将以数据库的读写操作为例,深入探讨关联流控的实战应用
1️⃣ 关联流控原理剖析
关联流控的核心思想:资源A的访问达到阈值时,自动限制关联资源B的访问,防止系统过载。 类比: 主干道(A)拥堵时,限制支路(B)车流,保障整体通行(系统稳定)。
关键点:
- 触发条件:资源A的访问频率超阈值。
- 关联动作:自动对资源B施加限流。
- 目的:通过优先级控制(保核心资源),维持系统整体稳定性
2️⃣ 数据库关联流控概要(读 vs 写)
核心问题💘
- 资源争用:读(
read_db
)与写(write_db
)共享底层存储,高并发写入时,大量读操作会加剧争用,导致:- 写操作延迟(数据持久化变慢)
- 读操作超时(连接池耗尽)
- 系统崩溃风险(CPU/IO 过载)
关联流控方案🚒
- 触发条件:
- 监控
write_db
的并发数/延迟/错误率,超过阈值时触发流控。
- 监控
- 调控策略:
- 限流读操作:降低
read_db
的并发配额(如从 1000 QPS 降至 300 QPS)。 - 动态降级:返回缓存数据或简化查询(避免全表扫描)。
- 限流读操作:降低
- 恢复机制:
- 当
write_db
负载回落,逐步恢复read_db
的正常流量。
- 当
关键
- 写优先:保障数据一致性(如订单支付、库存扣减)。
- 系统稳定:避免雪崩效应,维持服务可用性。
- 资源平衡:通过牺牲部分读性能(非核心路径),换取整体稳定性。
类比场景🚉
类似高速公路收费站:当货车(写操作)密集通行时,临时关闭部分轿车(读操作)通道,确保货车优先通过,避免整体拥堵。
3️⃣ 代码实战讲解
1、配置读写资源的关联限流规则
功能➡️ :通过 Sentinel 初始化数据库读写限流规则,实现:
- 写操作(
write_db
)限流:QPS ≤ 50 - 读操作(
read_db
)关联限流:当write_db
繁忙时,自动限制read_db
流量(基础 QPS=100)
实例代码
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
@Component
public class DbFlowRuleConfig {
@PostConstruct
public void initDbFlowRules() {
List<FlowRule> rules = new ArrayList<>();
// 写操作规则 - 基础限流
FlowRule writeRule = new FlowRule();
writeRule.setResource("write_db");
writeRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
writeRule.setCount(50); // 写操作QPS阈值50
rules.add(writeRule);
// 读操作规则 - 关联写操作
FlowRule readRule = new FlowRule();
readRule.setResource("read_db");
readRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
readRule.setCount(100); // 读操作基础QPS阈值100
readRule.setRefResource("write_db"); // 关联写操作资源
readRule.setStrategy(RuleConstant.STRATEGY_RELATE); // 关联策略
readRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
rules.add(readRule);
FlowRuleManager.loadRules(rules);
}
}
关键配置
参数 | 说明 |
---|---|
setRefResource |
关联资源(write_db 触发读限流) |
setStrategy(RELATE) |
启用关联流控策略 |
setCount |
基础QPS阈值(读100,写50) |
效果:当 write_db
QPS > 50,自动降低 read_db
的实际允许流量,优先保障写入。
2、数据库操作服务实现
功能🉑 :集成 Sentinel 注解实现数据库读写操作的限流与降级:
- 读操作:限流时返回提示,降级时返回缓存数据
- 写操作:限流时返回提示
代码事例
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;
@Service
public class DatabaseService {
// 读数据库操作
@SentinelResource(value = "read_db",
blockHandler = "readBlockHandler",
fallback = "readFallback")
public String readFromDb(String query) {
// 模拟数据库读操作
try {
Thread.sleep(10); // 模拟IO延迟
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "查询结果: " + query;
}
// 写数据库操作
@SentinelResource(value = "write_db",
blockHandler = "writeBlockHandler")
public String writeToDb(String data) {
// 模拟数据库写操作
try {
Thread.sleep(20); // 模拟IO延迟
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "写入成功: " + data;
}
// 读操作限流处理
public String readBlockHandler(String query, BlockException ex) {
return "系统繁忙,读操作被限流,请稍后再试";
}
// 写操作限流处理
public String writeBlockHandler(String data, BlockException ex) {
return "系统繁忙,写操作被限流,请稍后再试";
}
// 读操作降级处理
public String readFallback(String query, Throwable t) {
return "查询降级返回:缓存数据";
}
}
效果:
- 限流时:返回友好提示,避免用户长时间等待。
- 降级时:读操作返回缓存数据,保证基本可用性。
3、控制器层暴露接口
功能🉐 :负责将数据库服务的读写接口暴露给外部
代码事例
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/db")
public class DabaController {
@Autowired
private DatabaseService databaseService;
@GetMapping("/read")
public String read(@RequestParam String query) {
return databaseService.readFromDb(query);
}
@PostMapping("/write")
public String write(@RequestBody String data) {
return databaseService.writeToDb(data);
}
}