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

1. 分布式的基本概念

1.1 什么是分布式系统?

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

1.2 分布式 vs. 单体架构

  • 单体架构

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

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

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 分布式服务(微服务)

  • 含义:把一个庞大的单体应用拆分成若干个服务,每个服务只负责一个“相对独立的业务领域或功能”,称之为“微服务”。
    • 示例:
      • UserService:专注处理用户登录、注册、用户信息管理
      • OrderService:负责订单的创建、查询、支付信息对接
      • ProductService:管理产品、库存、定价等
      • PaymentService:处理支付渠道、账务、对账逻辑
  • 好处
    1. 解耦:每个服务都可独立部署、升级,互不影响。
    2. 独立扩展:哪块业务压力大就扩容对应服务的节点,而不是整合到一起。
    3. 技术栈灵活:不同服务甚至可以用不同的语言或框架。

在 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 中配置服务注册发现,大致流程:

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

3.3 分布式配置中心

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

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

好处:

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

3.4 分布式缓存(Redis 等)

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

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

使用 Redis 的关键点:

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

3.5 分布式锁

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

常见方案:

  • Redis 分布式锁
    • 使用 SETNX(set if not exist) + EXPIRESET 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)即可。但在分布式系统中,可能一个操作需要 跨多个微服务、跨多个数据库,这时就出现了 分布式事务 问题:

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

常见分布式事务方案:

  • 2PC(两阶段提交):协调者告诉所有参与者先预提交,然后再统一提交或回滚。实现复杂,性能损耗大,适合对一致性要求极高的场景。
  • TCC(Try-Confirm-Cancel):业务系统自己实现各个操作的 “Try, Confirm, Cancel”,实现灵活,但开发成本高。
  • Seata:阿里开源的分布式事务框架,提供 AT 模式(对 JDBC 层做代理),也提供 TCC 等模式。

Seata 示例

@GlobalTransactional
public void placeOrder(Order order) {// 跨服务调用inventoryService.decreaseStock(order.getProductId(), order.getQuantity());paymentService.processPayment(order);orderMapper.insert(order);// Seata 会在这里把整个调用过程进行管理,可做到成功或回滚
}

在执行过程中,如果其中一个调用报错,Seata 就会通知其他服务进行回滚。


3.7 分布式消息队列

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

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

MQ 的作用

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

3.8 API 网关与负载均衡

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

  • 服务网关(如 Spring Cloud GatewayNginxKong):
    • 统一对外提供访问入口
    • 进行路由分发,鉴权,限流,监控等
    • 在微服务复杂时,可以屏蔽内部服务接口的变化,对外提供稳定的 API。
  • 负载均衡
    • 当某个微服务有多个实例时,网关或负载均衡器需要把请求分散到各个实例上,避免其中一个实例被打满。
    • 常见方式:Nginx 反向代理Spring Cloud Ribbon (新版 Spring Cloud LoadBalancer)都可实现负载均衡。

四、整体流程与示例

4.1 典型电商微服务调用链

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

  1. 用户 访问 API 网关(或 Nginx),请求 /api/order/create 接口。
  2. 网关解析路由规则,将请求转发给 OrderService
  3. OrderService 调用 UserService 检查用户信息(比如积分、等级等)。
  4. OrderService 调用 ProductService 检查库存、扣减库存;同时查询商品价格。
  5. OrderService 写入订单数据库,本地事务或分布式事务处理。
  6. OrderServiceMQ 发送消息,用于通知其他服务(如物流、积分系统等)。
  7. 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)进行管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/69964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单了解应用层DNS协议

DNS(Domain Name System)协议是用于将人类可读的域名(如www.example.com)转换为计算机可识别的IP地址(如192.0.2.1)的系统。 TCP/IP中使用IP地址来确定网络上的一台主机,但是IP地址不方便人们记…

Windows 找不到文件gpedit.msc,没有组策略编辑器,解决办法附上

windows10和11都通用。是不是有人告诉你家庭版本没有gpedit.msc,没有组策略编辑器?这压根就是某软玩的小把戏。Win10/11家庭版可通过修改文件后缀新建bat脚本,添加组策略包,以管理员身份运行后,输入gpedit.msc即可打开…

“PEP 8: W292 no newline at end of file“报错 IntelliJ IDEA自动添加空行问题

"PEP 8: W292 no newline at end of file"报错 IntelliJ IDEA自动添加空行问题 在使用IntelliJ IDEA的过程中,经常会发现不管是对于代码文件或者纯文本文件,在保存时中会在文件末尾加上一个空行,提交GIT对比检查时,总是…

线性数据结构解密:数组的定义、操作与实际应用

系列文章目录 01-从零开始掌握Python数据结构:提升代码效率的必备技能! 02-算法复杂度全解析:时间与空间复杂度优化秘籍 03-线性数据结构解密:数组的定义、操作与实际应用 文章目录 系列文章目录前言一、数组的定义与特点1.1 数组…

docker-compose.yml 详细教学

目录 文件结构 版本 服务(Services) 示例 文件结构 docker-compose.yml 文件通常包含以下几部分: version:指定 Docker Compose 文件的版本。services:定义应用程序中的服务,每个服务对应一个容器。vo…

spring 学习 (注解)

目录 前言 常用的注解 须知 1 Conponent注解 demo(案例) 2 ControllerServiceRepository demo(案例) 3 ScopeLazyPostConstructPreDestroy demo(案例) 4 ValueAutowiredQualifierResource demo(案例) 5 Co…

【设计模式】【行为型模式】迭代器模式(Iterator)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD 🔥 2025本人正在沉淀中… 博客更新速度 👍 欢迎点赞、收藏、关注,跟上我的更新节奏 🎵 当你的天空突…

C语言-------结构体(1)

数据类型 (1)基本数据类型 整型 浮点型 字符型 (2)构造类型 数组 结构体 结构体: 用来处理,现实生活中,更复杂的数据的描述 用来 描述复杂数据的 一种用户自定义的数…

【centos7】安装redis

rpm链接:http://rpms.famillecollet.com/enterprise/remi-release-7.rpm 下载remi源 wget http://rpms.famillecollet.com/enterprise/remi-release-7.rpm 安装remi源 rpm -ivh remi-release-7.rpm 查找remi源中redis的版本 yum --enablereporemi list redis …

获取整十分钟时间戳的多种方法详解

在数据处理、定时任务等场景中,经常需要获取当前时间的整十分钟时间戳。本文将介绍两种常用方法,并拓展其他实现思路,帮助你灵活应对不同需求。 方法一:datetime模块计算法 原理:通过截断分钟数实现时间对齐。 代码实…

AcWing 798. 差分矩阵

题目来源: 找不到页面 - AcWing 题目内容: 输入一个 n 行 m 列的整数矩阵,再输入 q 个操作,每个操作包含五个整数 x1,y1,x2,y2,c,其中 (x1,y1) 和 (x2,y2)表示一个子矩阵的左上角坐标和右下角坐标。 每个操作都要将…

【Python爬虫①】专栏开篇:夯实Python基础

【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取&#xff…

数仓:核心概念,数仓系统(ETL,数仓分层,数仓建模),数仓建模方法(星型模型,雪花模型,星座模型)和步骤

数仓建模的核心概念 事实表(Fact Table): 存储业务过程的度量值(如销售额、订单数量等)。 通常包含外键,用于关联维度表。 维度表(Dimension Table): 存储描述性信息&…

【靶机渗透实战】AI:WEB:1

靶机下载官网AI: Web: 1 ~ VulnHub 靶机描述 Difficulty: IntermediateNetwork: DHCP (Automatically assign)Network Mode: NATThis box is designed to test skills of penetration tester. The goal is simple. Get flag from /root/flag.txt. Enumerate the box, get low…

MATLAB中contains函数用法

目录 语法 说明 示例 查找文本 使用模式进行搜索 匹配列表中的任何文本 忽略大小写 确定字符向量中是否包含子字符串 contains函数的功能是确定字符串中是否有模式。 语法 TF contains(str,pat) TF contains(str,pat,IgnoreCase,true) 说明 如果 str 包含指定的模…

【limit 1000000,10 加载很慢该怎么优化?】

在 SQL 数据库中,使用 LIMIT 子句进行分页查询时,如果偏移量(offset)很大,查询性能可能会变得非常差。 这是因为数据库需要扫描和跳过大量的记录才能到达所需的起始位置,然后再取出所需的记录数。 例如,LIMIT 1000000, 10 表示跳过前 100 万条记录,然后取接下来的 10…

Python基于 Flask 创建简单Web服务并接收文件

在全部网口上创建web服务, 监听8080端口关闭debug模式GET时返回HTML界面, 用于提交文件POST到 /upload 时, 从接收的 file 变量中读取文件, 并传递给 opencv 解析为 image 对象 from flask import Flask, request, redirect, url_for import os import cv2 import numpy impor…

zookeeper的zkCli.sh登录server报错【无法正常使用】

如果zookeeper使用zkCli.sh登录的时候老是频闪,没有办法正常使用,大概率是与java的版本不兼容 [zookeeperPostgreSQL bin]$ ./zkCli.sh Connecting to localhost:2181 2025-02-05 19:23:53,933 [myid:] - INFO [main:Environment100] - Client envir…

初始JavaEE篇 —— Spring Web MVC入门(下)

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程程(ಥ_ಥ)-CSDN博客 所属专栏:JavaEE 初始JavaEE篇 —— Spring Web MVC入门(上) 在上篇文章中,我们学习了一些注解的使用、Postman模…

【verilog】函数clogb2的解读

最近经常看到clogb2函数。 源代码如下所示。 function integer clogb2; input [31:0] value; reg [31:0] tmp; reg [31:0] rt; begin tmp value - 1; for (rt 0; tmp > 0; rt rt 1) tmp tmp >> 1; clogb2 rt; end endfunction 这个函数的意思是:这段…