Skip to content

高并发系统设计实践

高并发系统架构设计

设计一个能够支持高并发的系统需要从架构、性能优化、容错机制和可伸缩性等多个维度进行综合考虑。本文将系统性地介绍构建高并发系统的核心技术和最佳实践。

分布式架构设计

将庞大的单体应用拆解为多个独立的微服务模块,通过分布式架构降低单点故障风险,提升系统的可伸缩性和整体性能。

mermaid
graph TB
    subgraph 单体架构
        Monolith[单体应用<br/>所有功能集中]
        MonolithDB[(单一数据库)]
        
        Monolith -->|所有操作| MonolithDB
    end
    
    subgraph 分布式微服务架构
        Gateway[API网关]
        
        subgraph 用户域
            UserService[用户服务]
            UserDB[(用户库)]
        end
        
        subgraph 商品域
            ProductService[商品服务]
            ProductDB[(商品库)]
            ProductCache[商品缓存]
        end
        
        subgraph 订单域
            OrderService[订单服务]
            OrderDB[(订单库)]
            OrderMQ[订单队列]
        end
        
        subgraph 支付域
            PaymentService[支付服务]
            PaymentDB[(支付库)]
        end
        
        Gateway --> UserService
        Gateway --> ProductService
        Gateway --> OrderService
        Gateway --> PaymentService
        
        UserService --> UserDB
        ProductService --> ProductDB
        ProductService --> ProductCache
        OrderService --> OrderDB
        OrderService --> OrderMQ
        PaymentService --> PaymentDB
    end
    
    style Monolith fill:#E57373,stroke:#C62828,stroke-width:2px,rx:10,ry:10
    style Gateway fill:#2196F3,stroke:#1565C0,stroke-width:2px,rx:10,ry:10
    style UserService fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,rx:10,ry:10
    style ProductService fill:#FF9800,stroke:#E65100,stroke-width:2px,rx:10,ry:10
    style OrderService fill:#9C27B0,stroke:#6A1B9A,stroke-width:2px,rx:10,ry:10
    style PaymentService fill:#00BCD4,stroke:#0097A7,stroke-width:2px,rx:10,ry:10

集群部署与负载均衡

通过集群化部署提升系统的吞吐量和可用性,结合负载均衡技术将请求均匀分配到各个服务实例。

java
@Configuration
public class LoadBalancerConfig {
    
    /**
     * 配置Ribbon负载均衡策略
     */
    @Bean
    public IRule ribbonRule() {
        // 使用加权响应时间规则:响应时间越短的实例获得更多请求
        return new WeightedResponseTimeRule();
    }
    
    /**
     * 订单服务调用,自动负载均衡
     */
    @Service
    public class OrderClientService {
        
        @Autowired
        private RestTemplate restTemplate;
        
        @LoadBalanced
        public OrderDTO createOrder(OrderRequest request) {
            // Ribbon自动选择可用的订单服务实例
            String url = "http://order-service/api/order/create";
            return restTemplate.postForObject(url, request, OrderDTO.class);
        }
    }
}

缓存架构优化

多级缓存体系

构建从客户端到数据库的多层缓存架构,最大化减少对数据库的访问压力。

mermaid
graph TB
    Client[客户端]
    CDN[CDN缓存<br/>静态资源]
    Nginx[Nginx缓存<br/>页面片段]
    LocalCache[本地缓存<br/>Caffeine/Guava]
    Redis[Redis分布式缓存<br/>热点数据]
    Database[(MySQL数据库)]
    
    Client -->|1. 请求| CDN
    CDN -.->|未命中| Nginx
    Nginx -.->|未命中| LocalCache
    LocalCache -.->|未命中| Redis
    Redis -.->|未命中| Database
    
    Database -->|回填| Redis
    Redis -->|回填| LocalCache
    LocalCache -->|回填| Nginx
    
    style CDN fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,rx:10,ry:10
    style Nginx fill:#2196F3,stroke:#1565C0,stroke-width:2px,rx:10,ry:10
    style LocalCache fill:#FF9800,stroke:#E65100,stroke-width:2px,rx:10,ry:10
    style Redis fill:#E57373,stroke:#C62828,stroke-width:2px,rx:10,ry:10
    style Database fill:#9C27B0,stroke:#6A1B9A,stroke-width:2px,rx:10,ry:10

缓存实践案例

java
@Service
public class ProductCacheService {
    
    @Autowired
    private RedisTemplate<String, ProductDTO> redisTemplate;
    
    @Autowired
    private ProductRepository productRepository;
    
    // 本地缓存:Caffeine
    private final LoadingCache<Long, ProductDTO> localCache = Caffeine.newBuilder()
        .maximumSize(10000)  // 最多缓存1万个商品
        .expireAfterWrite(5, TimeUnit.MINUTES)  // 5分钟过期
        .recordStats()  // 记录统计信息
        .build(this::loadFromRedis);
    
    /**
     * 查询商品详情,三级缓存
     */
    public ProductDTO getProduct(Long productId) {
        try {
            // L1缓存:本地缓存
            return localCache.get(productId);
        } catch (Exception e) {
            logger.error("缓存查询失败,productId: {}", productId, e);
            // 降级:直接查数据库
            return productRepository.findById(productId).orElse(null);
        }
    }
    
    /**
     * 从Redis加载(L2缓存)
     */
    private ProductDTO loadFromRedis(Long productId) {
        String redisKey = "product:detail:" + productId;
        ProductDTO product = redisTemplate.opsForValue().get(redisKey);
        
        if (product == null) {
            // L3缓存未命中:查询数据库
            product = productRepository.findById(productId).orElse(null);
            if (product != null) {
                // 回填Redis缓存,设置随机过期时间避免雪崩
                int randomExpire = 3600 + new Random().nextInt(600);
                redisTemplate.opsForValue().set(redisKey, product, 
                    randomExpire, TimeUnit.SECONDS);
            }
        }
        
        return product;
    }
    
    /**
     * 缓存预热:提前加载热点商品
     */
    public void warmupHotProducts(List<Long> hotProductIds) {
        logger.info("开始预热{}个热点商品", hotProductIds.size());
        
        hotProductIds.forEach(productId -> {
            ProductDTO product = productRepository.findById(productId).orElse(null);
            if (product != null) {
                // 写入Redis
                String redisKey = "product:detail:" + productId;
                redisTemplate.opsForValue().set(redisKey, product, 1, TimeUnit.HOURS);
                
                // 写入本地缓存
                localCache.put(productId, product);
            }
        });
        
        logger.info("缓存预热完成");
    }
}

异步处理架构

消息队列削峰填谷

通过消息队列将同步操作转换为异步处理,降低请求响应时间,提升系统吞吐量。

mermaid
graph TB
    subgraph 同步处理模式
        SyncRequest[用户请求]
        SyncProcess[同步处理<br/>所有业务逻辑]
        SyncDB[(数据库)]
        SyncResponse[等待响应]
        
        SyncRequest --> SyncProcess
        SyncProcess --> SyncDB
        SyncDB --> SyncProcess
        SyncProcess --> SyncResponse
    end
    
    subgraph 异步处理模式
        AsyncRequest[用户请求]
        QuickResponse[快速响应]
        MQ[消息队列<br/>RabbitMQ/Kafka]
        AsyncWorker[异步消费者]
        AsyncDB[(数据库)]
        Notify[异步通知]
        
        AsyncRequest -->|核心操作| QuickResponse
        AsyncRequest -->|非核心操作| MQ
        MQ --> AsyncWorker
        AsyncWorker --> AsyncDB
        AsyncWorker --> Notify
    end
    
    style SyncProcess fill:#E57373,stroke:#C62828,stroke-width:2px,rx:10,ry:10
    style QuickResponse fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,rx:10,ry:10
    style MQ fill:#2196F3,stroke:#1565C0,stroke-width:2px,rx:10,ry:10

异步订单处理

java
@Service
public class AsyncOrderService {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Autowired
    private OrderRepository orderRepository;
    
    /**
     * 创建订单:异步处理非核心流程
     */
    @Transactional
    public OrderResult createOrder(OrderRequest request) {
        // 核心流程:同步执行
        // 1. 扣减库存
        boolean stockReduced = inventoryService.reduceStock(
            request.getProductId(), 
            request.getQuantity()
        );
        
        if (!stockReduced) {
            return OrderResult.fail("库存不足");
        }
        
        // 2. 创建订单记录
        OrderEntity order = OrderEntity.builder()
            .orderNo(generateOrderNo())
            .userId(request.getUserId())
            .productId(request.getProductId())
            .quantity(request.getQuantity())
            .status(OrderStatus.CREATED)
            .createTime(new Date())
            .build();
        
        orderRepository.save(order);
        
        // 非核心流程:异步处理
        // 3. 发送订单消息到MQ
        OrderMessage message = OrderMessage.builder()
            .orderNo(order.getOrderNo())
            .userId(request.getUserId())
            .productId(request.getProductId())
            .build();
        
        rabbitTemplate.convertAndSend("order.exchange", "order.created", message);
        
        // 快速响应用户
        return OrderResult.success(order.getOrderNo());
    }
    
    /**
     * 异步消费订单消息
     */
    @RabbitListener(queues = "order.process.queue")
    public void processOrderAsync(OrderMessage message) {
        try {
            // 发送订单确认邮件
            emailService.sendOrderConfirmation(message.getUserId(), message.getOrderNo());
            
            // 更新用户积分
            pointsService.addPoints(message.getUserId(), 10, "下单奖励");
            
            // 更新销量统计
            statisticsService.incrementSales(message.getProductId(), 1);
            
            logger.info("订单异步处理完成,orderNo: {}", message.getOrderNo());
        } catch (Exception e) {
            logger.error("订单异步处理失败,orderNo: {}", message.getOrderNo(), e);
            // 失败重试或记录到死信队列
        }
    }
}

数据库优化策略

读写分离架构

通过主从复制实现读写分离,主库负责写操作,从库负责读操作,提升数据库整体并发能力。

mermaid
graph TB
    App[应用服务]
    
    subgraph 数据库集群
        Master[(主库<br/>MySQL Master)]
        Slave1[(从库1<br/>MySQL Slave)]
        Slave2[(从库2<br/>MySQL Slave)]
        Slave3[(从库3<br/>MySQL Slave)]
        
        Master -.->|binlog同步| Slave1
        Master -.->|binlog同步| Slave2
        Master -.->|binlog同步| Slave3
    end
    
    App -->|写操作| Master
    App -->|读操作| Slave1
    App -->|读操作| Slave2
    App -->|读操作| Slave3
    
    style Master fill:#E57373,stroke:#C62828,stroke-width:2px,rx:10,ry:10
    style Slave1 fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,rx:10,ry:10
    style Slave2 fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,rx:10,ry:10
    style Slave3 fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,rx:10,ry:10
java
@Configuration
public class DataSourceConfig {
    
    /**
     * 主数据源
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    /**
     * 从数据源
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    /**
     * 动态数据源路由
     */
    @Bean
    public DataSource dynamicDataSource() {
        DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
        
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterDataSource());
        targetDataSources.put("slave", slaveDataSource());
        
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(masterDataSource());
        
        return dataSource;
    }
}

/**
 * 读写分离注解
 */
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    /**
     * 写操作:路由到主库
     */
    @Master
    @Transactional
    public void createUser(UserDTO userDTO) {
        UserEntity user = new UserEntity();
        BeanUtils.copyProperties(userDTO, user);
        userRepository.save(user);
    }
    
    /**
     * 读操作:路由到从库
     */
    @Slave
    @Transactional(readOnly = true)
    public UserDTO getUserById(Long userId) {
        return userRepository.findById(userId)
            .map(this::convertToDTO)
            .orElse(null);
    }
}

分库分表

当单表数据量超过千万级别时,通过分库分表水平拆分数据,提升查询性能。

java
@Configuration
public class ShardingConfig {
    
    /**
     * 配置订单表分片策略
     */
    @Bean
    public DataSource shardingDataSource() throws SQLException {
        // 配置真实数据源
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        dataSourceMap.put("ds0", createDataSource("order_db_0"));
        dataSourceMap.put("ds1", createDataSource("order_db_1"));
        
        // 配置订单表规则
        ShardingTableRuleConfiguration orderTableRule = new ShardingTableRuleConfiguration(
            "t_order",
            "ds${0..1}.t_order_${0..3}"
        );
        
        // 分库策略:根据user_id取模
        orderTableRule.setDatabaseShardingStrategyConfig(
            new InlineShardingStrategyConfiguration("user_id", "ds${user_id % 2}")
        );
        
        // 分表策略:根据order_id取模
        orderTableRule.setTableShardingStrategyConfig(
            new InlineShardingStrategyConfiguration("order_id", "t_order_${order_id % 4}")
        );
        
        // 配置分片规则
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRule);
        
        return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new Properties());
    }
    
    private DataSource createDataSource(String database) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/" + database);
        config.setUsername("root");
        config.setPassword("password");
        return new HikariDataSource(config);
    }
}

性能优化实践

减小锁粒度

通过细化锁的范围和使用无锁数据结构,降低锁竞争,提升并发性能。

java
public class InventoryService {
    
    // 错误示例:粗粒度锁
    private final Object globalLock = new Object();
    private final Map<Long, Integer> stockMap = new HashMap<>();
    
    public boolean reduceStockBad(Long productId, int quantity) {
        synchronized (globalLock) {  // 所有商品共用一把锁,并发度低
            Integer stock = stockMap.get(productId);
            if (stock != null && stock >= quantity) {
                stockMap.put(productId, stock - quantity);
                return true;
            }
            return false;
        }
    }
    
    // 优化示例:细粒度锁
    private final ConcurrentHashMap<Long, AtomicInteger> stockMapOptimized = 
        new ConcurrentHashMap<>();
    
    public boolean reduceStockGood(Long productId, int quantity) {
        AtomicInteger stock = stockMapOptimized.get(productId);
        if (stock == null) {
            return false;
        }
        
        // 使用CAS无锁操作
        while (true) {
            int currentStock = stock.get();
            if (currentStock < quantity) {
                return false;
            }
            
            if (stock.compareAndSet(currentStock, currentStock - quantity)) {
                return true;
            }
        }
    }
}

避免长事务

长事务会持有数据库锁,阻塞其他请求,严重影响并发性能。

java
@Service
public class OrderOptimizedService {
    
    /**
     * 错误示例:长事务
     */
    @Transactional
    public void createOrderBad(OrderRequest request) {
        // 查询商品详情(可能很慢)
        ProductDTO product = productRpcClient.getProduct(request.getProductId());
        
        // 复杂的业务计算(耗时操作)
        BigDecimal totalAmount = calculateTotalAmount(product, request);
        
        // 调用第三方接口(网络延迟)
        boolean limitCheck = riskService.checkUserLimit(request.getUserId());
        
        // 保存订单(整个事务期间持有锁)
        orderRepository.save(buildOrder(request, totalAmount));
    }
    
    /**
     * 优化示例:缩短事务范围
     */
    public void createOrderGood(OrderRequest request) {
        // 非事务操作:提前执行
        ProductDTO product = productRpcClient.getProduct(request.getProductId());
        BigDecimal totalAmount = calculateTotalAmount(product, request);
        boolean limitCheck = riskService.checkUserLimit(request.getUserId());
        
        if (!limitCheck) {
            throw new BusinessException("用户额度不足");
        }
        
        // 仅在必要时开启事务
        saveOrderInTransaction(buildOrder(request, totalAmount));
    }
    
    @Transactional
    private void saveOrderInTransaction(OrderEntity order) {
        // 事务范围最小化:仅包含数据库写操作
        orderRepository.save(order);
    }
}

容错与监控

限流熔断降级

综合运用限流、熔断、降级技术,构建多层次的容错保护体系。

java
@Service
public class RobustPaymentService {
    
    @Autowired
    private ThirdPartyPaymentClient paymentClient;
    
    private final CircuitBreaker circuitBreaker;
    private final RateLimiter rateLimiter;
    
    public RobustPaymentService() {
        // 配置熔断器
        this.circuitBreaker = CircuitBreaker.of("payment", CircuitBreakerConfig.custom()
            .failureRateThreshold(50)  // 失败率50%触发熔断
            .waitDurationInOpenState(Duration.ofSeconds(60))
            .build());
        
        // 配置限流器:每秒100个支付请求
        this.rateLimiter = RateLimiter.create(100.0);
    }
    
    /**
     * 支付处理:限流+熔断+降级
     */
    public PaymentResult processPayment(PaymentRequest request) {
        // 第一层:限流保护
        if (!rateLimiter.tryAcquire(1, 500, TimeUnit.MILLISECONDS)) {
            logger.warn("支付请求限流,userId: {}", request.getUserId());
            return PaymentResult.fail("支付服务繁忙,请稍后重试");
        }
        
        // 第二层:熔断保护
        try {
            return circuitBreaker.executeSupplier(() -> {
                return paymentClient.pay(request);
            });
        } catch (CallNotPermittedException e) {
            // 熔断器开启,执行降级逻辑
            logger.error("支付服务熔断,使用降级方案,userId: {}", request.getUserId());
            return executeFallback(request);
        } catch (Exception e) {
            logger.error("支付失败,userId: {}", request.getUserId(), e);
            return PaymentResult.fail("支付失败,请重试");
        }
    }
    
    /**
     * 降级方案:异步支付
     */
    private PaymentResult executeFallback(PaymentRequest request) {
        // 将支付请求放入延迟队列,稍后重试
        paymentDelayQueue.offer(request);
        
        return PaymentResult.builder()
            .success(false)
            .message("支付处理中,请稍后查看支付结果")
            .needRetry(true)
            .build();
    }
}

实时监控告警

java
@Component
public class SystemHealthMonitor {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    /**
     * 监控接口响应时间
     */
    public void monitorApiLatency(String apiName, long latencyMs) {
        Timer.builder("api.latency")
            .tag("api", apiName)
            .register(meterRegistry)
            .record(latencyMs, TimeUnit.MILLISECONDS);
        
        // 响应时间超过阈值告警
        if (latencyMs > 1000) {
            alertService.sendAlert("接口响应缓慢", 
                String.format("接口%s响应时间%dms,超过1秒", apiName, latencyMs));
        }
    }
    
    /**
     * 监控数据库连接池
     */
    @Scheduled(fixedRate = 10000)
    public void monitorConnectionPool() {
        HikariDataSource dataSource = (HikariDataSource) this.dataSource;
        HikariPoolMXBean poolMXBean = dataSource.getHikariPoolMXBean();
        
        int activeConnections = poolMXBean.getActiveConnections();
        int totalConnections = poolMXBean.getTotalConnections();
        double usage = (double) activeConnections / totalConnections;
        
        // 记录指标
        meterRegistry.gauge("db.connection.active", activeConnections);
        meterRegistry.gauge("db.connection.usage", usage);
        
        // 连接池使用率超过80%告警
        if (usage > 0.8) {
            alertService.sendAlert("数据库连接池告警", 
                String.format("连接池使用率%.1f%%,建议扩容", usage * 100));
        }
    }
}

高并发系统设计清单

构建高并发系统需要综合运用以下技术和策略:

架构层面

  • 分布式架构: 服务拆分、微服务治理
  • 集群部署: 负载均衡、水平扩展
  • 异地多活: 跨地域部署、容灾备份

性能优化

  • 多级缓存: CDN、本地缓存、分布式缓存
  • 异步处理: 消息队列、事件驱动
  • 代码优化: 减小锁粒度、避免长事务、优化算法

数据库优化

  • 索引优化: 合理设计索引、覆盖索引
  • 读写分离: 主从复制、读写路由
  • 分库分表: 水平拆分、垂直拆分

容错保障

  • 限流: 单机限流、集群限流、自适应限流
  • 熔断: 快速失败、自动恢复
  • 降级: 功能降级、读写降级

监控运维

  • 实时监控: 性能指标、业务指标
  • 告警机制: 阈值告警、智能告警
  • 压力测试: 全链路压测、容量评估

通过系统性地应用这些技术和最佳实践,可以构建一个高性能、高可用、可伸缩的高并发系统,满足业务快速增长的需求。

更新: 2025-12-04 17:41:37
原文: https://www.yuque.com/u22210564/zoxfmt/doc-04-04

Java 后端面试知识库