高并发系统设计:应对海量请求的技术实践
在互联网时代,高并发是每个系统都必须面对的挑战。无论是电商平台的秒杀活动、社交平台的热搜事件,还是金融系统的交易高峰,都可能产生海量的并发请求。一个设计良好的高并发系统不仅能够应对这些流量高峰,还能保证系统的稳定性和用户体验。本文将从架构设计、关键技术、实践案例等多个维度,全面介绍高并发系统设计的核心技术和最佳实践。
一、高并发系统架构概述
高并发系统的架构设计是一个系统工程,需要从多个层面综合考虑。从整体架构来看,通常采用分层架构,将系统分为接入层、应用层、服务层、数据层等,每层负责不同的职责。通过水平扩展各层节点,可以不断增强系统的处理能力。同时,使用异步消息队列实现削峰填谷,避免瞬时流量对后端系统造成冲击。
高并发架构的核心目标是:提高系统的吞吐量(Throughput),即单位时间内处理的请求数量;降低系统的响应延迟(Latency),即请求到响应的时间;保证系统的高可用(Availability),即系统正常运行的时间比例。这三个目标往往需要权衡,不可能同时达到最优。
┌─────────────────────────────────────────────────────────────┐ │ 高并发系统架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 用户A │ │ 用户B │ │ 用户C │ ... │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ └──────────────┼──────────────┘ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ 负载均衡层 │ ◄── Nginx / HAProxy │ │ │ (接入网关/路由) │ │ │ └────────┬─────────┘ │ │ │ │ │ ┌──────────────┼──────────────┐ │ │ ▼ ▼ ▼ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 应用节点1 │ │ 应用节点2 │ │ 应用节点3 │ ... │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ └──────────────┼──────────────┘ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ 服务层 │ ◄── 业务逻辑 │ │ │ (微服务/SOA) │ │ │ └────────┬─────────┘ │ │ │ │ │ ┌──────────────┼──────────────┐ │ │ ▼ ▼ ▼ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 缓存集群 │ │ 消息队列 │ │ 服务注册 │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ └──────────────┼──────────────┘ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ 数据层 │ │ │ │ (主从/分库分表) │ │ │ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘二、负载均衡技术详解
负载均衡是实现高并发的关键技术之一,它将请求分发到多个服务器上,避免单点过载。负载均衡可以在多个层面实现:DNS负载均衡通过域名解析将请求分发到不同IP;网络层负载均衡如LVS工作在TCP/IP协议栈;应用层负载均衡如Nginx可以基于请求内容进行路由选择。
负载均衡的算法决定了请求如何分配到各个服务器。常见的算法包括:轮询(Round Robin)简单均匀,但不考虑服务器实际负载;加权轮询(Weighted Round Robin)根据服务器性能分配权重;最少连接(Least Connections)将请求发送到当前连接数最少的服务器;IP哈希(IP Hash)同一IP的请求发送到同一服务器,保证会话粘性。
import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; // 负载均衡器实现 public class LoadBalancer { private final List<Server> servers; private final LoadBalancingStrategy strategy; public LoadBalancer(List<Server> servers, LoadBalancingStrategy strategy) { this.servers = new ArrayList<>(servers); this.strategy = strategy; } public Server select() { return strategy.select(servers); } } // 负载均衡策略接口 interface LoadBalancingStrategy { Server select(List<Server> servers); } // 轮询策略 public class RoundRobinStrategy implements LoadBalancingStrategy { private final AtomicInteger cursor = new AtomicInteger(0); @Override public Server select(List<Server> servers) { if (servers.isEmpty()) { throw new NoSuchElementException("No available servers"); } int index = cursor.getAndIncrement() % servers.size(); return servers.get(index); } } // 加权轮询策略 public class WeightedRoundRobinStrategy implements LoadBalancingStrategy { private final Map<Server, Integer> weights = new HashMap<>(); private final AtomicLong sequence = new AtomicLong(0); public WeightedRoundRobinStrategy(Map<Server, Integer> weights) { this.weights.putAll(weights); } @Override public Server select(List<Server> servers) { if (servers.isEmpty()) { throw new NoSuchElementException("No available servers"); } long currentSequence = sequence.getAndIncrement(); // 找出权重最大的服务器 Server selectedServer = servers.get(0); int maxWeight = weights.getOrDefault(selectedServer, 1); for (Server server : servers) { int weight = weights.getOrDefault(server, 1); if (weight > maxWeight) { maxWeight = weight; selectedServer = server; } } return selectedServer; } } // 最少连接策略 public class LeastConnectionsStrategy implements LoadBalancingStrategy { private final Map<Server, AtomicInteger> connectionCounts = new ConcurrentHashMap<>(); @Override public Server select(List<Server> servers) { if (servers.isEmpty()) { throw new NoSuchElementException("No available servers"); } Server leastConnections = null; int minConnections = Integer.MAX_VALUE; for (Server server : servers) { if (!server.isHealthy()) { continue; } int connections = connectionCounts .computeIfAbsent(server, k -> new AtomicInteger(0)) .get(); if (connections < minConnections) { minConnections = connections; leastConnections = server; } } return leastConnections != null ? leastConnections : servers.get(0); } public void incrementConnections(Server server) { connectionCounts.computeIfAbsent(server, k -> new AtomicInteger(0)) .incrementAndGet(); } public void decrementConnections(Server server) { AtomicInteger count = connectionCounts.get(server); if (count != null) { count.decrementAndGet(); } } } // IP哈希策略 public class IpHashStrategy implements LoadBalancingStrategy { @Override public Server select(List<Server> servers) { if (servers.isEmpty()) { throw new NoSuchElementException("No available servers"); } // 使用请求的IP地址进行哈希 String clientIp = getClientIpAddress(); int hash = Math.abs(clientIp.hashCode()); int index = hash % servers.size(); return servers.get(index); } private String getClientIpAddress() { // 从请求上下文获取IP return "192.168.1.100"; } }三、缓存架构与策略
缓存是提升系统性能的关键技术,合理使用缓存可以大幅减少数据库压力,加快响应速度。缓存架构设计需要考虑多个方面:缓存层的位置(客户端缓存、CDN、网关缓存、应用缓存、分布式缓存等);缓存的数据结构(字符串、对象、列表等);缓存的过期策略(TTL、定时过期、主动刷新等);缓存的一致性问题。
缓存策略的选择直接影响系统的性能和一致性。Cache-Aside模式是最常用的策略,应用程序先查询缓存,缓存未命中时查询数据库并更新缓存;Read-Through模式下,缓存负责从数据库加载数据;Write-Through模式下,写操作同时更新缓存和数据库;Write-Behind模式则先写缓存,后台异步更新数据库。
import java.util.*; import java.util.concurrent.*; import java.util.function.*; public class CacheManager<K, V> { private final Map<K, CacheEntry<V>> cache = new ConcurrentHashMap<>(); private final ScheduledExecutorService cleaner; private final long defaultTtlMs; public CacheManager(long defaultTtlMs) { this.defaultTtlMs = defaultTtlMs; this.cleaner = Executors.newSingleThreadScheduledExecutor(); // 定期清理过期缓存 cleaner.scheduleAtFixedRate( this::cleanExpiredEntries, 1, 1, TimeUnit.MINUTES ); } public V get(K key) { CacheEntry<V> entry = cache.get(key); if (entry == null) { return null; } if (entry.isExpired()) { cache.remove(key); return null; } return entry.getValue(); } public void put(K key, V value) { put(key, value, defaultTtlMs); } public void put(K key, V value, long ttlMs) { cache.put(key, new CacheEntry<>(value, System.currentTimeMillis() + ttlMs)); } public V getOrLoad(K key, Supplier<V> loader) { V value = get(key); if (value == null) { value = loader.get(); if (value != null) { put(key, value); } } return value; } public void remove(K key) { cache.remove(key); } public void clear() { cache.clear(); } private void cleanExpiredEntries() { long now = System.currentTimeMillis(); cache.entrySet().removeIf(entry -> entry.getValue().isExpired(now)); } private static class CacheEntry<V> { private final V value; private final long expireTime; CacheEntry(V value, long expireTime) { this.value = value; this.expireTime = expireTime; } V getValue() { return value; } boolean isExpired() { return isExpired(System.currentTimeMillis()); } boolean isExpired(long now) { return now > expireTime; } } } // 多级缓存实现 @Service public class MultiLevelCacheService { @Autowired private L1Cache localCache; // 本地缓存(Caffeine/Guava) @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private ProductRepository productRepository; private static final String REDIS_KEY_PREFIX = "product:"; private static final long LOCAL_CACHE_TTL = 60; // 1分钟 private static final long REDIS_CACHE_TTL = 300; // 5分钟 public Product getProduct(Long productId) { String redisKey = REDIS_KEY_PREFIX + productId; // 1. 先查本地缓存 Product product = localCache.getIfPresent(productId); if (product != null) { return product; } // 2. 再查Redis缓存 product = (Product) redisTemplate.opsForValue().get(redisKey); if (product != null) { // 回填本地缓存 localCache.put(productId, product); return product; } // 3. 查询数据库 product = productRepository.findById(productId) .orElseThrow(() -> new ProductNotFoundException(productId)); // 4. 写入缓存 redisTemplate.opsForValue().set(redisKey, product, REDIS_CACHE_TTL, TimeUnit.SECONDS); localCache.put(productId, product); return product; } public void updateProduct(Product product) { String redisKey = REDIS_KEY_PREFIX + product.getId(); // 更新数据库 productRepository.save(product); // 删除缓存(先删后写,避免脏读) redisTemplate.delete(redisKey); localCache.invalidate(product.getId()); } } // 缓存击穿、穿透、雪崩解决方案 @Service public class CacheProtectionService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private ProductRepository productRepository; private final Semaphore semaphore = new Semaphore(10); /** * 缓存击穿:使用互斥锁 */ public Product getProductWithLock(Long productId) { String key = "product:" + productId; // 尝试从缓存获取 Product product = (Product) redisTemplate.opsForValue().get(key); if (product != null) { return product; } try { // 获取锁 if (semaphore.tryAcquire()) { try { // 双重检查 product = (Product) redisTemplate.opsForValue().get(key); if (product != null) { return product; } // 从数据库加载 product = productRepository.findById(productId) .orElse(null); if (product != null) { redisTemplate.opsForValue().set(key, product, 5, TimeUnit.MINUTES); } return product; } finally { semaphore.release(); } } else { // 等待其他线程加载完成 Thread.sleep(50); return getProductWithLock(productId); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); return productRepository.findById(productId).orElse(null); } } /** * 缓存穿透:布隆过滤器 + 空值缓存 */ private final BloomFilter<Long> bloomFilter; public Product getProductWithBloomFilter(Long productId) { // 布隆过滤器检查 if (!bloomFilter.mightContain(productId)) { return null; // 一定不存在 } String key = "product:" + productId; Product product = (Product) redisTemplate.opsForValue().get(key); if (product != null) { return product; } // 数据库查询 product = productRepository.findById(productId).orElse(null); if (product == null) { // 缓存空值,防止穿透 redisTemplate.opsForValue().set(key, "", 5, TimeUnit.MINUTES); } else { redisTemplate.opsForValue().set(key, product, 30, TimeUnit.MINUTES); bloomFilter.put(productId); } return product; } /** * 缓存雪崩:过期时间随机化 + 持久化 */ public void setProductWithRandomTtl(Product product) { String key = "product:" + product.getId(); // 基础过期时间 + 随机偏移量 long baseTtl = 30 * 60; // 30分钟 long randomTtl = (long) (Math.random() * 10 * 60); // 0-10分钟随机 redisTemplate.opsForValue().set(key, product, baseTtl + randomTtl, TimeUnit.SECONDS); } }四、异步处理与消息队列
在高并发场景中,同步处理往往成为系统的瓶颈。异步处理可以将耗时操作从主流程中分离,显著提高系统的吞吐量和响应速度。消息队列是实现异步处理的核心组件,它解耦了生产者和消费者,让系统能够平滑处理流量高峰。
消息队列在高并发系统中有多种应用场景:异步处理,如用户注册后发送欢迎邮件、订单完成后发送通知等;流量削峰,如秒杀活动中的下单请求先入队,后台慢慢处理;系统解耦,不同模块通过消息队列通信,降低模块间的耦合度;数据同步,如数据库变更后同步到缓存、搜索引擎等。
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service; // 异步下单实现 @Service public class AsyncOrderService { @Autowired private RabbitTemplate rabbitTemplate; private static final String ORDER_EXCHANGE = "order.exchange"; private static final String ORDER_QUEUE = "order.queue"; private static final String NOTIFICATION_QUEUE = "notification.queue"; private static final String INVENTORY_QUEUE = "inventory.queue"; /** * 异步创建订单 */ public OrderResponse createOrderAsync(CreateOrderRequest request) { // 1. 快速生成订单号 String orderId = generateOrderId(); // 2. 创建订单实体(状态为PENDING) Order order = new Order(); order.setId(orderId); order.setCustomerId(request.getCustomerId()); order.setItems(request.getItems()); order.setStatus(OrderStatus.PENDING); order.setCreatedAt(new Date()); // 3. 保存订单 orderRepository.save(order); // 4. 发送消息给库存服务 rabbitTemplate.convertAndSend(ORDER_EXCHANGE, "inventory.reserve", new InventoryReserveMessage(orderId, request.getItems())); // 5. 发送消息给通知服务 rabbitTemplate.convertAndSend(ORDER_EXCHANGE, "notification.order", new OrderCreatedMessage(orderId, request.getCustomerId())); // 6. 立即返回给用户 return new OrderResponse(orderId, "订单正在处理中"); } /** * 订单创建消息处理器 */ @RabbitListener(queues = ORDER_QUEUE) public void handleOrderCreation(OrderMessage message) { try { // 处理订单创建逻辑 Order order = orderRepository.findById(message.getOrderId()) .orElseThrow(() -> new OrderNotFoundException(message.getOrderId())); // 扣减库存 inventoryService.reserveStock(message.getItems()); // 更新订单状态 order.setStatus(OrderStatus.CONFIRMED); orderRepository.save(order); } catch (Exception e) { // 失败处理 handleOrderCreationFailure(message, e); } } } // 消息重试机制 @Service public class MessageRetryHandler { @Autowired private RabbitTemplate rabbitTemplate; private static final int MAX_RETRY_COUNT = 3; private static final long RETRY_DELAY_MS = 5000; public void sendWithRetry(String exchange, String routingKey, Object message) { sendWithRetry(exchange, routingKey, message, 0); } private void sendWithRetry(String exchange, String routingKey, Object message, int retryCount) { try { rabbitTemplate.convertAndSend(exchange, routingKey, message); } catch (Exception e) { if (retryCount < MAX_RETRY_COUNT) { // 指数退避延迟重试 long delay = RETRY_DELAY_MS * (long) Math.pow(2, retryCount); try { Thread.sleep(delay); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } sendWithRetry(exchange, routingKey, message, retryCount + 1); } else { // 超过最大重试次数,发送到死信队列 sendToDeadLetterQueue(message, e); } } } private void sendToDeadLetterQueue(Object message, Exception e) { // 记录日志并发送告警 log.error("Message send failed after max retries", e); alertService.sendAlert("Message processing failed", message.toString()); } }五、限流与熔断机制
在高并发系统中,限流和熔断是保护系统的重要手段。限流控制进入系统的请求数量,避免瞬时流量压垮系统;熔断则在系统出现故障时快速失败,防止故障蔓延。这两种机制共同保障了系统在极端情况下的稳定性。
限流算法有多种实现:计数器算法简单直接,但可能出现突刺;滑动窗口算法解决了计数器的问题;令牌桶算法允许一定的突发流量;漏桶算法以固定速率处理请求。熔断器模式有三个状态:Closed(正常)、Open(熔断)、Half-Open(尝试恢复)。当失败率超过阈值时,熔断器打开,快速拒绝请求;一段时间后进入半开状态,尝试放行部分请求。
import java.util.concurrent.*; import java.util.concurrent.atomic.*; // 滑动窗口限流器 public class SlidingWindowRateLimiter { private final int windowSizeMs; private final int maxRequests; private final Queue<Long> requests; private final long windowStart; public SlidingWindowRateLimiter(int windowSizeMs, int maxRequests) { this.windowSizeMs = windowSizeMs; this.maxRequests = maxRequests; this.requests = new ConcurrentLinkedQueue<>(); this.windowStart = System.currentTimeMillis(); } public synchronized boolean tryAcquire() { long now = System.currentTimeMillis(); long windowEnd = windowStart + windowSizeMs; // 清理过期的请求记录 while (!requests.isEmpty() && requests.peek() < now - windowSizeMs) { requests.poll(); } if (requests.size() < maxRequests) { requests.offer(now); return true; } return false; } public int getCurrentRequestCount() { long now = System.currentTimeMillis(); while (!requests.isEmpty() && requests.peek() < now - windowSizeMs) { requests.poll(); } return requests.size(); } } // 令牌桶限流器 public class TokenBucketRateLimiter { private final long capacity; private final double refillRate; private final AtomicLong tokens; private final AtomicLong lastRefillTime; public TokenBucketRateLimiter(long capacity, double refillPerSecond) { this.capacity = capacity; this.refillRate = refillPerSecond; this.tokens = new AtomicLong(capacity); this.lastRefillTime = new AtomicLong(System.currentTimeMillis()); } public synchronized boolean tryAcquire() { refill(); if (tokens.get() > 0) { tokens.decrementAndGet(); return true; } return false; } private void refill() { long now = System.currentTimeMillis(); long lastRefill = lastRefillTime.get(); if (now > lastRefill) { long elapsed = now - lastRefill; double tokensToAdd = elapsed / 1000.0 * refillRate; tokens.updateAndGet(current -> Math.min(capacity, current + (long) tokensToAdd)); lastRefillTime.set(now); } } } // 熔断器实现 public class CircuitBreaker { private final String name; private final int failureThreshold; private final long timeout; private final long halfOpenSuccessThreshold; private final AtomicReference<State> state = new AtomicReference<>(State.CLOSED); private final AtomicInteger failureCount = new AtomicInteger(0); private final AtomicInteger successCount = new AtomicInteger(0); private final AtomicLong lastFailureTime = new AtomicLong(0); public CircuitBreaker(String name, int failureThreshold, long timeout, int halfOpenSuccessThreshold) { this.name = name; this.failureThreshold = failureThreshold; this.timeout = timeout; this.halfOpenSuccessThreshold = halfOpenSuccessThreshold; } public <T> T execute(Supplier<T> supplier) throws Exception { if (!allowRequest()) { throw new CircuitBreakerOpenException( "Circuit breaker " + name + " is OPEN"); } try { T result = supplier.get(); recordSuccess(); return result; } catch (Exception e) { recordFailure(); throw e; } } private boolean allowRequest() { State currentState = state.get(); if (currentState == State.CLOSED) { return true; } if (currentState == State.OPEN) { if (System.currentTimeMillis() - lastFailureTime.get() > timeout) { // 超时后进入半开状态 state.compareAndSet(State.OPEN, State.HALF_OPEN); successCount.set(0); return true; } return false; } // HALF_OPEN状态,允许部分请求 return true; } private void recordSuccess() { if (state.get() == State.HALF_OPEN) { if (successCount.incrementAndGet() >= halfOpenSuccessThreshold) { state.set(State.CLOSED); failureCount.set(0); } } else { failureCount.set(0); } } private void recordFailure() { lastFailureTime.set(System.currentTimeMillis()); if (state.get() == State.HALF_OPEN) { // 半开状态下失败,直接打开 state.set(State.OPEN); } else if (failureCount.incrementAndGet() >= failureThreshold) { state.set(State.OPEN); } } public enum State { CLOSED, // 正常 OPEN, // 熔断 HALF_OPEN // 半开 } } // 分布式限流实现 @Service public class DistributedRateLimiter { @Autowired private RedisTemplate<String, String> redisTemplate; private static final String RATE_LIMIT_PREFIX = "rate_limit:"; /** * 基于Redis的滑动窗口限流 */ public boolean isAllowed(String userId, String action, int limit, int windowSeconds) { String key = RATE_LIMIT_PREFIX + action + ":" + userId; long now = System.currentTimeMillis(); long windowStart = now - windowSeconds * 1000L; // 使用Redis事务保证原子性 redisTemplate.execute(new SessionCallback<Object>() { @Override public Object execute(RedisOperations operations) throws DataAccessException { // 删除窗口外的记录 operations.opsForZSet().removeRangeByScore(key, 0, windowStart); // 统计当前窗口内的请求数 Long count = operations.opsForZSet().zCard(key); if (count != null && count >= limit) { operations.multi(); return null; } // 添加新请求 operations.opsForZSet().add(key, String.valueOf(now), now); operations.expire(key, windowSeconds + 1); operations.multi(); return null; } }); Long count = redisTemplate.opsForZSet().zCard(key); return count != null && count <= limit; } }六、数据库优化与分库分表
数据库通常是系统中最先达到性能瓶颈的组件。在高并发场景下,单个数据库实例往往无法承受巨大的读写压力。数据库优化包括多个层面:SQL优化确保查询使用合适的索引;连接池优化合理配置连接数量;读写分离将读请求分散到从库;分库分表将数据分散到多个数据库实例。
分库分表是解决数据库性能瓶颈的有效手段。垂直分库按业务模块将表分散到不同数据库;垂直分表将大表按字段分散到多个表;水平分库将数据按某个维度分散到不同数据库;水平分表将数据按某个维度分散到多个表。分库分表需要考虑分片键的选择、跨分片查询、数据迁移等问题。
import org.apache.shardingsphere.api.config.sharding.*; import org.apache.shardingjdbc.core.api.ShardingDataSourceFactory; import javax.sql.DataSource; import java.util.*; // ShardingSphere分库分表配置 @Configuration public class ShardingConfig { @Bean public DataSource dataSource() throws SQLException { // 配置数据源 Map<String, DataSource> dataSourceMap = new HashMap<>(); dataSourceMap.put("ds_0", createDataSource("jdbc:mysql://localhost:3306/ds_0")); dataSourceMap.put("ds_1", createDataSource("jdbc:mysql://localhost:3306/ds_1")); // 配置分片规则 TableRuleConfiguration orderTableRule = new TableRuleConfiguration(); orderTableRule.setLogicTable("t_order"); orderTableRule.setActualDataNodes("ds_${0..1}.t_order_${0..15}"); orderTableRule.setTableShardingStrategyConfig( new StandardShardingStrategyConfiguration("order_id", new OrderIdShardingAlgorithm())); // 配置绑定表 Collection<String> bindingTables = Collections.singletonList("t_order"); // 配置默认数据库分片策略 Properties props = new Properties(); props.setProperty("sql.show", "true"); return ShardingDataSourceFactory.createDataSource( dataSourceMap, Arrays.asList(orderTableRule), bindingTables, props); } } // 分片键选择策略 public class OrderIdShardingAlgorithm implements PreciseShardingAlgorithm<Long> { private static final int SHARDING_COUNT = 16; @Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) { long orderId = shardingValue.getValue(); long shardingIndex = orderId % SHARDING_COUNT; for (String targetName : availableTargetNames) { String suffix = targetName.substring(targetName.lastIndexOf("_") + 1); if (Integer.parseInt(suffix) == shardingIndex) { return targetName; } } throw new IllegalArgumentException("No target found for orderId: " + orderId); } } // 读写分离配置 @Configuration public class ReadWriteSeparationConfig { @Bean @Primary public DataSource masterDataSource() { // 主库数据源 DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://master:3306/order_db"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean(name = "slaveDataSource1") public DataSource slaveDataSource1() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://slave1:3306/order_db"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean(name = "slaveDataSource2") public DataSource slaveDataSource2() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://slave2:3306/order_db"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean public DataSource routingDataSource(@Qualifier("masterDataSource") DataSource master, @Qualifier("slaveDataSource1") DataSource slave1, @Qualifier("slaveDataSource2") DataSource slave2) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("master", master); targetDataSources.put("slave1", slave1); targetDataSources.put("slave2", slave2); RoutingDataSource routingDataSource = new RoutingDataSource(); routingDataSource.setTargetDataSources(targetDataSources); routingDataSource.setDefaultTargetDataSource(master); return routingDataSource; } }总结
高并发系统设计是一项复杂而系统的工程,需要综合运用多种技术手段。本文从架构设计、负载均衡、缓存策略、异步处理、限流熔断、数据库优化等方面全面介绍了高并发系统的核心技术。
在实际应用中,需要根据业务特点和系统规模选择合适的技术方案。同时,高并发优化是一个持续迭代的过程,需要通过监控发现瓶颈,通过测试验证优化效果。最重要的是,要充分考虑系统的可维护性和可扩展性,避免过度优化带来的复杂度提升。