Java中的分布式概念說明
1. 分布式的基本概念
1.1 什么是分布式系統(tǒng)?
- 分布式系統(tǒng)(Distributed System):由多臺服務器(或節(jié)點)協(xié)同工作,對外提供一個整體服務。
- 不同節(jié)點之間通過網絡通信來協(xié)同處理請求或共享數據,相對于「單體應用」而言,可以帶來更高的吞吐量、可用性和靈活擴展能力。
1.2 分布式 vs. 單體架構
- 單體架構
- 所有業(yè)務模塊部署在同一應用實例中,垂直擴容(升級服務器硬件)成為主要的擴展方式。
- 優(yōu)點:開發(fā)調試較簡單,部署方便。
- 缺點:當應用規(guī)模過大時,任何一個模塊出現(xiàn)故障或性能瓶頸,都會影響整個系統(tǒng),并且無法靈活擴容單個模塊。
- 分布式架構
- 將系統(tǒng)拆分成若干服務或節(jié)點,每個節(jié)點可以獨立運行、獨立擴容、獨立維護。
- 優(yōu)點:更好的可擴展性、可靠性,能處理更高并發(fā)和數據量。
- 缺點:系統(tǒng)變得復雜,需要處理 網絡通信、數據一致性、運維管理 等問題。
| 類型 | 描述 | 舉例 |
|---|---|---|
| 水平拆分(微服務) | 一個系統(tǒng)被拆成多個功能模塊,部署在不同節(jié)點上 | 訂單服務、用戶服務、商品服務各自部署 |
| 垂直擴展(集群) | 同一個程序部署多份,提高并發(fā)能力 | 多個 Tomcat 實例同時跑一個 SpringBoot 項目 |
| 混合型 | 微服務 + 每個服務本身也集群部署 | 現(xiàn)在主流架構 |
(1)是一個程序拆分成多個模塊,每個模塊部署在不同虛擬機上,這叫分布式嗎?
?? 是的,這是最典型的分布式方式,叫“微服務架構”。
每個模塊(比如訂單、用戶、商品服務)可以獨立開發(fā)、部署、伸縮,節(jié)點之間通過 REST API 或 RPC 調用通信。
(2)如果是一個程序本身部署多個虛擬機實例,這算分布式嗎?
?? 這叫集群部署,也算分布式的一種,但更準確說是“分布式部署”或者“高可用集群”。
多個實例共享負載,提高并發(fā)處理能力和可用性,但它們屬于同一個服務模塊。
(3)多個虛擬機放在一臺云服務器上,還算分布式嗎?
??是的,從系統(tǒng)架構角度看,只要是多個獨立進程/服務協(xié)同工作,就算分布式。
但從容錯和可用性角度看:
- 如果多個虛擬機都在一臺物理服務器上,不能實現(xiàn)真正的容災備份;
- 一旦這臺云服務器掛了,所有虛擬機都掛了。
(4)Redis 的哨兵模式可以部署在一個云服務器上嗎?
??可以,但不推薦。
- 哨兵模式本意是為了高可用自動故障轉移;
- 如果所有哨兵、主從節(jié)點都在一臺云服務器,一旦機器故障,高可用機制就失效了;
- 實際部署建議:至少部署在三臺機器(物理或云)上,防止單點故障。
Redis 的部署模式
| 模式 | 特點 | 說明 |
|---|---|---|
| 單機模式 | 開發(fā)測試用 | 不適合生產 |
| 主從復制(Master-Slave) | 讀寫分離 | 一主多從,提高讀取性能 |
| 哨兵模式(Sentinel) | 自動故障轉移 | 監(jiān)控主節(jié)點,自動主從切換 |
| 集群模式(Cluster) | 真正分布式 | 多主多從,分片存儲,高可用、高擴展 |
(5)數據庫的分庫也能部署在一個云服務器上嗎?
??能,但也不推薦。
- 分庫是為了提升性能、解決單點瓶頸;
- 如果多個庫都在同一臺機器上,機器的CPU、內存、磁盤IO是共享的,無法做到真正的擴展與隔離;
- 一旦這臺機器宕機,所有庫都不可用。
1.3 分布式系統(tǒng)的核心挑戰(zhàn)
- 數據一致性:多節(jié)點同時修改同一數據,如何保證最終數據正確?
- 可用性:某個節(jié)點失敗不會影響整體服務。
- 可擴展性:需要隨業(yè)務增長快速增加節(jié)點處理能力。
- 網絡延遲與可靠性:網絡抖動、分區(qū)故障等異常場景必須做好應對策略(如重試、降級)。
- 系統(tǒng)復雜度:日志監(jiān)控、調試、部署都更加繁瑣。
2. 分布式架構的主要組成部分
Spring Boot 下的分布式架構通常包含以下幾個關鍵部分:
| 組件 | 作用 |
|---|---|
| 分布式服務(微服務) | 業(yè)務拆分,避免單體架構的復雜性 |
| 分布式緩存(Redis) | 提高查詢性能,減少數據庫壓力 |
| 分布式鎖(Redis/Zookeeper) | 解決多個節(jié)點同時修改數據的一致性問題 |
| 分布式事務(Seata) | 保障數據一致性,避免并發(fā)沖突 |
| 分布式消息隊列(RabbitMQ/Kafka) | 異步處理任務,提升系統(tǒng)吞吐量 |
| 服務注冊與發(fā)現(xiàn)(Nacos/Eureka) | 讓服務可以自動發(fā)現(xiàn)彼此,不需要手動配置 |
| 分布式配置中心(Nacos/Spring Cloud Config) | 統(tǒng)一管理配置,提高可維護性 |
| 負載均衡(Nginx/Spring Cloud Gateway) | 把請求合理分配到多個服務實例 |
| 分布式任務調度(ElasticJob/Xxl-Job) | 讓多個服務器協(xié)同執(zhí)行定時任務 |
3. Spring Boot 分布式架構的實現(xiàn)方式
- Redis 提供緩存和分布式鎖,提升性能
- Nacos/Eureka 讓微服務可以互相發(fā)現(xiàn)
- MQ 讓服務之間異步通信,減少耦合
- Seata 保證分布式事務一致性
- 負載均衡 + API 網關 讓服務更高效
3.1 分布式服務(微服務)
微服務(Microservices)是 架構設計理念,它強調將一個大型應用拆分成多個 獨立部署、獨立運行 的小型服務,每個服務負責特定的業(yè)務邏輯。是否是微服務 不取決于是否運行在 同一臺云服務器,而取決于它們是否是獨立的服務實例。
微服務的特點
- 獨立運行:不同服務可以分開部署,即使運行在同一臺云服務器上,也屬于不同的微服務。
- 獨立進程:通常一個微服務運行在一個 獨立的 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里),它們更像是單體應用的多個業(yè)務模塊。 - 微服務的關鍵是獨立部署和獨立進程。
3. 多個微服務共享同一個數據庫,還叫微服務嗎?
- 是的,仍然可以叫微服務,但這會帶來分布式事務問題。
- 推薦的微服務架構 是 每個微服務獨立數據庫,但現(xiàn)實中,很多公司還是會讓多個微服務共享數據庫,避免數據一致性問題。
- 共享數據庫的微服務 仍然是微服務,但會讓事務管理變得復雜。
- 含義:把一個龐大的單體應用拆分成若干個服務,每個服務只負責一個“相對獨立的業(yè)務領域或功能”,稱之為“微服務”。
- 示例:
UserService:專注處理用戶登錄、注冊、用戶信息管理OrderService:負責訂單的創(chuàng)建、查詢、支付信息對接ProductService:管理產品、庫存、定價等PaymentService:處理支付渠道、賬務、對賬邏輯
- 示例:
- 好處:
- 解耦:每個服務都可獨立部署、升級,互不影響。
- 獨立擴展:哪塊業(yè)務壓力大就擴容對應服務的節(jié)點,而不是整合到一起。
- 技術棧靈活:不同服務甚至可以用不同的語言或框架。
在 Spring Boot 中如何實現(xiàn)微服務?
- Spring Boot + Spring Cloud
- Spring Cloud 提供了微服務生態(tài),包括:
- 服務注冊與發(fā)現(xiàn)(Eureka, Nacos, Consul),讓各微服務在一個注冊中心上登記并獲取彼此的地址
- 負載均衡(Ribbon 或 Spring Cloud LoadBalancer),在調用某個微服務時自動從多個實例中選一臺
- 服務調用(Feign),通過 HTTP/REST 的方式去請求其他微服務
- 熔斷、限流(Hystrix, Sentinel),在調用失效時防止雪崩
- 網關(Spring Cloud Gateway),統(tǒng)一處理路由、鑒權、流量控制
- 服務間通信方式
- HTTP/REST:最常見的形式,每個微服務暴露 RESTful API,其他微服務通過 HTTP 調用。
- RPC:部分場景需要高性能的調用,可以使用 RPC(例如 Dubbo、gRPC),減少網絡開銷,提升效率。
- 消息隊列:如果是異步調用場景,還會結合 MQ 來實現(xiàn)解耦與異步化。
3.2 服務注冊與發(fā)現(xiàn)(Service Discovery)
當我們有了多個微服務之后,問題來了:如何讓它們相互找到對方?
- 傳統(tǒng)做法:在配置文件里寫死每個服務的地址。但一旦服務集群擴容或 IP 地址變動,就要重新修改配置,非常麻煩。
- 分布式做法:服務注冊與發(fā)現(xiàn)。各個微服務在啟動時,自動向“注冊中心”報到,注冊中心會保存當前可用的服務實例列表。其他服務要調用它時,只需要從注冊中心查到目標服務的地址就行。
常見的注冊中心:
- Eureka(Netflix OSS)
- Nacos(阿里巴巴開源,功能更強大,也能做配置中心)
- Zookeeper(Apache 基金會項目,也能做服務注冊,但更多用于分布式協(xié)調)
在 Spring Boot + Spring Cloud 中配置服務注冊發(fā)現(xiàn),大致流程:
- 在
pom.xml中引入對應的依賴(例如spring-cloud-starter-alibaba-nacos-discovery)。 - 在
application.yml中配置好注冊中心地址server-addr: localhost:8848等。 - 啟動時,服務會自動注冊到 Nacos(或其他注冊中心)。
3.3 分布式配置中心
配置中心 主要解決的是“在分布式環(huán)境中,如何統(tǒng)一管理各個微服務的配置”,避免每個服務都各自持有不同的配置文件,難以維護。
- Spring Cloud Config:早期常用的配置中心,基于 Git 存儲配置
- Nacos Config:Nacos 同時提供注冊發(fā)現(xiàn)和配置管理
- Apollo(攜程開源)或 Disconf 等也可以
好處:
- 統(tǒng)一管理:所有配置信息都在一個地方(配置中心),修改后可實時生效。
- 動態(tài)更新:微服務在運行時能監(jiān)控到配置變動,自動刷新,無需重啟。
- 區(qū)分環(huán)境:如 DEV, TEST, PROD 環(huán)境對應不同配置。
3.4 分布式緩存(Redis 等)
在分布式環(huán)境下,數據庫通常成為性能瓶頸。為減少對數據庫的直接訪問和壓力,需要一個 高性能的分布式緩存。Redis 是最常用的選擇,它具有以下優(yōu)勢:
- 內存存儲,讀寫速度快。
- 豐富的數據結構(字符串、哈希、列表、集合、有序集合等)。
- 支持 主從復制、Cluster 集群,適合分布式部署。
- 常用于 緩存熱點數據、分布式 Session、分布式鎖 等場景。
使用 Redis 的關鍵點:
- 設計 合理的緩存鍵(key),比如
product:detail:{productId}。 - 設置 過期時間,避免緩存數據與數據庫數據長期不一致。
- 考慮 緩存穿透、緩存雪崩、緩存擊穿 等問題,并進行對應的防護(如 Bloom Filter, 加互斥鎖, 合理限流等)。
3.5 分布式鎖
在分布式環(huán)境中,如果多個節(jié)點同時對同一個資源進行寫操作,就容易出現(xiàn)數據不一致或并發(fā)沖突。因此,需要一種分布式鎖來保證 在同一時間,只有一個節(jié)點可以獲取鎖,進行資源操作。
常見方案:
- Redis 分布式鎖
- 使用
SETNX(set if not exist) +EXPIRE或SET key value NX PX time命令實現(xiàn)。 - 注意要設置超時時間,避免鎖無法釋放導致死鎖。
- 也要考慮鎖的續(xù)約和解鎖時的原子性操作(Lua 腳本),以避免誤刪他人的鎖。
- 使用
- Zookeeper 分布式鎖
- 利用 ZK 的臨時順序節(jié)點來競爭鎖,監(jiān)聽事件,一旦獲取鎖的節(jié)點斷開連接,就自動刪除節(jié)點,其他節(jié)點立即感知到并可重新競爭。
示例:基于 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 {
// 執(zhí)行業(yè)務邏輯
} finally {
// 解鎖時,先判斷鎖是否是自己加的
String val = redisTemplate.opsForValue().get(lockKey);
if (lockVal.equals(val)) {
redisTemplate.delete(lockKey);
}
}
}3.6 分布式事務
在單體應用中,事務只需要依賴數據庫的本地事務(ACID)即可。但在分布式系統(tǒng)中,可能一個操作需要 跨多個微服務、跨多個數據庫,這時就出現(xiàn)了 分布式事務 問題:
- 例如,在電商場景下,創(chuàng)建訂單 時,要同時扣減庫存、生成支付記錄等,這些操作都在不同微服務里完成;如果其中某一步出錯,就需要回滾之前的操作。
常見分布式事務方案:
- 2PC(兩階段提交):協(xié)調者告訴所有參與者先預提交,然后再統(tǒng)一提交或回滾。實現(xiàn)復雜,性能損耗大,適合對一致性要求極高的場景。
- TCC(Try-Confirm-Cancel):業(yè)務系統(tǒng)自己實現(xiàn)各個操作的 “Try, Confirm, Cancel”,實現(xiàn)靈活,但開發(fā)成本高。
- Seata:阿里開源的分布式事務框架,提供 AT 模式(對 JDBC 層做代理),也提供 TCC 等模式。
Seata 示例
@GlobalTransactional
public void placeOrder(Order order) {
// 跨服務調用
inventoryService.decreaseStock(order.getProductId(), order.getQuantity());
paymentService.processPayment(order);
orderMapper.insert(order);
// Seata 會在這里把整個調用過程進行管理,可做到成功或回滾
}在執(zhí)行過程中,如果其中一個調用報錯,Seata 就會通知其他服務進行回滾。
3.7 分布式消息隊列
消息隊列 (Message Queue) 用于解耦系統(tǒng)、異步處理和削峰填谷。常見的 MQ 方案有:
- RabbitMQ:輕量級,支持事務與確認機制,適合傳統(tǒng)企業(yè)應用以及對消息可靠性要求高的場景。
- Apache Kafka:高吞吐,大規(guī)模數據流處理的“事實標準”,更多用于大數據、日志收集、流式處理等場景。
- RocketMQ:阿里開源的分布式消息中間件,和 Kafka 類似,也有較高的吞吐。
MQ 的作用:
- 解耦:比如,用戶下單后,需要發(fā)送優(yōu)惠券、通知物流、通知商家等,而如果所有這些操作都放在下單接口里,會導致耦合過高;使用 MQ,每個消費者服務負責監(jiān)聽消息并執(zhí)行相應的業(yè)務邏輯。
- 削峰填谷:在高峰時段,訂單系統(tǒng)可以快速寫入消息隊列,后臺處理系統(tǒng)再慢慢消費,避免直接壓垮數據庫或其他服務。
- 異步:不需要同步等待消息處理完成,加快用戶請求的響應速度。
3.8 API 網關與負載均衡
當服務拆分越來越多,我們往往需要一個統(tǒng)一的 網關 來管理請求:
- 服務網關(如 Spring Cloud Gateway、Nginx、Kong):
- 統(tǒng)一對外提供訪問入口
- 進行路由分發(fā),鑒權,限流,監(jiān)控等
- 在微服務復雜時,可以屏蔽內部服務接口的變化,對外提供穩(wěn)定的 API。
- 負載均衡:
- 當某個微服務有多個實例時,網關或負載均衡器需要把請求分散到各個實例上,避免其中一個實例被打滿。
- 常見方式:Nginx 反向代理 或 Spring Cloud Ribbon (新版 Spring Cloud LoadBalancer)都可實現(xiàn)負載均衡。
4、整體流程與示例
4.1 典型電商微服務調用鏈
以 電商訂單 流程為例,來看看分布式系統(tǒng)下的一般調用。
- 用戶 訪問 API 網關(或 Nginx),請求
/api/order/create接口。 - 網關解析路由規(guī)則,將請求轉發(fā)給 OrderService。
- OrderService 調用 UserService 檢查用戶信息(比如積分、等級等)。
- OrderService 調用 ProductService 檢查庫存、扣減庫存;同時查詢商品價格。
- OrderService 寫入訂單數據庫,本地事務或分布式事務處理。
- OrderService 向 MQ 發(fā)送消息,用于通知其他服務(如物流、積分系統(tǒng)等)。
- MQ 的消費者(如 LogisticsService)消費消息并執(zhí)行下一步操作。
在這個過程中,會用到:
- 服務注冊中心(保證 OrderService 能動態(tài)發(fā)現(xiàn) ProductService 的地址)
- 分布式緩存(可能在 OrderService、ProductService 的查詢環(huán)節(jié)做緩存)
- 分布式鎖(避免多次重復扣減庫存)
- 分布式事務(如要保證扣庫存與下單一致)
- 消息隊列(通知其他異步任務)
4.2 部署模式
- 開發(fā)/測試環(huán)境:一般都是在本地 Docker 或者虛擬機里把注冊中心、MQ、Redis、數據庫等組件跑起來即可。
- 生產環(huán)境:會把各個服務獨立部署在多臺服務器(或容器云)上:
- 注冊中心、配置中心(Nacos/Consul/Eureka)集群
- Redis 高可用集群(主從+哨兵模式或 Redis Cluster)
- MQ 集群(RabbitMQ 集群或 Kafka 集群)
- 分布式文件系統(tǒng)(如 MinIO, FastDFS, OSS 等)
- 后端數據存儲(MySQL 或者多分片數據庫),需要做讀寫分離或分庫分表
- 若干微服務集群(UserService、OrderService...),通過容器編排(Kubernetes 或 Docker Swarm)進行管理
到此這篇關于Java中的分布式(概念說明)的文章就介紹到這了,更多相關java分布式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Dubbo之SPI機制的實現(xiàn)原理和優(yōu)勢分析
這篇文章主要介紹了Dubbo之SPI機制的實現(xiàn)原理和優(yōu)勢,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-05-05
舉例講解Java的Spring框架中AOP程序設計方式的使用
這篇文章主要介紹了Java的Spring框架中AOP程序設計方式的使用講解,文中舉的AOP下拋出異常的例子非常實用,需要的朋友可以參考下2016-04-04
SpringBoot使用?Sleuth?進行分布式跟蹤的過程分析
Spring Boot Sleuth是一個分布式跟蹤解決方案,它可以幫助您在分布式系統(tǒng)中跟蹤請求并分析性能問題,Spring Boot Sleuth是Spring Cloud的一部分,它提供了分布式跟蹤的功能,本文將介紹如何在Spring Boot應用程序中使用Sleuth進行分布式跟蹤,感興趣的朋友一起看看吧2023-10-10
jenkins通過docker部署后系統(tǒng)時間不正確問題的詳細解決方法
這篇文章主要介紹了jenkins通過docker部署后系統(tǒng)時間不正確問題的詳細解決方法,Jenkins時間顯示慢8小時通常由JVM時區(qū)未正確配置引發(fā),文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-06-06
解決本機安裝的JDK8,啟動IDEA2019沒反應的問題(開發(fā)工具)
這篇文章主要介紹了解決本機安裝的JDK8啟動IDEA2019沒反應的問題(開發(fā)工具),非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
關于jd-gui啟動報This?program?requires?Java?1.8+的錯誤問題及解決方法
最近,在Mac使用上JD-GUI啟動時總是報錯,接下來通過本文給大家介紹關于jd-gui啟動報this?program?requires?Java?1.8+的錯誤問題及解決方法,需要的朋友可以參考下2022-05-05

