Java 技术栈全景指南:从基础到微服务的完整知识体系

摘要:本文系统梳理 Java 技术栈的完整知识体系,涵盖 Spring Boot、Spring Cloud、MyBatis、Redis、消息队列等核心框架与中间件。从 Web 开发、持久层到微服务与分布式架构,结合实战案例与选型建议,帮助开发者快速建立 Java 企业级开发的全景认知,为技术选型与项目实践提供参考。

1. 引言

1. 引言

Java 作为一门拥有二十余年历史的编程语言,凭借其跨平台、面向对象、生态丰富等特性,至今仍是企业级应用开发的主流选择。无论是大型互联网公司还是传统金融、制造行业,Java 技术栈都占据着举足轻重的地位。

本文将从 Java 技术栈的整体架构出发,系统梳理 Java 开发中常见的框架与组件,涵盖 Web 开发、持久层、微服务、中间件、构建工具等多个维度,帮助读者建立完整的 Java 技术知识体系。

2. Java 技术栈全景图

Java 技术栈可以按照应用层次划分为以下几大板块:

  • 基础层:JDK、JVM、Java 语言特性
  • Web 开发层:Spring MVC、Spring Boot、Struts2 等
  • 持久层:MyBatis、Hibernate、Spring Data JPA 等
  • 微服务与分布式:Spring Cloud、Dubbo、gRPC 等
  • 中间件:消息队列(Kafka、RabbitMQ)、缓存(Redis)、搜索引擎(Elasticsearch)
  • 构建与工程化:Maven、Gradle、Jenkins
  • 容器化与运维:Docker、Kubernetes、Prometheus

#mermaid-svg-M47jCzhCFQMg3rzt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-M47jCzhCFQMg3rzt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-M47jCzhCFQMg3rzt .error-icon{fill:#552222;}#mermaid-svg-M47jCzhCFQMg3rzt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-M47jCzhCFQMg3rzt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-M47jCzhCFQMg3rzt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-M47jCzhCFQMg3rzt .marker.cross{stroke:#333333;}#mermaid-svg-M47jCzhCFQMg3rzt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-M47jCzhCFQMg3rzt p{margin:0;}#mermaid-svg-M47jCzhCFQMg3rzt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-M47jCzhCFQMg3rzt .cluster-label text{fill:#333;}#mermaid-svg-M47jCzhCFQMg3rzt .cluster-label span{color:#333;}#mermaid-svg-M47jCzhCFQMg3rzt .cluster-label span p{background-color:transparent;}#mermaid-svg-M47jCzhCFQMg3rzt .label text,#mermaid-svg-M47jCzhCFQMg3rzt span{fill:#333;color:#333;}#mermaid-svg-M47jCzhCFQMg3rzt .node rect,#mermaid-svg-M47jCzhCFQMg3rzt .node circle,#mermaid-svg-M47jCzhCFQMg3rzt .node ellipse,#mermaid-svg-M47jCzhCFQMg3rzt .node polygon,#mermaid-svg-M47jCzhCFQMg3rzt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-M47jCzhCFQMg3rzt .rough-node .label text,#mermaid-svg-M47jCzhCFQMg3rzt .node .label text,#mermaid-svg-M47jCzhCFQMg3rzt .image-shape .label,#mermaid-svg-M47jCzhCFQMg3rzt .icon-shape .label{text-anchor:middle;}#mermaid-svg-M47jCzhCFQMg3rzt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-M47jCzhCFQMg3rzt .rough-node .label,#mermaid-svg-M47jCzhCFQMg3rzt .node .label,#mermaid-svg-M47jCzhCFQMg3rzt .image-shape .label,#mermaid-svg-M47jCzhCFQMg3rzt .icon-shape .label{text-align:center;}#mermaid-svg-M47jCzhCFQMg3rzt .node.clickable{cursor:pointer;}#mermaid-svg-M47jCzhCFQMg3rzt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-M47jCzhCFQMg3rzt .arrowheadPath{fill:#333333;}#mermaid-svg-M47jCzhCFQMg3rzt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-M47jCzhCFQMg3rzt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-M47jCzhCFQMg3rzt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-M47jCzhCFQMg3rzt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-M47jCzhCFQMg3rzt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-M47jCzhCFQMg3rzt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-M47jCzhCFQMg3rzt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-M47jCzhCFQMg3rzt .cluster text{fill:#333;}#mermaid-svg-M47jCzhCFQMg3rzt .cluster span{color:#333;}#mermaid-svg-M47jCzhCFQMg3rzt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-M47jCzhCFQMg3rzt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-M47jCzhCFQMg3rzt rect.text{fill:none;stroke-width:0;}#mermaid-svg-M47jCzhCFQMg3rzt .icon-shape,#mermaid-svg-M47jCzhCFQMg3rzt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-M47jCzhCFQMg3rzt .icon-shape p,#mermaid-svg-M47jCzhCFQMg3rzt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-M47jCzhCFQMg3rzt .icon-shape .label rect,#mermaid-svg-M47jCzhCFQMg3rzt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-M47jCzhCFQMg3rzt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-M47jCzhCFQMg3rzt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-M47jCzhCFQMg3rzt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Java 技术栈
基础层
Web 开发层
持久层
微服务与分布式
中间件
构建与工程化
容器化与运维
JDK / JVM
Spring Boot
Spring MVC
MyBatis
Hibernate
Spring Cloud
Dubbo
Kafka / RabbitMQ
Redis
Maven / Gradle
Docker / K8s

3. Web 开发框架

3.1 Spring 家族

Spring 是 Java 生态中最核心的框架,几乎成为 Java 企业级开发的代名词。

Spring Framework 提供了 IoC(控制反转)和 AOP(面向切面编程)两大核心能力,是整个 Spring 生态的基石。通过 IoC 容器管理对象的创建与依赖关系,大大降低了组件之间的耦合度。

Spring Boot 是 Spring 生态中最重要的演进,它通过自动配置和起步依赖,让开发者能够以极低的成本快速搭建可独立运行的 Spring 应用。内嵌 Tomcat、Jetty 等容器,使得部署变得异常简单,目前已成为 Java Web 开发的事实标准。

Spring MVC 是基于 Servlet 的 Web 框架,采用 MVC 分层思想,将控制器、模型、视图解耦,配合 RESTful 风格接口设计,广泛用于传统单体应用开发。

3.2 其他 Web 框架

Struts2 是早期的经典 MVC 框架,虽然如今已逐渐淡出主流,但在部分遗留系统中仍可见到。

Vert.x 是一个基于事件驱动和非阻塞 IO 的框架,适合构建高并发、低延迟的响应式应用,在物联网和实时通信场景中表现突出。

4. 持久层框架

4.1 MyBatis

MyBatis 是一款半自动 ORM 框架,它允许开发者直接编写 SQL 语句,灵活度极高。通过 XML 或注解配置 SQL 与 Java 方法的映射关系,适合对 SQL 优化有较高要求的复杂业务场景。

java 复制代码
@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User findById(Long id);
}

4.2 Hibernate 与 JPA

Hibernate 是经典的自动 ORM 框架,开发者无需编写 SQL,通过对象关系映射即可完成数据库操作。Spring Data JPA 在此基础上进一步封装,提供了 Repository 接口的自动实现,大幅提升开发效率。

java 复制代码
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByAgeGreaterThan(int age);
}

4.3 数据库连接池

在实际项目中,数据库连接池是必不可少的组件。HikariCP 凭借其轻量和高性能成为 Spring Boot 默认选择;Druid 则提供了监控、SQL 拦截等丰富功能,在国内企业中使用广泛。

5. 微服务与分布式框架

5.1 Spring Cloud

Spring Cloud 是基于 Spring Boot 的微服务解决方案全家桶,涵盖服务注册与发现、配置中心、网关、熔断降级等能力。

  • 服务注册与发现:Eureka、Nacos、Consul
  • 配置中心:Spring Cloud Config、Nacos Config
  • 网关:Spring Cloud Gateway、Zuul
  • 熔断降级:Sentinel、Hystrix、Resilience4j
  • 负载均衡:Ribbon、Spring Cloud LoadBalancer
基于 Spring Cloud Alibaba 的微服务实战案例

下面以一个「订单服务调用用户服务」的典型场景为例,演示 Spring Cloud Alibaba 三大核心组件的落地用法:Nacos 负责服务注册与发现,OpenFeign 负责声明式远程调用,Sentinel 负责熔断降级与流量防护。

① 引入依赖(pom.xml)

xml 复制代码
<!-- 统一管理 Spring Cloud Alibaba 版本 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2021.0.5.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- Nacos 服务注册与发现 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- OpenFeign 远程调用 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <!-- Sentinel 熔断降级 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>
</dependencies>

② 配置 Nacos 注册中心(application.yml)

yaml 复制代码
spring:
  application:
    name: order-service        # 服务名,注册到 Nacos 后用于服务发现
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848   # Nacos 服务端地址
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080     # Sentinel 控制台地址
server:
  port: 8081

③ 启动类开启服务发现与 Feign(OrderApplication.java)

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient          // 开启 Nacos 服务注册与发现
@EnableFeignClients             // 开启 OpenFeign 远程调用
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

④ 声明 Feign 客户端,远程调用用户服务(UserClient.java)

java 复制代码
@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient {

    @GetMapping("/user/{id}")
    User getUserById(@PathVariable("id") Long id);
}

⑤ 编写 Sentinel 熔断降级兜底类(UserClientFallback.java)

java 复制代码
@Component
public class UserClientFallback implements UserClient {

    @Override
    public User getUserById(Long id) {
        // 降级兜底:返回默认用户,避免异常向上游扩散
        User fallback = new User();
        fallback.setId(id);
        fallback.setName("默认用户");
        return fallback;
    }
}

⑥ 业务调用:订单服务通过 Feign 获取用户信息(OrderService.java)

java 复制代码
@Service
public class OrderService {

    @Autowired
    private UserClient userClient;

    // @SentinelResource 定义资源名并配置降级兜底方法
    @SentinelResource(value = "getUser", fallback = "getUserFallback")
    public User getUser(Long userId) {
        // 通过 OpenFeign 发起远程调用,由 Nacos 完成服务发现与负载均衡
        return userClient.getUserById(userId);
    }

    // 兜底方法:当触发 Sentinel 熔断或限流时执行
    public User getUserFallback(Long userId, Throwable ex) {
        User fallback = new User();
        fallback.setId(userId);
        fallback.setName("服务繁忙,请稍后重试");
        return fallback;
    }
}

关键步骤小结 :① 通过 @EnableDiscoveryClient 让服务注册到 Nacos,实现服务发现;② 通过 @FeignClient 声明式定义远程调用接口,由 Nacos 完成服务路由与负载均衡;③ 通过 @SentinelResource 为关键方法配置熔断降级兜底,当被调服务异常或流量超阈值时自动降级,保障系统稳定。

5.2 Dubbo

5.2 Dubbo

Dubbo 是阿里巴巴开源的高性能 RPC 框架,擅长服务治理,支持多种协议(如 Dubbo 协议、gRPC、HTTP),在大型分布式系统中应用广泛。与 Spring Cloud 相比,Dubbo 更侧重于高性能 RPC 调用和服务治理能力。

Spring Cloud 与 Dubbo 对比
对比维度 Spring Cloud Dubbo
服务治理 全家桶式解决方案,涵盖注册发现、配置中心、网关、熔断、负载均衡等完整能力 侧重服务注册发现、路由、负载均衡与集群容错,治理能力聚焦于 RPC 调用链路
RPC 协议 默认基于 HTTP/REST,通过 OpenFeign 或 RestTemplate 调用,协议通用、跨语言友好 原生 Dubbo 协议(高性能二进制),同时支持 gRPC、HTTP、REST 等多种协议
生态整合 与 Spring Boot/Spring Cloud Alibaba 深度整合,组件丰富,社区活跃,适合全家桶式落地 与 Spring 生态集成良好,但周边组件相对精简,常需搭配 Nacos、Sentinel 等外部组件
适用场景 适合需要完整微服务治理体系、追求生态统一与快速迭代的大型分布式系统 适合对 RPC 性能要求高、服务间调用频繁、希望轻量级服务治理的互联网高并发场景

选型建议:若团队已深度使用 Spring 生态、需要一站式微服务治理能力,优先选择 Spring Cloud(尤其 Spring Cloud Alibaba);若业务以高性能 RPC 调用为核心、追求极致吞吐与低延迟,且服务治理需求相对聚焦,Dubbo 是更合适的选择。两者也可结合使用,以 Dubbo 作为 RPC 通信层、Spring Cloud 提供治理与生态整合。

Dubbo 是阿里巴巴开源的高性能 RPC 框架,擅长服务治理,支持多种协议(如 Dubbo 协议、gRPC、HTTP),在大型分布式系统中应用广泛。与 Spring Cloud 相比,Dubbo 更侧重于高性能 RPC 调用和服务治理能力。

5.3 分布式事务

在微服务架构下,跨服务的数据一致性是难点。常见解决方案包括:

  • Seata:阿里开源的分布式事务框架,支持 AT、TCC、SAGA 模式
  • 本地消息表 + 消息队列:通过最终一致性方案解决

下面以一个「下单扣库存 + 扣余额」的典型跨服务场景为例,演示 Seata AT 模式的完整落地流程:订单服务负责创建订单并扣减库存,账户服务负责扣减用户余额,两者通过 @GlobalTransactional 纳入同一个全局事务,保证数据一致性。

① 引入 Seata 依赖(pom.xml)

xml 复制代码
<!-- Seata 分布式事务 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
<!-- 使用 Nacos 作为 Seata 注册与配置中心时,需引入 Nacos 客户端 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

② 配置 Seata 数据源代理(application.yml)

Seata AT 模式要求对业务数据源进行代理,以便在事务执行过程中自动记录 undo_log 回滚日志。使用 seata-spring-boot-starter 时,只需开启自动代理即可:

yaml 复制代码
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848   # Nacos 服务端地址
    alibaba:
      seata:
        tx-service-group: my_test_tx_group   # 事务分组,需与 Seata Server 配置一致
seata:
  enabled: true
  application-id: order-service
  tx-service-group: my_test_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
  # 数据源自动代理:Seata 会为 DataSource 生成代理,自动记录 undo_log
  data-source-proxy-mode: AT
server:
  port: 8081

说明:Seata 会在每个参与事务的数据库中自动创建 undo_log 表,用于 AT 模式下的回滚日志记录。若使用非自动代理方式,也可手动用 DataSourceProxy 包装数据源。

③ 启动类开启全局事务支持(OrderApplication.java)

java 复制代码
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

④ 订单服务:创建订单并扣减库存(OrderService.java)

java 复制代码
@Service
public class OrderService {

    @Autowired
    private StockClient stockClient;      // 远程调用库存服务(Feign)
    @Autowired
    private AccountClient accountClient;  // 远程调用账户服务(Feign)
    @Autowired
    private OrderMapper orderMapper;

    // @GlobalTransactional 开启全局事务:任一分支失败则整体回滚
    @GlobalTransactional(name = "create-order-tx", rollbackFor = Exception.class)
    public void createOrder(Long userId, Long productId, Integer count, BigDecimal amount) {
        // 1. 本地事务:创建订单(状态为待支付)
        Order order = new Order();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setCount(count);
        order.setAmount(amount);
        order.setStatus(0);
        orderMapper.insert(order);

        // 2. 远程调用库存服务:扣减库存(参与全局事务)
        stockClient.deductStock(productId, count);

        // 3. 远程调用账户服务:扣减余额(参与全局事务)
        accountClient.deductBalance(userId, amount);

        // 4. 全部成功,订单状态置为已支付
        order.setStatus(1);
        orderMapper.updateById(order);
    }
}

⑤ 库存服务:扣减库存(StockService.java)

java 复制代码
@Service
public class StockService {

    @Autowired
    private StockMapper stockMapper;

    // 库存扣减方法:由订单服务通过 Feign 远程调用
    public void deductStock(Long productId, Integer count) {
        // 乐观锁扣减:库存不足时影响行数为 0,抛出异常触发全局回滚
        int rows = stockMapper.deductStock(productId, count);
        if (rows == 0) {
            throw new RuntimeException("库存不足,扣减失败");
        }
    }
}

⑥ 账户服务:扣减余额(AccountService.java)

java 复制代码
@Service
public class AccountService {

    @Autowired
    private AccountMapper accountMapper;

    // 余额扣减方法:由订单服务通过 Feign 远程调用
    public void deductBalance(Long userId, BigDecimal amount) {
        // 余额不足时影响行数为 0,抛出异常触发全局回滚
        int rows = accountMapper.deductBalance(userId, amount);
        if (rows == 0) {
            throw new RuntimeException("余额不足,扣减失败");
        }
    }
}

⑦ 关键步骤小结 :① 通过 @GlobalTransactional 在订单服务入口开启全局事务,将库存扣减与余额扣减纳入同一事务边界;② 各参与服务只需在本地方法中正常执行 SQL,Seata AT 模式会自动记录 undo_log 并在异常时反向补偿回滚;③ 任一分支(如库存不足、余额不足)抛出异常,全局事务即整体回滚,保证跨服务数据一致性。

分布式事务方案对比

为便于选型,下表横向比较 Seata AT、TCC、SAGA 与本地消息表 + MQ 四种主流方案的实现原理、一致性保证、适用场景与优缺点:

对比维度 Seata AT Seata TCC Seata SAGA 本地消息表 + MQ
实现原理 基于数据源代理自动记录 undo_log,通过全局锁 + 反向 SQL 补偿实现回滚,对业务代码侵入极小 业务方需手动实现 Try、Confirm、Cancel 三个方法,由框架协调各分支的预留与确认/回滚 将长事务拆分为多个本地事务,通过状态机编排,按顺序执行并记录补偿动作 业务本地事务中同步写业务表与消息表,通过定时任务轮询消息表并投递 MQ,消费方处理后确认
一致性保证 强一致性(全局事务提交前各分支数据对外不可见,通过全局锁隔离) 强一致性(Try 阶段预留资源,Confirm/Cancel 阶段最终一致) 最终一致性(各分支独立提交,失败时执行反向补偿) 最终一致性(依赖消息可靠投递与消费确认,允许短暂不一致)
适用场景 对一致性要求高、业务改动小、希望快速接入的跨库/跨服务事务 对性能要求高、业务可拆分为预留/确认/回滚三段、且能接受一定开发量的场景 长链路、多步骤业务流程(如订单、审批、旅行预订),对实时一致性要求不苛刻 异步解耦、削峰填谷、对实时性要求不高的场景(如积分、通知、日志同步)
优点 侵入性低、接入成本小、自动回滚、对开发者透明 性能较好、无全局锁、资源占用低、适合高并发 无全局锁、适合长事务、可编排复杂流程、容错性强 实现简单、天然异步、系统解耦、无额外框架依赖
缺点 存在全局锁,高并发下性能有损耗;依赖 undo_log 表与全局事务协调器 开发量大,需为每个分支编写三套方法;空回滚、幂等、悬挂等边界需自行处理 补偿逻辑需人工编写,流程编排复杂;一致性较弱,存在中间状态 消息可能重复投递,需消费幂等;数据最终一致,存在时间窗口;需维护定时任务

选型建议:若追求强一致性且希望快速落地、业务侵入小,优先选择 Seata AT 模式;若业务对性能敏感、能接受较高的开发成本,可选用 TCC 模式;若业务流程长、步骤多且对实时一致性要求不高,SAGA 模式更合适;若业务天然适合异步解耦、允许最终一致,本地消息表 + MQ 是最轻量、成本最低的方案。实际项目中常将多种方案组合使用,例如核心资金链路用 AT/TCC 保证强一致,非核心异步链路用消息表 + MQ 实现最终一致。

6. 中间件

6.1 消息队列

消息队列用于系统解耦、异步处理和流量削峰。

  • Kafka:高吞吐、分布式消息系统,适合日志收集、大数据流处理
  • RabbitMQ:基于 AMQP 协议,功能完善,适合复杂路由场景
  • RocketMQ:阿里开源,支持事务消息,适合电商等业务场景
Kafka、RabbitMQ、RocketMQ 对比

为便于选型,下表从吞吐量、消息可靠性、延迟、适用场景与优缺点五个维度,横向对比 Kafka、RabbitMQ、RocketMQ 三大主流消息队列:

对比维度 Kafka RabbitMQ RocketMQ
吞吐量 极高,基于分区 + 顺序写盘 + 批量发送,单机可达数十万级 TPS,是大数据场景的首选 中等,基于 AMQP 协议与内存队列,单机吞吐在万级左右,适合中小规模业务 高,借鉴 Kafka 的分区模型并优化,单机可达十万级 TPS,兼顾吞吐与功能
消息可靠性 高,通过副本机制(ISR)与 acks 配置保证不丢消息,但需合理设置 acks=all 与 min.insync.replicas 高,支持 Publisher Confirm、事务与持久化队列,可靠性配置灵活,适合对消息不丢失要求严格的业务 高,支持同步/异步刷盘、主从复制与事务消息,可靠性机制完善,适合金融级场景
延迟 较高,为追求吞吐牺牲了部分延迟,端到端延迟通常在毫秒到百毫秒级 较低,内存队列 + 即时投递,延迟通常在毫秒级,适合对实时性敏感的场景 较低,优化了存储与网络模型,延迟通常在毫秒级,兼顾吞吐与实时性
适用场景 日志收集、大数据流处理、用户行为追踪、指标监控等海量数据场景 复杂路由、RPC 异步化、任务队列、需要灵活交换机(Exchange)绑定的业务场景 电商交易、订单消息、事务消息、削峰填谷等对可靠性与功能要求高的业务场景
优点 吞吐极高、生态成熟(与 Flink/Spark 深度集成)、天然支持分区与多副本、可水平扩展 功能丰富(多种交换机类型)、路由灵活、社区活跃、上手简单、管理界面友好 功能全面(事务消息、延迟消息、消息轨迹)、吞吐高、可靠性强、阿里大规模生产验证
缺点 功能相对精简(无内置延迟消息、事务消息支持较弱)、延迟偏高、运维门槛较高 吞吐相对有限、消息堆积能力较弱、水平扩展不如 Kafka/RocketMQ 平滑 社区与生态相对 Kafka 略小、客户端语言覆盖不如 Kafka 广、运维组件较多

选型建议:若业务以海量日志、大数据流处理为核心,追求极致吞吐,优先选择 Kafka;若业务需要灵活的路由与交换机能力、对实时性要求高、消息量中等,RabbitMQ 是更轻量易用的选择;若业务属于电商交易、订单等核心链路,既要求高吞吐又需要事务消息、延迟消息等高级特性,RocketMQ 最为合适。实际项目中常将多种消息队列组合使用,例如用 Kafka 承载日志与流计算、用 RocketMQ 承载核心交易消息、用 RabbitMQ 处理复杂路由的异步任务。

6.2 缓存

Redis 是 Java 生态中最常用的缓存中间件,支持丰富的数据结构(String、Hash、List、Set、ZSet),配合 Spring Data Redis 可以轻松集成。在缓存穿透、击穿、雪崩等场景下,需要结合布隆过滤器、互斥锁等策略进行防护。

缓存穿透、击穿、雪崩的排查与应对

缓存穿透:指查询一个数据库中不存在的数据,缓存与数据库都查不到,导致每次请求都直接打到数据库。

  • 典型现象:大量请求命中不存在的 key,数据库压力骤增,QPS 异常升高。
  • 排查步骤 :
    ① 查看 Redis 命中率是否骤降(INFO stats 观察 keyspace_hits / keyspace_misses 比值);
    ② 使用 MONITOR 命令实时观察命令流,定位高频访问的不存在 key;
    ③ 检查请求 key 是否集中在不存在的 ID 上(如自增 ID 被恶意遍历);
    ④ 结合应用慢查询日志与访问日志,确认是否被恶意或异常流量刷接口;
    ⑤ 用 redis-cli --bigkeys 或热点 key 分析工具,确认是否存在大量空值缓存。
  • 代码级解决方案:使用布隆过滤器在缓存前拦截不存在的 key,或对空结果做短暂缓存。
java 复制代码
// 布隆过滤器拦截(以 Redisson 为例)
RBloomFilter<String> bloomFilter = redisson.getBloomFilter("userBloom");
bloomFilter.tryInit(100000L, 0.03);

public User getUserById(Long id) {
    String key = "user:" + id;
    if (!bloomFilter.contains(key)) {
        return null; // 一定不存在,直接返回
    }
    User user = redisTemplate.opsForValue().get(key);
    if (user == null) {
        user = userMapper.findById(id);
        if (user == null) {
            // 空值短暂缓存,防止穿透
            redisTemplate.opsForValue().set(key, "", 60, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
        }
    }
    return user;
}

缓存击穿:指某个热点 key 在过期瞬间,大量并发请求同时打到数据库。

  • 典型现象:某个热点数据过期后,数据库瞬时出现大量相同查询,连接池被打满。
  • 排查步骤 :
    ① 定位是哪个 key 过期引发(通过 MONITOR 或应用日志找到回源数据库的 key);
    ② 观察该 key 的访问量是否集中在同一时刻(结合 Redis 的 INFO commandstats 与热点 key 分析);
    ③ 检查缓存过期时间设置是否合理,是否热点数据过期时间过短;
    ④ 使用 Redis 慢查询日志(SLOWLOG GET)确认数据库回源是否集中爆发;
    ⑤ 结合监控大盘,对比缓存命中率与数据库 QPS 的瞬时波动曲线。
  • 代码级解决方案:使用互斥锁(分布式锁)保证只有一个线程回源数据库,其余线程等待缓存重建。
java 复制代码
public User getUserById(Long id) {
    String key = "user:" + id;
    User user = redisTemplate.opsForValue().get(key);
    if (user != null) {
        return user;
    }
    // 互斥锁:只允许一个线程回源数据库
    String lockKey = "lock:" + key;
    boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS);
    if (locked) {
        try {
            user = userMapper.findById(id);
            redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES);
        } finally {
            redisTemplate.delete(lockKey);
        }
    } else {
        // 其他线程短暂休眠后重试
        Thread.sleep(100);
        return getUserById(id);
    }
    return user;
}

缓存雪崩:指大量 key 在同一时间段集中过期,导致数据库瞬间承受巨大压力。

  • 典型现象:缓存大面积失效,数据库 QPS 飙升,甚至引发服务不可用。
  • 排查步骤 :
    ① 检查缓存 key 的过期时间是否集中在同一时刻(批量扫描 key 的 TTL 分布);
    ② 确认是否因宕机或批量更新导致缓存整体清空(查看 Redis 重启时间与 INFO memory 的 used_memory 变化);
    ③ 观察数据库连接池与慢查询指标,确认是否出现连接数打满;
    ④ 使用 MONITOR 或 redis-cli --scan 抽样统计 key 的过期时间分布;
    ⑤ 结合应用日志与发布记录,排查是否因代码批量删除或缓存预热缺失引发。
  • 代码级解决方案:为过期时间增加随机偏移量打散失效时间,或采用逻辑过期 + 异步重建的方式。
java 复制代码
// 过期时间加随机值,避免集中失效
int baseExpire = 30 * 60;
int randomExpire = baseExpire + new Random().nextInt(300);
redisTemplate.opsForValue().set(key, user, randomExpire, TimeUnit.SECONDS);

// 逻辑过期:缓存中存逻辑过期时间,异步线程重建
public User getUserById(Long id) {
    String key = "user:" + id;
    CacheData cacheData = redisTemplate.opsForValue().get(key);
    if (cacheData == null) {
        return null;
    }
    if (cacheData.getExpireTime() > System.currentTimeMillis()) {
        return cacheData.getUser(); // 未过期,直接返回
    }
    // 已逻辑过期,异步重建缓存,先返回旧数据
    asyncRebuildCache(id);
    return cacheData.getUser();
}
缓存异常综合防护实战

前面分别介绍了缓存穿透、击穿、雪崩的独立解决方案,但在真实的高并发业务中,这三种异常往往同时存在、相互叠加。下面给出一个完整的 Spring Boot 服务类,将布隆过滤器拦截、互斥锁回源、逻辑过期异步重建三种策略整合到同一个 getUserById 方法中,形成一套「先拦截、再回源、后重建」的立体防护链路:

java 复制代码
@Service
public class UserCacheService {

    @Autowired
    private StringRedisTemplate redisTemplate;   // Redis 客户端
    @Autowired
    private RedissonClient redisson;            // Redisson,用于布隆过滤器与分布式锁
    @Autowired
    private UserMapper userMapper;              // 数据库访问

    private static final String USER_KEY_PREFIX = "user:";
    private static final String LOCK_KEY_PREFIX = "lock:user:";
    private static final long LOGICAL_TTL_MS = 30 * 60 * 1000L;  // 逻辑过期时间 30 分钟

    /**
     * 综合防护查询入口:
     * 1. 布隆过滤器拦截 ------ 防穿透(key 一定不存在时直接返回,不打数据库)
     * 2. 互斥锁回源 ------ 防击穿(热点 key 过期瞬间只允许一个线程回源)
     * 3. 逻辑过期异步重建 ------ 防雪崩(缓存不物理过期,异步刷新,避免集中失效)
     */
    public User getUserById(Long id) {
        String key = USER_KEY_PREFIX + id;

        // ========== 第一层:布隆过滤器拦截(防穿透) ==========
        // 触发条件:请求的 key 在布隆过滤器中不存在,说明该 ID 一定没有数据
        // 降级路径:直接返回 null,避免无效请求穿透到数据库
        RBloomFilter<String> bloomFilter = redisson.getBloomFilter("userBloom");
        if (!bloomFilter.contains(key)) {
            return null; // 一定不存在,直接返回,数据库零压力
        }

        // ========== 第二层:读取缓存(逻辑过期结构) ==========
        // 缓存中存的是 CacheData(含用户数据 + 逻辑过期时间戳),而非裸 User
        CacheData cacheData = redisTemplate.opsForValue().get(key);
        if (cacheData == null) {
            // 缓存完全缺失(如首次访问或缓存被清空),走互斥锁回源
            return loadFromDbWithLock(id, key);
        }

        // 缓存命中且未逻辑过期:直接返回,性能最优
        if (cacheData.getExpireTime() > System.currentTimeMillis()) {
            return cacheData.getUser();
        }

        // ========== 第三层:逻辑过期,异步重建(防雪崩) ==========
        // 触发条件:缓存已逻辑过期,但数据仍在(不物理删除)
        // 降级路径:先返回旧数据保证可用性,同时异步线程回源重建缓存
        // 由于缓存不物理过期,大量 key 不会在同一时刻集中失效,从而规避雪崩
        asyncRebuildCache(id, key);
        return cacheData.getUser(); // 返回旧数据,用户体验无感知
    }

    /**
     * 互斥锁回源:仅允许一个线程查询数据库并重建缓存,其余线程等待后重试
     * 触发条件:缓存缺失(穿透拦截通过但缓存为空),或需要重建缓存
     * 降级路径:抢到锁的线程回源数据库;未抢到锁的线程短暂休眠后递归重试
     */
    private User loadFromDbWithLock(Long id, String key) {
        String lockKey = LOCK_KEY_PREFIX + id;
        // 尝试获取分布式锁,5 秒自动过期防止死锁
        boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS);
        if (locked) {
            try {
                // 双重检查:可能其他线程已重建完成
                CacheData cacheData = redisTemplate.opsForValue().get(key);
                if (cacheData != null && cacheData.getExpireTime() > System.currentTimeMillis()) {
                    return cacheData.getUser();
                }
                // 真正回源数据库
                User user = userMapper.findById(id);
                if (user == null) {
                    // 数据库也不存在:空值短暂缓存,进一步防穿透
                    redisTemplate.opsForValue().set(key, "", 60, TimeUnit.SECONDS);
                    return null;
                }
                // 写入逻辑过期缓存(物理不过期,避免雪崩)
                CacheData newData = new CacheData(user, System.currentTimeMillis() + LOGICAL_TTL_MS);
                redisTemplate.opsForValue().set(key, newData);
                return user;
            } finally {
                // 释放锁
                redisTemplate.delete(lockKey);
            }
        } else {
            // 其他线程正在回源:短暂休眠后重试,避免自旋空耗
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            return getUserById(id); // 递归重试,走完整防护链路
        }
    }

    /**
     * 异步重建缓存:逻辑过期后由后台线程回源数据库并刷新缓存
     * 触发条件:缓存逻辑过期,但仍有旧数据可返回
     * 降级路径:异步执行,不阻塞主线程;重建失败不影响旧数据返回
     */
    private void asyncRebuildCache(Long id, String key) {
        // 使用线程池异步执行,避免阻塞请求线程
        CompletableFuture.runAsync(() -> {
            // 先获取互斥锁,防止多个线程同时重建同一 key
            String lockKey = LOCK_KEY_PREFIX + id;
            boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 5, TimeUnit.SECONDS);
            if (!locked) {
                return; // 已有线程在重建,直接放弃
            }
            try {
                User user = userMapper.findById(id);
                if (user != null) {
                    CacheData newData = new CacheData(user, System.currentTimeMillis() + LOGICAL_TTL_MS);
                    redisTemplate.opsForValue().set(key, newData);
                }
            } finally {
                redisTemplate.delete(lockKey);
            }
        });
    }

    /**
     * 缓存数据结构:用户数据 + 逻辑过期时间戳
     * 逻辑过期而非物理过期,是防雪崩的关键设计
     */
    @Data
    public static class CacheData {
        private User user;
        private long expireTime;

        public CacheData(User user, long expireTime) {
            this.user = user;
            this.expireTime = expireTime;
        }
    }
}

三种策略的触发条件与降级路径小结:

防护策略 触发条件 降级路径
布隆过滤器拦截 请求的 key 在布隆过滤器中不存在(ID 一定无数据) 直接返回 null,不打数据库,从源头拦截穿透流量
互斥锁回源 缓存完全缺失(首次访问或缓存被清空) 抢到锁的线程回源数据库并重建缓存;未抢到锁的线程休眠后重试,避免数据库被并发打爆
逻辑过期异步重建 缓存命中但逻辑过期(数据仍在,时间戳已超时) 先返回旧数据保证可用性,后台线程异步回源刷新缓存,避免大量 key 集中物理失效引发雪崩

设计要点:① 布隆过滤器放在最前面,用极低的内存成本拦截绝大多数不存在的 key;② 互斥锁保证同一时刻只有一个线程回源数据库,解决热点 key 击穿;③ 缓存采用「逻辑过期」而非「物理过期」,从根源上规避大量 key 集中失效导致的雪崩,同时配合异步重建保证数据最终一致。三层策略各司其职、层层递进,共同构成一套完整的高并发缓存防护体系。

缓存异常排查流程图

下面用一张 Mermaid 流程图,汇总缓存穿透、击穿、雪崩三类异常的排查路径与应对策略,便于快速定位问题:
#mermaid-svg-e2mSFohyeqeyUZON{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-e2mSFohyeqeyUZON .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-e2mSFohyeqeyUZON .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-e2mSFohyeqeyUZON .error-icon{fill:#552222;}#mermaid-svg-e2mSFohyeqeyUZON .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-e2mSFohyeqeyUZON .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-e2mSFohyeqeyUZON .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-e2mSFohyeqeyUZON .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-e2mSFohyeqeyUZON .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-e2mSFohyeqeyUZON .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-e2mSFohyeqeyUZON .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-e2mSFohyeqeyUZON .marker{fill:#333333;stroke:#333333;}#mermaid-svg-e2mSFohyeqeyUZON .marker.cross{stroke:#333333;}#mermaid-svg-e2mSFohyeqeyUZON svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-e2mSFohyeqeyUZON p{margin:0;}#mermaid-svg-e2mSFohyeqeyUZON .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-e2mSFohyeqeyUZON .cluster-label text{fill:#333;}#mermaid-svg-e2mSFohyeqeyUZON .cluster-label span{color:#333;}#mermaid-svg-e2mSFohyeqeyUZON .cluster-label span p{background-color:transparent;}#mermaid-svg-e2mSFohyeqeyUZON .label text,#mermaid-svg-e2mSFohyeqeyUZON span{fill:#333;color:#333;}#mermaid-svg-e2mSFohyeqeyUZON .node rect,#mermaid-svg-e2mSFohyeqeyUZON .node circle,#mermaid-svg-e2mSFohyeqeyUZON .node ellipse,#mermaid-svg-e2mSFohyeqeyUZON .node polygon,#mermaid-svg-e2mSFohyeqeyUZON .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-e2mSFohyeqeyUZON .rough-node .label text,#mermaid-svg-e2mSFohyeqeyUZON .node .label text,#mermaid-svg-e2mSFohyeqeyUZON .image-shape .label,#mermaid-svg-e2mSFohyeqeyUZON .icon-shape .label{text-anchor:middle;}#mermaid-svg-e2mSFohyeqeyUZON .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-e2mSFohyeqeyUZON .rough-node .label,#mermaid-svg-e2mSFohyeqeyUZON .node .label,#mermaid-svg-e2mSFohyeqeyUZON .image-shape .label,#mermaid-svg-e2mSFohyeqeyUZON .icon-shape .label{text-align:center;}#mermaid-svg-e2mSFohyeqeyUZON .node.clickable{cursor:pointer;}#mermaid-svg-e2mSFohyeqeyUZON .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-e2mSFohyeqeyUZON .arrowheadPath{fill:#333333;}#mermaid-svg-e2mSFohyeqeyUZON .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-e2mSFohyeqeyUZON .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-e2mSFohyeqeyUZON .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-e2mSFohyeqeyUZON .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-e2mSFohyeqeyUZON .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-e2mSFohyeqeyUZON .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-e2mSFohyeqeyUZON .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-e2mSFohyeqeyUZON .cluster text{fill:#333;}#mermaid-svg-e2mSFohyeqeyUZON .cluster span{color:#333;}#mermaid-svg-e2mSFohyeqeyUZON div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-e2mSFohyeqeyUZON .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-e2mSFohyeqeyUZON rect.text{fill:none;stroke-width:0;}#mermaid-svg-e2mSFohyeqeyUZON .icon-shape,#mermaid-svg-e2mSFohyeqeyUZON .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-e2mSFohyeqeyUZON .icon-shape p,#mermaid-svg-e2mSFohyeqeyUZON .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-e2mSFohyeqeyUZON .icon-shape .label rect,#mermaid-svg-e2mSFohyeqeyUZON .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-e2mSFohyeqeyUZON .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-e2mSFohyeqeyUZON .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-e2mSFohyeqeyUZON :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 大量请求命中不存在的 key
单个热点 key 过期瞬间并发回源
大量 key 集中过期
发现缓存异常:数据库 QPS 飙升
判断异常类型
缓存穿透
缓存击穿
缓存雪崩
查看 Redis 命中率 keyspace_hits / misses
MONITOR 观察高频不存在的 key
检查是否被恶意遍历 ID
布隆过滤器拦截 / 空值短暂缓存
定位过期热点 key
观察访问是否集中在同一时刻
检查过期时间设置是否合理
互斥锁回源 / 逻辑过期异步重建
扫描 key 的 TTL 分布是否集中
确认是否宕机或批量清空
观察连接池与慢查询指标
过期时间加随机值 / 缓存预热
恢复稳定,持续监控

6.3 搜索引擎

Elasticsearch 是分布式搜索引擎,基于 Lucene 构建,常用于全文检索、日志分析、指标监控等场景。配合 Kibana 和 Logstash 组成 ELK 技术栈,是日志分析领域的主流方案。

7. 构建与工程化工具

7.1 Maven

Maven 是 Java 最经典的构建工具,通过 pom.xml 管理项目依赖、构建生命周期和插件。中央仓库提供了海量开源依赖,是绝大多数 Java 项目的标配。

7.2 Gradle

Gradle 结合了 Maven 的依赖管理和 Ant 的灵活性,采用 Groovy 或 Kotlin DSL 编写构建脚本,构建速度更快,在 Android 开发和部分现代 Java 项目中逐渐流行。

7.3 CI/CD

Jenkins 是最流行的持续集成工具,配合 GitLab CI、GitHub Actions 等,可以实现代码提交后自动构建、测试和部署。

8. 容器化与云原生

随着云原生理念的普及,Java 应用的部署方式也在发生变革。

  • Docker:将应用及其依赖打包为镜像,实现环境一致性
  • Kubernetes:容器编排平台,提供服务发现、弹性伸缩、滚动更新等能力
  • Service Mesh:Istio、Linkerd 等为微服务提供流量管理和安全能力
  • 可观测性:Prometheus + Grafana 监控、SkyWalking 链路追踪、Loki 日志

9. 技术选型建议

面对如此丰富的技术栈,如何选择适合项目的组合?以下是一些实践建议:

  • 中小型单体项目:Spring Boot + MyBatis/JPA + MySQL + Redis,快速交付、易于维护
  • 大型微服务项目:Spring Cloud Alibaba(Nacos + Sentinel + Seata)+ Dubbo/OpenFeign + Kafka + Elasticsearch
  • 高并发场景:重点关注 Redis 缓存、消息队列削峰、分库分表(ShardingSphere)
  • 团队技术积累:选择团队熟悉的技术,避免盲目追新
Java 技术栈选型速查表

为便于快速决策,下表按典型业务场景汇总了推荐的技术组合、核心组件与适用理由:

业务场景 推荐技术组合 核心组件 适用理由
单体应用 Spring Boot + MyBatis/JPA + MySQL + Redis Spring MVC、HikariCP、Spring Data Redis 开发效率高、部署简单,适合中小型项目快速交付与后期维护
微服务 Spring Cloud Alibaba + Dubbo/OpenFeign + Kafka + Elasticsearch Nacos、Sentinel、Seata、Gateway、OpenFeign 提供完整的服务注册发现、配置中心、熔断降级与分布式事务能力,适合大型分布式系统
高并发 Redis + Kafka/RocketMQ + ShardingSphere + Sentinel 布隆过滤器、互斥锁、逻辑过期、分库分表 通过缓存、消息削峰、限流降级与水平扩展,保障系统在高流量下的稳定性
大数据处理 Kafka + Flink/Spark + Elasticsearch + HBase 流批处理引擎、分布式存储、ELK 日志分析 支撑海量数据的采集、实时计算、检索与离线分析,适合日志与指标类业务

速查要点:单体优先 Spring Boot 全家桶;微服务优先 Spring Cloud Alibaba 生态;高并发场景重点投入缓存与消息队列;大数据场景则围绕 Kafka + 计算引擎 + 搜索引擎构建数据链路。

10. 总结

Java 技术栈经过多年发展,已经形成了从基础到应用、从单体到微服务的完整生态体系。Spring Boot 作为当前 Web 开发的主流框架,配合 MyBatis、Redis、消息队列等组件,可以应对绝大多数业务场景;而在大型分布式系统中,Spring Cloud 与 Dubbo 则提供了成熟的服务治理方案。

技术选型没有绝对的"最佳",关键在于结合业务场景、团队能力和系统规模做出合理决策。希望本文能帮助读者建立起 Java 技术栈的整体认知,为后续深入学习和项目实践打下基础。

相关推荐
Escalating_xu2 小时前
【C 语言】深入理解指针(2):数组名、数组传参、二级指针与指针数组
java·c语言·开发语言
郝学胜-神的一滴2 小时前
游戏引擎原理与实践 01:聊聊游戏引擎的前世今生
开发语言·c++·游戏引擎·产品运营·软件工程·产品经理·untiy
景熙55232 小时前
JDBC 详解:从原理到实战(含完整可运行 Demo)
java·spring·tomcat·mybatis·jdbc
程序猿乐锅2 小时前
一文讲透缓存穿透、击穿和雪崩
java·redis·spring·缓存·mybatis
bkspiderx2 小时前
Qt 的消息机制:事件驱动与信号槽的底层逻辑
开发语言·qt·信号槽·事件驱动·qt 的消息机制
xcl09252 小时前
西安同城货运系统源码开发实战 核心功能实现与部署全指南
java·spring boot
晴天的雨.9922 小时前
【C++算法】三数之和
开发语言·c++·算法
pippocao2 小时前
王者荣耀日志组件BqLog为什么这么快之1——高性能实时压缩日志
java
AC赳赳老秦2 小时前
公开 CSV 数据集批量处理实战:用 OpenClaw 高效完成下载、清洗与标准化分析样本生成
java·开发语言·汇编·c++·python·deepseek·openclaw