软件开发进阶技能之分布式与高并发(一)

简介: 教程来源 https://tmywi.cn/ 本文系统讲解分布式与高并发核心技能:从CAP/BASE理论、负载均衡、多级缓存(穿透/击穿/雪崩应对)、消息队列、分布式事务/锁,到微服务治理与限流熔断,涵盖原理、实战代码与真实场景,助你构建高可用、可扩展的现代系统。

当你开发的系统从几百个用户增长到几百万、几千万,单台服务器已经无法承载巨大的流量和数据量。这时候,系统架构必须从单体应用演进为分布式系统,并从低并发走向高并发。分布式与高并发是软件开发进阶技能中最具挑战性也最有价值的部分,它融合了网络通信、数据一致性、容错、性能优化、架构设计等众多领域的知识。

什么是分布式系统? 分布式系统是由多个通过网络通信的计算机节点组成的系统,对外表现为一个统一的整体。它的目标是:可扩展性(Scalability)、高可用性(Availability)、容错性(Fault Tolerance)。

什么是高并发? 高并发是指在极短的时间内,系统需要处理大量请求(例如双十一的秒杀、春运抢票)。高并发系统需要充分利用多核、多机并行处理,并通过多种技术手段(缓存、异步、限流、降级)保证系统稳定。

本文将从基础理论(CAP、BASE)、负载均衡、缓存设计、消息队列、分布式事务、分布式锁、服务治理与微服务、限流熔断、一致性哈希、分布式 ID 等方面,结合大量代码示例和真实场景,深入讲解分布式与高并发的核心技能。

预备知识:你已经熟悉后端开发(如 Java/Go/Python),了解数据库和网络基础,写过 Web 服务。

第一部分:分布式系统基础理论 —— CAP 与 BASE

1.1 CAP 定理
CAP 定理指出,一个分布式系统最多只能同时满足以下三个特性中的两个:

一致性(Consistency):所有节点在同一时刻看到相同的数据。即写操作完成后,读操作必须返回最新的写入值。

可用性(Availability):每个请求在有限时间内都能收到非错误的响应(但不保证是最新数据)。

分区容错性(Partition Tolerance):当网络分区(节点之间通信中断)发生时,系统依然能继续运行。

在实际分布式系统中,网络分区是不可避免的(交换机故障、光缆断裂),所以 P 必须满足。因此,系统需要在 CP(一致+分区容忍)和 AP(可用+分区容忍)之间做出权衡。

CP 系统:保证强一致性,但可能在网络分区时拒绝服务(例如 ZooKeeper、HBase、MongoDB 在某些配置下)。典型实现:多数派写入(Paxos/Raft)。

AP 系统:保证可用性,但可能读到不一致的数据(最终一致性,例如 Cassandra、DynamoDB、CouchDB)。典型实现:冲突解决(Last Write Wins, Merkle Tree 反熵)。

1.2 BASE 理论 —— 对 CAP 中一致性的弱化
BASE 是 Basically Available(基本可用)、Soft state(软状态) 和 Eventually consistent(最终一致性) 的缩写。它是对大型分布式系统实践经验的总结,强调用最终一致性换取高可用。

基本可用:系统出现故障时,允许部分功能降级(如响应时间变长、返回旧缓存数据)。

软状态:允许系统中存在中间状态,该状态不影响系统整体可用性(例如数据复制延迟)。

最终一致性:经过一段时间的异步修复,数据最终会达到一致。

最终一致性的变种:

因果一致性:有因果关系的操作需按顺序被所有节点看到。

会话一致性:同一个会话中读操作保证读到自己的写操作。

单调读一致性:一旦读到新值,不会回滚到旧值。

很多实际系统(如 DNS、Gossip 协议)都基于最终一致性设计。

第二部分:高并发架构概述 —— 纵向扩展与横向扩展

要支撑高并发,架构上要么向上(纵向扩展),换更强的服务器(CPU 更多、内存更大),要么向外(横向扩展),增加更多普通服务器。纵向扩展有物理上限且成本非线性增长,因此现代高并发系统主要依赖横向扩展。

横向扩展会带来以下挑战:

负载如何均匀分发到多台机器? → 负载均衡

用户会话(session)如何共享? → 分布式会话

数据如何分布到多个数据库? → 分库分表 / 分片

频繁读取的数据如何减轻数据库压力? → 多级缓存

大量写请求如何削峰填谷? → 消息队列

服务之间如何通信和治理? → 微服务 + 服务注册发现

下面将逐一深入讲解。

第三部分:负载均衡 —— 流量的交通警察

负载均衡器(Load Balancer)是分布式系统的门面,它接收所有客户端请求,然后按照一定策略分发到后端服务器。

3.1 负载均衡层次
DNS 负载均衡:最简单的全局负载,将域名解析到不同 IP。缺点:缓存生效慢,无法感知服务健康状态。

硬件负载均衡(F5、A10):性能极高,但昂贵,通常用于大型入口。

软件负载均衡(Nginx、HAProxy、LVS):开源、灵活,是主流选择。

客户端负载均衡(Ribbon、Spring Cloud LoadBalancer):内嵌在应用内,通过服务注册中心获取可用列表,自行选择节点。

3.2 常见负载均衡算法
image.png
3.3 Nginx 配置示例

upstream backend {
    # 加权轮询
    server 192.168.1.10 weight=3;
    server 192.168.1.11 weight=1;
    # 最少连接
    least_conn;
    # IP Hash
    ip_hash;
    # 健康检查(需 nginx plus 或第三方模块)
    server 192.168.1.12 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

3.4 分布式会话问题与解决方案
当负载均衡使用轮询时,用户请求可能落在不同服务器,导致 session 丢失。解决方案:

粘性会话(Sticky Session):通过 IP Hash 或 cookie 绑定,但某台机器宕机时会话仍会丢失。

会话复制(Session Replication):在 Tomcat 等容器中同步 session 到所有节点,网络开销大,不推荐。

集中存储(推荐):将 session 存入 Redis 或数据库,所有服务器共享。Spring Session + Redis 是典型方案。

Spring Session + Redis 示例:

@Configuration
@EnableRedisHttpSession
public class SessionConfig {
    @Bean
    public LettuceConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory("redis-host", 6379);
    }
}

第四部分:缓存 —— 性能加速的利器

缓存是扛高并发最有效的手段之一。正确使用缓存可以让读请求在内存中直接返回,避免穿透到数据库。

4.1 缓存层次
客户端缓存(浏览器缓存、App 本地缓存)

CDN 缓存:分发静态资源,减轻源站压力。

反向代理缓存(Nginx、Varnish):缓存动态页面片段。

应用本地缓存(Guava Cache、Caffeine):进程内缓存,速度极快,但无法跨服务共享。

分布式缓存(Redis、Memcached):独立于应用,多节点共享。

4.2 缓存模式
4.2.1 Cache Aside(旁路缓存)
这是最常用的模式:

读:先读缓存,命中则返回;未命中则读数据库,写回缓存。

写:先更新数据库,然后删除缓存(或更新缓存,但删除更简单,避免并发脏数据)。

public User getUser(Long id) {
    // 读缓存
    User user = redis.get("user:" + id);
    if (user != null) return user;
    // 读数据库
    user = db.query("SELECT * FROM user WHERE id = ?", id);
    if (user != null) {
        redis.setex("user:" + id, 3600, user);
    }
    return user;
}

public void updateUser(User user) {
    db.update("UPDATE user SET name=? WHERE id=?", user.getName(), user.getId());
    redis.del("user:" + user.getId());  // 删除缓存
}

为什么是删除而不是更新? 因为更新缓存可能有并发问题:两个写线程,一个更新了数据库,另一个用旧值覆盖了缓存。删除后,下次读会重新加载新值。

4.2.2 Read/Write Through(读写穿透)
应用只和缓存交互,缓存作为代理负责读写数据库。适合对应用透明的场景,但缓存层实现复杂。

4.2.3 Write Behind Caching(写回)
先写缓存,异步批量写数据库。写入性能极高,但可能丢失数据(缓存宕机)。适用对数据丢失不敏感的日志、计数等。

4.3 缓存三大痛点:穿透、击穿、雪崩
image.png
布隆过滤器示例(Guava 版)

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

BloomFilter<Long> bloom = BloomFilter.create(Funnels.longFunnel(), 1000000, 0.01);
// 初始化时将所有存在的 id 加入
for (Long id : allUserIds) {
    bloom.put(id);
}

// 查询前先判断
if (!bloom.mightContain(userId)) {
    return null; // 一定不存在,直接返回
}
// 否则走缓存/DB

互斥锁防止击穿(Redis 分布式锁)

public User getWithMutex(Long id) {
    String key = "user:" + id;
    User user = redis.get(key);
    if (user != null) return user;

    // 尝试获取锁
    String lockKey = "lock:user:" + id;
    Boolean locked = redis.setnx(lockKey, "1", 10, TimeUnit.SECONDS);
    if (locked) {
        try {
            user = db.query(...);
            redis.setex(key, 3600, user);
        } finally {
            redis.del(lockKey);
        }
    } else {
        // 等待一小段时间后重试
        Thread.sleep(50);
        return getWithMutex(id);
    }
    return user;
}

4.4 缓存一致性(双写一致性)
当数据库和缓存同时写时,保证一致性是难点。除了 Cache Aside 模式(先更新 DB 再删缓存),还可以:

订阅数据库变更日志(Canal):解析 MySQL binlog,异步刷新缓存。

延时双删:先删缓存,再更新 DB,然后延时(如 1 秒)再删一次,解决并发读导致的脏数据问题。
来源:
https://yyvgt.cn/

相关文章
|
21天前
|
人工智能 Rust 监控
这 3 个开源小工具,帮你让 Coding Agent 少吃点 Token
今天我们就来分享 3 个有用的开源项目,专门帮你的 Coding Agent 整理“上下文”:让它少翻无关代码,少吞冗长日志,把 token 留给更关键的信息。
232 0
这 3 个开源小工具,帮你让 Coding Agent 少吃点 Token
|
21天前
|
存储 弹性计算 数据库
阿里云服务器ECS免费试用攻略:0成本试用体验与申请与使用注意事项
阿里云ECS免费试用活动为新手用户提供零成本上云体验。完成实名认证且从未购买过ECS的用户,可申请3个月免费试用:个人用户享300元额度(0.833元/小时),企业用户享660元额度(1.833元/小时),每月另赠20GB国内+200GB海外公网流量,支持华北2、杭州、广州等7大免费地域。试用期内可灵活调整实例配置,适用于网站托管、开发测试、数据库部署等多种场景。超出额度按量计费,到期未释放将自动转为按量付费。
|
21天前
|
存储 人工智能 自然语言处理
阿里云骡子快跑 MuleRun详解:功能用途、收费标准及完整使用指南
阿里云MuleRun(骡子快跑)是一站式AI原生智能工作空间,支持自然语言驱动任务执行,具备四层记忆、主动智能与可信沙箱等能力,深度集成电商、CRM等数据源,助力企业自动化运营、多平台触达与分析提效。提供Team版(420元/席/月)和Enterprise版(2500元/席/年)。MuleRun(骡子快跑)官网:https://t.aliyun.com/U/gSCv7v
|
21天前
|
存储 SQL 安全
【Java并发编程】JMM Java内存模型:原子性、可见性、有序性、happens-before原则(附《思维导图》+《面试高频考点清单》)
Java内存模型(JMM)是Java并发编程的基石,抽象定义主内存与线程工作内存的交互规则,系统解决可见性、原子性、有序性三大核心问题,并通过happens-before、volatile、synchronized等机制保障多线程安全与跨平台一致性。
|
21天前
|
存储 安全 Java
AgentScope Java 2.0:打造分布式、企业级智能体底座
AgentScope 2.0 面向分布式部署、稳定运行、权限安全等企业级需求全面升级,打造支持多租户隔离与长期稳定运行的企业级智能体底座。
911 14
|
8天前
|
消息中间件 人工智能 安全
7 月 9 日香港,AI Agent 工程化实战专场邀您参会
AI Agent正规模化落地,但多智能体协作、安全治理、高并发稳定运行及决策可解释性等挑战亟待解决。7月9日香港,阿里云将分享“可信、可控、可观测”的企业级Agent工程化实战方案,涵盖Agent Teams、AI网关、RocketMQ for AI与STAROps等全栈能力。
|
21天前
|
缓存 人工智能 JavaScript
Markstream-VUE:构建高性能流式 Markdown 渲染器
在 AI 对话、实时协作文档、知识库等场景中,Markdown 内容的流式渲染已成为刚需。传统方案面临"闪烁重绘"、"内存暴涨"、"大文档卡顿"三大痛点。本文将深度剖析开源项目https://github.com/Simon-He95/markstream-vue的技术架构,从流式解析算法、虚拟化渲染策略、Monaco 增量更新、渐进式图表渲染四个维度,揭示其实现"零闪烁、低内存、高响应"流式体验的核心原理,并提供可直接落地的性能调优方案。
340 8
Markstream-VUE:构建高性能流式 Markdown 渲染器
|
21天前
|
弹性计算 监控 Java
Maven 并行构建配置:-T 4C 提速 4 倍实战
本文深入讲解了 Maven 并行构建的核心原理和实战技巧,包含 -T 参数详解、模块并行化改造、性能监控与分析等企业级最佳实践。通过真实案例展示了如何将多模块项目的构建时间从 45 分钟缩短到 11 分钟(提升 4.1 倍),提供完整的性能测试脚本和优化检查清单。掌握这些技能,你将能够充分利用多核 CPU 加速 Maven 构建。适合 Java 开发者、架构师、DevOps 工程师阅读。
|
21天前
|
人工智能 IDE 定位技术
Understand-Anything:不用硬啃源码,把项目变成一张能追问的知识图谱
Understand-Anything 是一款开源AI工具,通过静态分析+多智能体理解,自动构建代码库知识图谱,帮开发者快速掌握系统架构、业务流程与模块依赖。支持中文、影响分析、新人引导等,让读代码前先有“地图”。(238字)
385 3
Understand-Anything:不用硬啃源码,把项目变成一张能追问的知识图谱
|
19天前
|
缓存 安全 算法
软件开发进阶技能之性能与安全调优(一)
本文系统讲解性能与安全调优核心技术:从算法复杂度优化、集合选型、线程池配置、锁粒度控制,到无锁编程与异步并发,结合大量Java代码示例与底层原理,助开发者构建高可靠、高可用企业级应用。