系统设计:高并发策略与缓存设计

1. 高并发核心策略

核心目标:在流量洪峰下保障系统稳定性、可用性和响应速度。


(1) 限流(Rate Limiting)

作用 :控制请求速率,防止系统过载。
常用算法

  • 令牌桶算法(Token Bucket)

    • 原理:以固定速率向桶中添加令牌,请求需获取令牌才能执行(允许突发流量)。
    • 实现 :Guava RateLimiter
java 复制代码
RateLimiter limiter = RateLimiter.create(100); // 每秒100个令牌  
if (limiter.tryAcquire()) {  
    // 处理请求  
} else {  
    // 拒绝或降级  
}
  • 漏桶算法(Leaky Bucket)

    • 原理:请求以恒定速率流出(平滑流量,限制突发)。
    • 对比令牌桶:漏桶强制固定速率,令牌桶允许突发但限制平均速率。

场景选择

  • 令牌桶:秒杀场景(允许短时突发)。
  • 漏桶:API网关限流(严格限制QPS)。

(2) 降级(Degradation)

一、熔断机制核心目标

在分布式系统中,熔断(Circuit Breaker) 用于解决以下问题:

  • 服务雪崩:防止因单个服务故障引发连锁反应。
  • 资源保护:快速失败避免资源耗尽(如线程池、数据库连接)。
  • 故障隔离:将不稳定服务与系统其他部分隔离。

二、Hystrix(Netflix 开源)

1. 核心特性
特性 说明
熔断策略 基于错误率(默认 50% 错误请求触发熔断)
资源隔离 线程池隔离(默认)或信号量隔离
降级处理 通过 @HystrixCommand(fallbackMethod = "methodName") 定义降级方法
监控集成 支持 Hystrix Dashboard 实时监控熔断状态
维护状态 2018 年进入维护模式,不再主动更新
2. 工作流程
java 复制代码
graph TD
  A[服务调用] --> B{Hystrix 拦截}
  B -->|正常请求| C[执行目标方法]
  B -->|熔断开启| D[直接执行降级逻辑]
  C --> E{执行结果}
  E -->|成功| F[返回结果]
  E -->|失败| G[统计错误率]
  G --> H{达到阈值?}
  H -->|是| I[开启熔断]
  H -->|否| J[保持关闭]
  I --> K[熔断时间窗口]
  K --> L{时间结束?}
  L -->|是| M[半开状态尝试恢复]
  M --> N{请求成功?}
  N -->|是| O[关闭熔断]
  N -->|否| I
3. 代码示例
java 复制代码
@Service
public class UserService {
    @HystrixCommand(
        fallbackMethod = "getUserFallback",
        commandProperties = {
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"), // 触发熔断的最小请求数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000") // 熔断持续时间
        }
    )
    public User getUserById(Long id) {
        // 调用远程服务
        return userClient.getUser(id);
    }

    // 降级方法(参数需与原方法一致)
    private User getUserFallback(Long id) {
        return new User("fallback_user");
    }
}

三、Sentinel(阿里巴巴开源)

1. 核心特性
特性 说明
熔断策略 支持慢调用比例、异常比例、异常数三种熔断策略
流量控制 支持 QPS/线程数限流、关联资源限流、链路限流
系统保护 自适应系统负载保护(CPU、平均 RT、线程数等)
动态规则 支持通过控制台/Nacos/ZooKeeper 动态配置规则
生态集成 深度集成 Spring Cloud Alibaba、Dubbo、gRPC 等
2. 熔断规则配置

通过 sentinel-dashboard 控制台或代码配置:

java 复制代码
// 代码配置示例
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule("resourceName")
    .setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO) // 熔断策略
    .setCount(0.7) // 阈值(异常比例 70%)
    .setTimeWindow(10) // 熔断时间窗口(秒)
    .setMinRequestAmount(10); // 最小请求数
rules.add(rule);
DegradeRuleManager.loadRules(rules);
3. 工作流程
java 复制代码
graph TD
  A[请求进入] --> B{Sentinel 资源检查}
  B -->|通过| C[执行目标逻辑]
  B -->|拒绝| D[执行降级逻辑]
  C --> E{执行结果}
  E -->|正常| F[返回结果]
  E -->|异常| G[统计指标]
  G --> H{达到熔断条件?}
  H -->|是| I[开启熔断]
  H -->|否| J[保持关闭]
  I --> K[熔断时间窗口]
  K --> L{时间结束?}
  L -->|是| M[进入半开状态]
  M --> N{试探请求成功?}
  N -->|是| O[关闭熔断]
  N -->|否| I

四、Hystrix vs Sentinel 对比

对比维度 Hystrix Sentinel
设计目标 服务容错 流量控制 + 熔断降级 + 系统保护
资源隔离 线程池隔离(资源消耗较大) 基于计数器(轻量级)
规则配置 静态配置(代码/配置文件) 动态配置(控制台/配置中心)
监控能力 需额外集成 Hystrix Dashboard 自带实时监控与控制台
扩展性 扩展性有限 支持 SPI 扩展(规则管理、适配器等)
社区活跃度 已停止维护 持续更新

五、选型建议

  1. 新项目推荐 Sentinel
    • 更丰富的流量控制手段
    • 动态规则配置能力
    • 对云原生支持更友好
  2. 存量 Hystrix 项目
    • 可逐步迁移至 Resilience4j 或 Sentinel
    • 避免继续增加 Hystrix 依赖

六、注意事项

  1. Hystrix 线程池开销
    • 线程池隔离会带来额外上下文切换成本,需合理设置线程数。
  2. Sentinel 规则持久化
    • 默认规则存储在内存中,重启失效,需集成 Nacos 等实现持久化。
  3. 熔断恢复策略
    • Sentinel 支持更灵活的半开状态探测机制。
  4. 异常处理
    • Hystrix 需显式定义 fallback,Sentinel 支持全局默认降级逻辑。

总结

核心工具 优势场景 典型应用
Hystrix 简单熔断降级、Spring Cloud Netflix 集成 老旧微服务项目维护
Sentinel 复杂流量控制、动态规则管理、高扩展性 新分布式系统、云原生环境、高并发场景

(3) 异步化(MQ削峰填谷)

作用 :通过消息队列缓冲瞬时流量,异步处理非实时任务。
实现流程

  1. 流量洪峰:请求写入MQ(如Kafka、RocketMQ)。
  2. 异步消费:下游服务按处理能力拉取消息,避免压垮数据库。
  3. 最终一致:通过重试机制保障业务逻辑完成。

典型场景

  • 订单支付成功后的通知、日志记录。
  • 大数据量批量处理(如Excel导入)。

2. 缓存设计


(1) 缓存一致性:Cache Aside Pattern

核心流程

  1. 读操作

    • 先查缓存,命中则返回。
    • 未命中则查数据库,写入缓存后返回。
  2. 写操作

    • 先更新数据库。
    • 删除缓存(而非更新,避免并发写导致脏数据)。

极端情况处理

  • 缓存删除失败:通过重试队列或订阅数据库Binlog(如Canal)补偿删除。
  • 读请求在写操作删除缓存后,旧数据回填
    • 方案:延迟双删(写后延迟再删一次缓存)。

(2) 热点数据优化

问题 :高频访问的数据导致缓存击穿或分布式缓存压力过大。
解决方案

  • 本地缓存(如Caffeine)

    • 优势:微秒级访问速度,减少Redis网络开销。
    • 配置示例
java 复制代码
Cache<String, Object> cache = Caffeine.newBuilder()  
    .maximumSize(10_000)  
    .expireAfterWrite(5, TimeUnit.MINUTES)  
    .build();
  • 多级缓存架构

    1. 本地缓存(Caffeine) → 2. 分布式缓存(Redis) → 3. 数据库
      降级策略
    • 本地缓存失效后,从Redis获取并回填。
    • Redis压力过大时,本地缓存延长TTL兜底。

热点发现

  • 实时监控(如Redis热点Key分析)。
  • 静态预测(如大促前提前加载商品数据)。

3. 总结

  • 高并发三板斧:限流控入口、降级保核心、异步化削峰。
  • 缓存设计核心
    • 一致性靠"删除缓存"而非"更新缓存"。
    • 热点数据用多级缓存降低延迟,同时避免缓存雪崩(随机过期时间)。
  • 工具选择
    • 中小规模:Guava + Redis + Hystrix。
    • 大规模:Sentinel + RocketMQ + Caffeine。

通过合理组合策略,可构建支撑百万QPS的高并发系统!

相关推荐
小马爱打代码8 分钟前
Kafka - 消息零丢失实战
分布式·kafka
长河10 分钟前
Kafka系列教程 - Kafka 运维 -8
运维·分布式·kafka
张张张31215 分钟前
4.2学习总结 Java:list系列集合
java·学习
KATA~18 分钟前
解决MyBatis-Plus枚举映射错误:No enum constant问题
java·数据库·mybatis
xyliiiiiL34 分钟前
一文总结常见项目排查
java·服务器·数据库
shaoing35 分钟前
MySQL 错误 报错:Table ‘performance_schema.session_variables’ Doesn’t Exist
java·开发语言·数据库
腥臭腐朽的日子熠熠生辉1 小时前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian1 小时前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之2 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码2 小时前
Spring Task 定时任务
java·前端·spring