当前位置: 首页 > news >正文

【小也的Java之旅系列】02 分布式集群详解

文章目录

  • 前言
    • 为什么叫小也
  • 本系列适合什么样的人阅读
  • 正文
  • 单体
    • 优点
    • 缺点
  • CAP
    • 为什么CAP不可能全部满足?
    • CAP 三选二
  • 分布式事务
  • 分布式方案——Seata
    • XA模式(强一致)
    • AT模式(自动补偿,默认模式)
    • TCC模式(手动补偿)
    • Saga模式(长事务)
    • 四种模式的区别
  • 分布式锁
    • ZooKeeper 实现分布式锁
    • Redis 实现分布式锁
    • 区别
  • 总结

前言

做Java开发多年,一直以来都有想把Java做成一个系列的想法,最近整理自己的笔记发现有很多值得写的内容,但这些内容又往往杂乱不堪。CSDN上有很多高质量的Java博客,但大多不是从一个人成长的角度去写的。而我们——一个技术人员——一个人,是在不断的学习中成长的,这样的过程如果能体现在系列博客中那真的就太好了。于是,终于下定决心,想花一段时间整理成册——或许是几个月,或许是半年,或许是一年不止。希望自己能坚持下去。

为什么叫小也

孩子是我们之所以还努力的原因。

本系列适合什么样的人阅读

阅读本文最好有一定基础,最优人群是:

  1. 了解Java的基础语法
  2. 自己本身已经写过代码
  3. 对Java架构、大数据、轻代码等进阶有兴趣

如果你是个初出茅庐的初学者,对Java技术内容都不甚了解,也不用特别担心,我的另外一个系列你肯定感兴趣——《Java8系列博文合集》(或者访问我的博客园也可以阅读)。

正文

上一章内容大体描述了什么是分布式,以及分布式和微服务等架构的关系。接下来,我们要详细讨论分布式,以及如何在实战实战中使用。

上一章里,小也使用分布式思路帮助叔叔解决了厨房出餐效率的问题。那么,到底什么是分布式?

如果用一句话描述分布式:
将系统别发在不同的服务器,就是分布式。

分布式不是一种特指的代码架构,更多的是一种解决问题的方法。比如:我们可以说微服务就使用了分布式的思路,但微服务≠分布式。

在实战中,分布式更强调部署方式,而不是开发。

单体

在这里插入图片描述
同样以厨房为例:厨师=软件程序,工作台=服务器硬件。
单个软件运行在单个服务器上,就是单体系统。

在以往,最初的系统结构较为简单时,大多都是单体系统。

优点

  1. ​开发简单,代码集中管理
  2. ​部署便捷,运维成本低
  3. ​测试直观,集成测试无需模拟外部服务

缺点

  1. ​扩展性差,只能整体扩容,无法按需伸缩
  2. ​复杂性高,代码臃肿,依赖关系复杂
  3. ​技术更新难,升级技术栈需全局重构
  4. ​故障隔离差,单点故障可能影响全局

随着社会发展,程序逻辑越来越复杂,单体系统劣势越来越明显,高并发、高可用的呼声越来越大了。在这种情况下,必须出现一种模式解决单体系统的问题。

CAP

CAP 定理(Consistency, Availability, Partition Tolerance)是分布式系统中的一个基本理论,指出在一个分布式系统中,不可能同时满足以下三个特性:

  • 一致性(Consistency, C):所有节点访问同一份最新的数据副本。
  • 可用性(Availability, A):所有的请求都能收到一个响应,无论数据是否是最新的。
  • 分区容忍性(Partition Tolerance, P):系统能够继续运行,即使部分节点之间的通信失败。

为什么CAP不可能全部满足?

回到小也遇到的厨房问题。
厨房最开始只有一位厨师+一个工作台,当出现任何问题,如:工作台损坏或厨师生病,就会导致不能出餐。

小也开始思考这些问题,得出了一系列结论,如果要让饭店良好的运转,应该满足以下要求:

  • 一致性:不管是哪位厨师做餐,只要是同一个菜品,厨师出的餐就应该是一样的
  • 可用性:不管是何时何地点餐,厨师都应该及时做出指定的菜品。
  • 分区容忍性:不管遇到任何问题,哪怕是某位厨师生病或工作台损坏,都不影响出餐。
    在这里插入图片描述
    在这里插入图片描述

但在实际操作中,小也很快发现了新问题:
一致性与可用性冲突:有一天,三位厨师正在为一桌客人做菜,做了一半时,客人告诉A厨师她不吃葱姜蒜,这时服务员也同时来取餐。A厨师立马停下了加葱姜蒜的手,但还没来得及告诉其他两位厨师,他们的菜已经做好(有葱姜蒜)。如果从一致性角度,厨师出的餐必须符合一致要求——A厨师应该立即告诉其他厨师去掉葱姜蒜重新做——再出餐。但从可用性角度,这时候服务员已经来取餐,不能让客人获取不到。

​假设: 存在一个分布式系统同时满足C、A、P
​当网络分区发生时:
根据A(可用性),系统必须响应所有请求
根据C(一致性),所有节点数据必须同步更新
但分区导致节点间无法实时通信,无法完成同步
​结论:假设不成立,三者无法共存

CAP 三选二

根据CAP定理,分布式系统只能在以下三种方案中选择两者:

  1. CP(Consistency + Partition Tolerance):保证数据一致性,即使某些节点发生分区故障,系统可能无法响应部分请求。例如:HBase、MongoDB(某些模式)。
  2. AP(Availability + Partition Tolerance):保证系统高可用性,即使发生分区,数据可能是不一致的。例如:Cassandra、DynamoDB。
  3. CA(Consistency + Availability):只在没有网络分区时成立,通常单机数据库(如传统的关系型数据库)可以满足。

在这里插入图片描述

如果选择:

  • CA:就是单体服务,因为没有分区,程序只在一个服务器运行,自然也能保证一致性和可用性。
  • CP:使用通信让不同分区间的程序数据保持一致,如:数据库主从,使用加锁方式强制保持一致。但这样就丧失了实时性。
  • AP:高并发模式下的系统可以同时允许多人访问,如:12306购票,可以使用缓存技术及时响应用户,但这样就丧失了一致性,导致在出票环节显示无票(痛苦的回忆 TT)。

分布式事务

分布式一旦成型后,还面临一个普遍的问题:任何关键流程一旦分布在不同服务器,就必须保证其所有环节的一致性。

以上文提到的12306购票为例:

提交订单→跳转第三方程序付款→确认付款成功→出票

假设这些程序分布在不同服务器,无论哪个程序出错都将导致订票失败。反过来讲,其中任何一个环节出错都应该终止订票。

分布式事务就是创造一个程序作为监视者,监控流程中的程序,当这些程序出现错误时,将整个订票流程回滚。

分布式方案——Seata

有了以上的理论基础,小也在面对分布式“炒菜”问题时,也有了结论:
如果能有一个人——比如饭店老板——专门控制菜品要求,让客人的需求及时反馈到厨房,同时让厨师按照要求做菜,这样就不会出现菜品不一致的问题。

Seata​(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,提供AT、TCC、Saga 和 ​XA 四种事务模式,支持跨数据库、跨服务的分布式事务管理。

术语说明
​TCTransaction Coordinator(事务协调器):全局事务的调度者(独立部署)
​TMTransaction Manager(事务管理器):定义全局事务边界(@GlobalTransactional)
​RMResource Manager(资源管理器):管理分支事务的资源(如数据库连接)

TC:饭店老板,在饭店里协调客人完成点餐→出餐→吃饭→结账
TM:服务员,负责接待客人,确认其需求并报告给老板协调
RM:厨师,为每个客人出餐

XA模式(强一致)

在这里插入图片描述

原理:基于数据库XA协议的两阶段提交
适用场景:传统数据库跨库事务(如银行核心系统)

流程:

  1. TM首先向TC注册
  2. TM分别调用RM
  3. RM各自向TC注册
  4. RM各自执行操作并向TC汇报状态(正常或异常)
  5. TM从TC处获取各RM执行情况,并向TC提出提交/回滚
  6. TC要求所有RM执行统一操作:提交/回滚

AT模式(自动补偿,默认模式)

原理:通过代理数据源拦截SQL,生成逆向SQL实现回滚
适用场景:跨数据库事务(如MySQL、Oracle)

在这里插入图片描述
流程:

  1. TM首先向TC注册
  2. TM分别调用RM
  3. RM各自向TC注册
  4. RM各自执行操作并直接提交(commit),将操作记录到undolog表,之后向TC汇报状态(正常或异常)
  5. TM从TC处获取各RM执行情况,并向TC提出提交/回滚
  6. TC要求所有RM执行统一操作:如果是提交则保留RM各自的执行结果,如果是回滚则根据undolog的内容进行反向恢复操作

一句话总结:AT是先执行错了都再改回去,XA是必须保证都对再执行。

TCC模式(手动补偿)

原理:通过 Try-Confirm-Cancel 三阶段实现
适用场景:跨境支付(汇率锁定+资金划转)

  1. Try阶段:

    • 预留资源(如冻结库存)
    • 生成预备数据
  2. Confirm阶段:

    • 提交预备数据(如扣减冻结库存)
  3. Cancel阶段:

    • 释放预留资源(如解冻库存)

流程:
Try:冻结用户美元账户资金
Confirm:实际扣款并完成人民币入账
Cancel:解冻冻结资金(若汇率波动超阈值)

Saga模式(长事务)

原理:通过状态机编排服务调用,失败时执行补偿操作
适用场景:旅游平台多服务预订(酒店+机票+租车)

​流程:
正向操作:预订酒店 → 预订机票 → 租车
补偿操作:若租车失败 → 取消机票 → 取消酒店

四种模式的区别

对比维度AT(自动补偿)​TCC(手动补偿)​Saga(长事务补偿)​XA(强一致性)​
实现原理代理数据源生成逆向SQL回滚Try-Confirm-Cancel三阶段手动控制正向服务链 + 逆向补偿链数据库原生XA协议两阶段提交
一致性级别最终一致性(默认)强一致性最终一致性强一致性
业务侵入性低(仅需数据源代理)高(需实现Try/Confirm/Cancel接口)中(需定义补偿服务)无(数据库驱动实现)
锁机制一阶段提交即释放锁Try阶段锁定资源无锁(依赖业务幂等)全程持有数据库锁
性能高(本地事务快速提交)中(需多次RPC调用)低(长事务延迟高)低(两阶段同步阻塞)
隔离性通过全局锁实现读隔离业务自行控制隔离性无隔离(可能脏读)完全隔离
适用场景跨数据库事务(如订单+库存)金融交易(如支付扣款)长流程业务(如机票预订)传统数据库跨库事务(如银行转账)
典型框架Seata AT模式Seata TCC模式Apache ServiceComb SagaAtomikos、Narayana
补偿方式自动生成反向SQL手动编写补偿逻辑手动或配置式补偿数据库自动回滚
数据一致性保障最终一致性(允许短暂不一致)强一致性最终一致性(需补偿成功)强一致性

分布式锁

小也用分布式事务的思维模式解决了流程上统一性的问题,但又有了新问题。
以前一个厨师的时候,大家点餐都是先来后到,反正就这么一个厨子,按顺序出餐就是了。但现在厨师多了,大家同时点餐时,厨师们有时候需要同时用到某一台厨具,这个时候就产生了竞争。

控制对同一对象/资源使用,就需要用到锁。

以前单体系统的时候,程序在一台服务器上,使用Java的自带锁就可以解决大部分问题,但现在程序分散在不同服务器,要保证业务流程正确的前提下,还要保证对竞争资源的顺序使用,就需要一个跨服务器的分布式锁。

Java架构中常用的分布式锁有:ZooKeeper 和redis。

ZooKeeper 实现分布式锁

利用 ZooKeeper 的 ​临时顺序节点 和 ​Watcher 机制 实现公平锁。

  • 优点
    ​强一致性:ZAB协议保证数据一致性
    ​自动清理:临时节点自动删除避免死锁
    ​公平锁:按节点顺序获取锁

  • ​缺点
    ​性能较低:频繁创建节点和触发Watcher有延迟
    ​依赖ZooKeeper集群:需维护ZooKeeper服务

Redis 实现分布式锁

通过 SETNX(或 SET 命令扩展参数)实现互斥锁,配合Lua脚本保证原子性。

  • 优点
    ​高性能:内存操作响应快
    ​简单易用:API友好,支持多种客户端

  • ​缺点
    ​非强一致:主从切换可能导致锁丢失(RedLock缓解但未彻底解决)
    ​锁续期复杂:需处理过期时间与业务执行时间的匹配

区别

维度ZooKeeperRedis
一致性强一致性(ZAB协议)最终一致性(主从同步延迟)
性能低(频繁节点操作和Watcher触发)高(内存操作)
死锁处理临时节点自动删除依赖超时机制
锁类型公平锁非公平锁(Redisson可配置为公平锁)
适用场景需严格一致性的系统(如金融交易)高并发且允许短暂不一致的场景(如库存扣减)
运维复杂度需维护ZooKeeper集群单节点简单,RedLock需多实例部署

总结

分布式虽然带来了高并发高可用的优点,但同时也带了新问题。以往单体服务的事务、锁机制都可以控制在单一服务器内解决,但现在不得不从多个服务器角度思考。于是,提出了分布式事务和分布式锁。其原理与单体服对应解决方案一致,但由于分布式复杂性,在实际解决时需要考虑不同服务器之间通信和状态同步。

相关文章:

  • 经典算法Golang实现
  • 【含文档+PPT+源码】基于微信小程序的社交摄影约拍平台的设计与实现
  • python 语言始终是中文
  • 论文笔记(七十五)Auto-Encoding Variational Bayes
  • vue父子周期解决问题
  • Dubbo分布式框架学习(2)
  • Cursor:AI 驱动的编程变革者
  • JavaScript性能优化实践:从微观加速到系统级策略
  • 【数据分享】中国3254座水库集水区特征数据集(免费获取)
  • C++11QT复习 (七)
  • MySQL中的函数(字符串,数值,日期,流程)以及部分案例
  • A股复权计算_权息数据整理代码
  • 自适应二值化与形态学变换在图像颜色识别与替换中的应用解析
  • .Net中的流处理类总结 Stream/FileStream/MemoryStream/NetworkStream/StreamReader
  • 04-深入解析 Spring 事务管理原理及源码
  • YOLOv5配置训练以及华为昇腾910B推理
  • JavaScript数组Array的使用:添加、删除、排序、遍历、互转
  • 【python中级】使用 distutils 和wheel生成whl 轮子文件
  • 蓝桥杯 切割
  • 深入探究Spring MVC
  • 落实中美经贸高层会谈重要共识,中方调整对美加征关税措施
  • 某博主遭勒索后自杀系自导自演,成都警方立案调查
  • 演员发文抵制代拍获粉丝支持,媒体:追星“正确姿势”不妨多来点
  • “犍陀罗艺术与亚洲文明”在浙大对外展出
  • 巴基斯坦称未违反停火协议
  • 图集︱“中国排面”威武亮相