Java中的分布式(概念说明)

Java中的分布式(概念说明)

1. 分布式的基本概念

1.1 什么是分布式系统?

分布式系统(Distributed System):由多台服务器(或节点)协同工作,对外提供一个整体服务。不同节点之间通过网络通信来协同处理请求或共享数据,相对于「单体应用」而言,可以带来更高的吞吐量、可用性和灵活扩展能力。

1.2 分布式 vs. 单体架构

单体架构

所有业务模块部署在同一应用实例中,垂直扩容(升级服务器硬件)成为主要的扩展方式。优点:开发调试较简单,部署方便。缺点:当应用规模过大时,任何一个模块出现故障或性能瓶颈,都会影响整个系统,并且无法灵活扩容单个模块。

分布式架构

将系统拆分成若干服务或节点,每个节点可以独立运行、独立扩容、独立维护。优点:更好的可扩展性、可靠性,能处理更高并发和数据量。缺点:系统变得复杂,需要处理 网络通信、数据一致性、运维管理 等问题。

类型描述举例水平拆分(微服务)一个系统被拆成多个功能模块,部署在不同节点上订单服务、用户服务、商品服务各自部署垂直扩展(集群)同一个程序部署多份,提高并发能力多个 Tomcat 实例同时跑一个 SpringBoot 项目混合型微服务 + 每个服务本身也集群部署现在主流架构

(1)是一个程序拆分成多个模块,每个模块部署在不同虚拟机上,这叫分布式吗?

✔️ 是的,这是最典型的分布式方式,叫“微服务架构”。

每个模块(比如订单、用户、商品服务)可以独立开发、部署、伸缩,节点之间通过 REST API 或 RPC 调用通信。

(2)如果是一个程序本身部署多个虚拟机实例,这算分布式吗?

✔️ 这叫集群部署,也算分布式的一种,但更准确说是“分布式部署”或者“高可用集群”。

多个实例共享负载,提高并发处理能力和可用性,但它们属于同一个服务模块。

(3)多个虚拟机放在一台云服务器上,还算分布式吗?

✔️是的,从系统架构角度看,只要是多个独立进程/服务协同工作,就算分布式。

但从容错和可用性角度看:

如果多个虚拟机都在一台物理服务器上,不能实现真正的容灾备份;

一旦这台云服务器挂了,所有虚拟机都挂了。

(4)Redis 的哨兵模式可以部署在一个云服务器上吗?

✔️可以,但不推荐。

哨兵模式本意是为了高可用自动故障转移;

如果所有哨兵、主从节点都在一台云服务器,一旦机器故障,高可用机制就失效了;

实际部署建议:至少部署在三台机器(物理或云)上,防止单点故障。

Redis 的部署模式

模式特点说明单机模式开发测试用不适合生产主从复制(Master-Slave)读写分离一主多从,提高读取性能哨兵模式(Sentinel)自动故障转移监控主节点,自动主从切换集群模式(Cluster)真正分布式多主多从,分片存储,高可用、高扩展

(5)数据库的分库也能部署在一个云服务器上吗?

✔️能,但也不推荐。

分库是为了提升性能、解决单点瓶颈;

如果多个库都在同一台机器上,机器的CPU、内存、磁盘IO是共享的,无法做到真正的扩展与隔离;

一旦这台机器宕机,所有库都不可用。

1.3 分布式系统的核心挑战

数据一致性:多节点同时修改同一数据,如何保证最终数据正确?可用性:某个节点失败不会影响整体服务。可扩展性:需要随业务增长快速增加节点处理能力。网络延迟与可靠性:网络抖动、分区故障等异常场景必须做好应对策略(如重试、降级)。系统复杂度:日志监控、调试、部署都更加繁琐。

2. 分布式架构的主要组成部分

Spring Boot 下的分布式架构通常包含以下几个关键部分:

组件作用分布式服务(微服务)业务拆分,避免单体架构的复杂性分布式缓存(Redis)提高查询性能,减少数据库压力分布式锁(Redis/Zookeeper)解决多个节点同时修改数据的一致性问题分布式事务(Seata)保障数据一致性,避免并发冲突分布式消息队列(RabbitMQ/Kafka)异步处理任务,提升系统吞吐量服务注册与发现(Nacos/Eureka)让服务可以自动发现彼此,不需要手动配置分布式配置中心(Nacos/Spring Cloud Config)统一管理配置,提高可维护性负载均衡(Nginx/Spring Cloud Gateway)把请求合理分配到多个服务实例分布式任务调度(ElasticJob/Xxl-Job)让多个服务器协同执行定时任务

3. Spring Boot 分布式架构的实现方式

Redis 提供缓存和分布式锁,提升性能Nacos/Eureka 让微服务可以互相发现MQ 让服务之间异步通信,减少耦合Seata 保证分布式事务一致性负载均衡 + API 网关 让服务更高效

3.1 分布式服务(微服务)

微服务(Microservices)是 架构设计理念,它强调将一个大型应用拆分成多个 独立部署、独立运行 的小型服务,每个服务负责特定的业务逻辑。是否是微服务 不取决于是否运行在 同一台云服务器,而取决于它们是否是独立的服务实例。

微服务的特点

独立运行:不同服务可以分开部署,即使运行在同一台云服务器上,也属于不同的微服务。独立进程:通常一个微服务运行在一个 独立的 JVM(不同的 Java 进程),而不是多个模块共享同一个 JVM。独立数据库(推荐):但不强制,多个微服务可以共享一个数据库。

1. 微服务必须部署在不同的服务器上才算微服务吗?不是,微服务可以部署在同一台服务器上,只要它们是独立的进程(不同的 JVM 实例)。

例如:

order-service.jar (端口 8081)stock-service.jar (端口 8082)payment-service.jar (端口 8083)

这些都是微服务,即使它们都在同一台服务器上运行。

2. 只要是同一个 JVM 里的多个模块,就不能算是微服务?

是的,不能算微服务,如果多个模块运行在同一个 JVM(比如 Spring Boot 的 module1、module2 在同一个 application 里),它们更像是单体应用的多个业务模块。微服务的关键是独立部署和独立进程。

3. 多个微服务共享同一个数据库,还叫微服务吗?

是的,仍然可以叫微服务,但这会带来分布式事务问题。推荐的微服务架构 是 每个微服务独立数据库,但现实中,很多公司还是会让多个微服务共享数据库,避免数据一致性问题。共享数据库的微服务 仍然是微服务,但会让事务管理变得复杂。

含义:把一个庞大的单体应用拆分成若干个服务,每个服务只负责一个“相对独立的业务领域或功能”,称之为“微服务”。

示例:

UserService:专注处理用户登录、注册、用户信息管理OrderService:负责订单的创建、查询、支付信息对接ProductService:管理产品、库存、定价等PaymentService:处理支付渠道、账务、对账逻辑

好处:

解耦:每个服务都可独立部署、升级,互不影响。独立扩展:哪块业务压力大就扩容对应服务的节点,而不是整合到一起。技术栈灵活:不同服务甚至可以用不同的语言或框架。

在 Spring Boot 中如何实现微服务?

Spring Boot + Spring Cloud

Spring Cloud 提供了微服务生态,包括:

服务注册与发现(Eureka, Nacos, Consul),让各微服务在一个注册中心上登记并获取彼此的地址负载均衡(Ribbon 或 Spring Cloud LoadBalancer),在调用某个微服务时自动从多个实例中选一台服务调用(Feign),通过 HTTP/REST 的方式去请求其他微服务熔断、限流(Hystrix, Sentinel),在调用失效时防止雪崩网关(Spring Cloud Gateway),统一处理路由、鉴权、流量控制

服务间通信方式

HTTP/REST:最常见的形式,每个微服务暴露 RESTful API,其他微服务通过 HTTP 调用。RPC:部分场景需要高性能的调用,可以使用 RPC(例如 Dubbo、gRPC),减少网络开销,提升效率。消息队列:如果是异步调用场景,还会结合 MQ 来实现解耦与异步化。

3.2 服务注册与发现(Service Discovery)

当我们有了多个微服务之后,问题来了:如何让它们相互找到对方?

传统做法:在配置文件里写死每个服务的地址。但一旦服务集群扩容或 IP 地址变动,就要重新修改配置,非常麻烦。分布式做法:服务注册与发现。各个微服务在启动时,自动向“注册中心”报到,注册中心会保存当前可用的服务实例列表。其他服务要调用它时,只需要从注册中心查到目标服务的地址就行。

常见的注册中心:

Eureka(Netflix OSS)Nacos(阿里巴巴开源,功能更强大,也能做配置中心)Zookeeper(Apache 基金会项目,也能做服务注册,但更多用于分布式协调)

在 Spring Boot + Spring Cloud 中配置服务注册发现,大致流程:

在 pom.xml 中引入对应的依赖(例如 spring-cloud-starter-alibaba-nacos-discovery)。在 application.yml 中配置好注册中心地址 server-addr: localhost:8848 等。启动时,服务会自动注册到 Nacos(或其他注册中心)。

3.3 分布式配置中心

配置中心 主要解决的是“在分布式环境中,如何统一管理各个微服务的配置”,避免每个服务都各自持有不同的配置文件,难以维护。

Spring Cloud Config:早期常用的配置中心,基于 Git 存储配置Nacos Config:Nacos 同时提供注册发现和配置管理Apollo(携程开源)或 Disconf 等也可以

好处:

统一管理:所有配置信息都在一个地方(配置中心),修改后可实时生效。动态更新:微服务在运行时能监控到配置变动,自动刷新,无需重启。区分环境:如 DEV, TEST, PROD 环境对应不同配置。

3.4 分布式缓存(Redis 等)

在分布式环境下,数据库通常成为性能瓶颈。为减少对数据库的直接访问和压力,需要一个 高性能的分布式缓存。Redis 是最常用的选择,它具有以下优势:

内存存储,读写速度快。丰富的数据结构(字符串、哈希、列表、集合、有序集合等)。支持 主从复制、Cluster 集群,适合分布式部署。常用于 缓存热点数据、分布式 Session、分布式锁 等场景。

使用 Redis 的关键点:

设计 合理的缓存键(key),比如 product:detail:{productId}。设置 过期时间,避免缓存数据与数据库数据长期不一致。考虑 缓存穿透、缓存雪崩、缓存击穿 等问题,并进行对应的防护(如 Bloom Filter, 加互斥锁, 合理限流等)。

3.5 分布式锁

在分布式环境中,如果多个节点同时对同一个资源进行写操作,就容易出现数据不一致或并发冲突。因此,需要一种分布式锁来保证 在同一时间,只有一个节点可以获取锁,进行资源操作。

常见方案:

Redis 分布式锁

使用 SETNX(set if not exist) + EXPIRE 或 SET key value NX PX time 命令实现。注意要设置超时时间,避免锁无法释放导致死锁。也要考虑锁的续约和解锁时的原子性操作(Lua 脚本),以避免误删他人的锁。

Zookeeper 分布式锁

利用 ZK 的临时顺序节点来竞争锁,监听事件,一旦获取锁的节点断开连接,就自动删除节点,其他节点立即感知到并可重新竞争。

示例:基于 Redis 的简易分布式锁代码(示例性,不是完整生产级)

String lockKey = "lock:order";

String lockVal = UUID.randomUUID().toString();

// 尝试加锁

Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, lockVal, 10, TimeUnit.SECONDS);

if (Boolean.TRUE.equals(success)) {

try {

// 执行业务逻辑

} finally {

// 解锁时,先判断锁是否是自己加的

String val = redisTemplate.opsForValue().get(lockKey);

if (lockVal.equals(val)) {

redisTemplate.delete(lockKey);

}

}

}

3.6 分布式事务

在单体应用中,事务只需要依赖数据库的本地事务(ACID)即可。但在分布式系统中,可能一个操作需要 跨多个微服务、跨多个数据库,这时就出现了 分布式事务 问题:

例如,在电商场景下,创建订单 时,要同时扣减库存、生成支付记录等,这些操作都在不同微服务里完成;如果其中某一步出错,就需要回滚之前的操作。

3.6.1 强一致性(Strict Consistency)

定义: 保证数据在任何时刻都是一致的,即所有操作要么全部成功,要么全部失败。没有数据不一致的窗口期。

代表方案: 两阶段提交(2PC) 和它的变体(如 3PC)。

工作原理:

准备阶段: 一个协调者向所有参与者(如数据库、缓存)发起事务准备请求。所有参与者执行事务操作,但不提交,并锁定相关资源。

提交/回滚阶段: 如果所有参与者都成功准备,协调者就发起提交请求;如果有任何一个参与者失败,协调者就发起回滚请求。

为什么在互联网企业中 “几乎不用”?

性能瓶颈: 整个事务过程是同步阻塞的。所有参与者在等待协调者指令时,会长时间锁定资源,严重降低系统吞吐量。

可用性低: 存在单点故障。如果协调者在关键时刻宕机,参与者将无法收到最终指令,导致资源被永久锁定,形成“死锁”。

扩展性差: 事务的成功与否取决于最慢的那个参与者,难以水平扩展。

3.6.2 最终一致性(Eventual Consistency)

定义: 不追求数据的实时一致性,而是允许数据在短时间内处于不一致状态,但最终会通过某种机制达到一致。这是互联网企业的主流选择,因为它在高并发、高可用场景下更具优势。

核心思想: 通过异步补偿的方式,确保所有操作最终都会成功。

以下是两种最常用且最公认的实现方式:

(1)基于本地消息表(或外部消息队列)

原理:

业务服务将数据库操作和发送消息放在同一个本地事务中。

如果数据库操作成功,一条记录(消息)会同时写入本地的“消息表”中,代表“待发送”。

一个独立的后台任务(或者消费者服务)会定期扫描这张消息表,将待发送的消息发送到消息队列中。

消息队列中的消息被其他服务消费,从而完成后续操作。

优点:

高吞吐量: 本地事务非常快,不依赖于远程调用,性能极高。

高可靠性: 消息是持久化到数据库的,即使发送失败,也可以通过重试机制来保证最终发送成功,数据不会丢失。

解耦: 业务逻辑和数据同步完全分离,服务间相互独立。

局限性: 额外维护一张消息表,增加了数据库的负担。

(2)基于事务性消息(如 RocketMQ 的事务消息)

原理:

业务服务向消息队列发送一个“预备消息”,该消息对消费者不可见。

消息队列返回成功后,业务服务执行本地数据库事务。

本地事务成功后,业务服务向消息队列发送“确认消息”。消息队列将预备消息变为可见,消费者可以消费。

如果本地事务失败,业务服务发送“回滚消息”,消息队列会丢弃该预备消息。

优点:

原子性: 保证了本地事务和消息发送的原子性,开发者无需维护本地消息表。

简化开发: 复杂的消息一致性逻辑被封装在消息中间件中,极大简化了开发。

流行度: 这是目前互联网企业最主流的分布式事务解决方案之一。

(3)TCC (Try-Confirm-Cancel)

原理: 适用于对数据隔离性要求高的场景,例如扣减库存、账户扣款等。

Try 阶段: 尝试执行,对所有资源进行预留(而不是直接扣减),并锁定这些资源。

Confirm 阶段: 如果所有参与者的 Try 都成功,则发起 Confirm 操作,真正提交事务并扣减资源。

Cancel 阶段: 如果任何一个参与者的 Try 失败,则发起 Cancel 操作,回滚所有预留资源。

优点:

隔离性好: 通过预留机制解决了资源竞争问题,避免了超卖等并发问题。

数据最终一致: 最终通过 Confirm 或 Cancel 来保证数据一致性。

局限性:

开发成本高: 每个业务逻辑都需要实现 Try、Confirm、Cancel 三个方法,代码复杂。

强依赖于业务: 业务逻辑必须可逆。

流行度: 在金融支付、电商交易等核心业务场景中非常重要,是不可或缺的补充方案。

3.6.3 总结

2PC: 理论上完美,但实践中几乎不用,因其牺牲了性能和可用性。

最终一致性: 互联网企业的绝对主流。

本地消息表 / 事务消息: 最常用,用于绝大多数需要异步同步的业务场景。

TCC: 不可或缺,用于对资源隔离性要求极高的核心业务。

3.7 分布式消息队列

消息队列 (Message Queue) 用于解耦系统、异步处理和削峰填谷。常见的 MQ 方案有:

RabbitMQ:轻量级,支持事务与确认机制,适合传统企业应用以及对消息可靠性要求高的场景。Apache Kafka:高吞吐,大规模数据流处理的“事实标准”,更多用于大数据、日志收集、流式处理等场景。RocketMQ:阿里开源的分布式消息中间件,和 Kafka 类似,也有较高的吞吐。

MQ 的作用:

解耦:比如,用户下单后,需要发送优惠券、通知物流、通知商家等,而如果所有这些操作都放在下单接口里,会导致耦合过高;使用 MQ,每个消费者服务负责监听消息并执行相应的业务逻辑。削峰填谷:在高峰时段,订单系统可以快速写入消息队列,后台处理系统再慢慢消费,避免直接压垮数据库或其他服务。异步:不需要同步等待消息处理完成,加快用户请求的响应速度。

3.8 API 网关与负载均衡

当服务拆分越来越多,我们往往需要一个统一的 网关 来管理请求:

服务网关(如 Spring Cloud Gateway、Nginx、Kong):

统一对外提供访问入口进行路由分发,鉴权,限流,监控等在微服务复杂时,可以屏蔽内部服务接口的变化,对外提供稳定的 API。

负载均衡:

当某个微服务有多个实例时,网关或负载均衡器需要把请求分散到各个实例上,避免其中一个实例被打满。常见方式:Nginx 反向代理 或 Spring Cloud Ribbon (新版 Spring Cloud LoadBalancer)都可实现负载均衡。

四、整体流程与示例

4.1 典型电商微服务调用链

以 电商订单 流程为例,来看看分布式系统下的一般调用。

用户 访问 API 网关(或 Nginx),请求 /api/order/create 接口。网关解析路由规则,将请求转发给 OrderService。OrderService 调用 UserService 检查用户信息(比如积分、等级等)。OrderService 调用 ProductService 检查库存、扣减库存;同时查询商品价格。OrderService 写入订单数据库,本地事务或分布式事务处理。OrderService 向 MQ 发送消息,用于通知其他服务(如物流、积分系统等)。MQ 的消费者(如 LogisticsService)消费消息并执行下一步操作。

在这个过程中,会用到:

服务注册中心(保证 OrderService 能动态发现 ProductService 的地址)分布式缓存(可能在 OrderService、ProductService 的查询环节做缓存)分布式锁(避免多次重复扣减库存)分布式事务(如要保证扣库存与下单一致)消息队列(通知其他异步任务)

4.2 部署模式

开发/测试环境:一般都是在本地 Docker 或者虚拟机里把注册中心、MQ、Redis、数据库等组件跑起来即可。生产环境:会把各个服务独立部署在多台服务器(或容器云)上:

注册中心、配置中心(Nacos/Consul/Eureka)集群Redis 高可用集群(主从+哨兵模式或 Redis Cluster)MQ 集群(RabbitMQ 集群或 Kafka 集群)分布式文件系统(如 MinIO, FastDFS, OSS 等)后端数据存储(MySQL 或者多分片数据库),需要做读写分离或分库分表若干微服务集群(UserService、OrderService...),通过容器编排(Kubernetes 或 Docker Swarm)进行管理

相关推荐

森林灵敏度怎么设置舒服
Bet体育365第二次提款要多久

森林灵敏度怎么设置舒服

📅 07-28 👁️ 3947
被玻璃划伤多久能好
365bet手机版下载

被玻璃划伤多久能好

📅 07-26 👁️ 1945
angelababy演的电影
365bet手机版下载

angelababy演的电影

📅 08-19 👁️ 6858
乌龟一般吃什么?了解乌龟的饮食习惯与偏好
365bet手机版下载

乌龟一般吃什么?了解乌龟的饮食习惯与偏好

📅 07-24 👁️ 7907
海尔(Haier)全国官方售后服务点24小时热线400号码
Bet体育365第二次提款要多久

海尔(Haier)全国官方售后服务点24小时热线400号码

📅 08-06 👁️ 9555
逆战最新英文歌曲名 新出的英文歌曲名是什么
Bet体育365第二次提款要多久

逆战最新英文歌曲名 新出的英文歌曲名是什么

📅 08-05 👁️ 2197
2025最全戴爾外星人Alienware美國與中國售後服務指南(售後網點及電話+全球聯保+保修期+維修價格)  戴爾售後服務政策
SDE是什么职位?
365bet手机版下载

SDE是什么职位?

📅 09-18 👁️ 1125
性别与健康
mobile365体育投注官网

性别与健康

📅 10-01 👁️ 9591