返回介绍

Java 帝国之宫廷内斗(2)

发布于 2025-02-16 11:28:23 字数 6557 浏览 0 评论 0 收藏 0

1 前情提要

上回说到 IO 大臣一直被 JDBC 大臣打压, 为了搞掉 JDBC 大臣, 他忍辱负重、历经千辛万苦终于搞出了分布式事务的标准 Java Transaction API, 满心以为这次必定翻身,但是没想到国王为了平衡朝中的权利, 居然把 JTA 的管理权赐给了新任的 JTA 大臣。

更没有想到的是,幸亏自己没有管理 JTA,这个官方标准太强调强一致性,和民间的高并发系统要求的最终一致性不合拍,用不起来,变成了 JTA 大臣的烫手山芋。

和民间代表深谈了一次以后,本来已经心灰意冷的 IO 大臣再次激起了雄心壮志: 一定要把 JDBC 大臣和 JTA 大臣搞掉。

2 基本可用

IO 大臣马上找了自己的心腹幕僚 InputReader , 交代了一项任务, 去民间考察这些高并发系统是怎么折腾最终一致性的。

InputReader 连夜出发, 为了不引起 JDBC 大臣和 JTA 大臣的注意, 这次特意微服私访。

他不辞辛苦, 跑遍了帝国大大小小几十个高并发系统, 与大量的民间领袖深入地交换了意见。 他越谈越惊心: 我们总是高高在上地制定所谓官方标准,自我感觉良好,实际上根本没人用, 前有 EJB, 今有 JTA, 都是脱离了实际需求想出来的。

3 个月后, InputReader 已经成竹在胸, 回到京城向大人汇报。

“大人, 据小人观察, 我们的 JTA 用的人确实很少,我现在是理解了他们民间所说的最终一致性了”

看着黑瘦的 InputReader, IO 大臣心里非常感动, 暗下决心: 等老夫控制了朝局, 一定给忠于自己的 InputReader 升两级。

“还是拿那个转账的例子来说吧” InputReader 喝了口茶继续说 “ 假设两个账户(吕秀才和郭芙蓉)在两个独立的数据库中, 我们原来设计的 JTA 是要求从吕秀才账户减去 100 两银子, 然后在郭芙蓉账户加上 100 两银子, 这两个操作要么全部做完,要么全部不做, 但是在网络的环境下, 这是不大容易做到的, 或者说在高并发的情况下做到的代价太高。”

“这我理解,上次说了, 你说说民间到底是怎么实现的。” IO 大臣有点心急。

“其实特别简单, 他们用了一个叫做消息队列的东西来实现的, 大人请看 ” InputReader 展开了一张图:

IO 大臣看着图: “就这么简单?”

InputReader 说: “小人举的是个非常简单的例子, 但是也能说明问题了, 你看我们想从吕秀才账户转 100 两银子给郭芙蓉, 需要在数据库 1 发起一个事务, 从吕秀才账户扣除 100 两, 然后还得向消息队列插入一条给郭芙蓉账号增加 100 两的消息, 然后这个数据库 1 的事务就结束了! 消息队列中的消息会在某一刻被读取出来,进行处理,给郭芙蓉的账号增加 100 两。”

“那给郭芙蓉添加 100 两的消息什么时候会被处理呢? ”

“这个时间不确定, 就看具体怎么实现了, 比如有个后台程序定期运行,读取消息来处理 ”

“那万一消息队列 down 机怎么办? ”

“不用怕, 消息队列的数据都是持久化到硬盘上的, 不会丢失。”

“郭芙蓉这么刁蛮, 这 100 两银子不能立刻到账, 她还不把吕秀才给‘排山倒海’了?”

“大人,这就是关键了,你想啊, 假设数据库 2 down 机了, 对郭芙蓉有两种选择: 一种是由于系统原因,转账操作完全不能操作,另外一种是可以转账,但是钱稍后到账,你说郭芙蓉会选哪一种?”

IO 大臣说: “有道理,第一种情况是完全不可用, 第二种只是是部分可用, 郭芙蓉肯定会先让吕秀才转账, 反正 100 两银子是自己的, 早一点晚一点也没关系。 ”

“对的, 这就是最终一致性,数据虽然在某些时候看起来不一致,吕秀才的钱少了但是郭芙蓉的钱没增加,这个时候钱在消息队列中暂时存着呢。”

“这样做有什么好处?”

“好处很大,对于高并发的场景,转账的时候扣完钱, 向消息队列插入消息,事务就结束了, 根本不用什么两阶段提交, 性能很好。”

“嗯,不错, 我们再来看看一些细节吧。。。。。。”

3 走漏风声

天下没有不透风的墙, JDBC 大臣的密探早已潜伏在 IO 府中好多年了,虽然只是个端茶送水的下人, 但是很多消息都进入了他的耳朵, 然后又进入了 JDBC 大臣的耳朵。

JDBC 大臣找来了 JTA 大臣前来商议, 为了找一个同盟军和强大的 IO 大臣对抗, JDBC 大臣收买了不干实事的 JTA 大臣。

“你知道吗? IO 老头儿派人出去调查了, 我估计很快就会像上次那样参我一本。” JDBC 大臣忧心忡忡。

“这 IO 老头儿为啥老是和大人过不去呢, 守好他那一亩三分地多好!”

“人的欲望都是无穷的,再说我这几年确实打压他比较厉害, 不说了,你先看看这张图, 是我们的卧底从 IO 府中偷出来的。”

JTA 大臣抽了一口冷气:“现在民间都这么玩了? 不用 JTA 了? ”

“是啊, 你看他们的方法还不错嘛, 基本可用,最终一致性。真是实践中出真知啊” JDBC 大臣感叹道,他在观察 JTA 的反应。

“大人, 我建议咱们抢先一步, 明天早朝就把这幅图献给陛下,陛下一高兴,估计就会把这一块儿划给我管了, 不不, 是给你管了。 ”

“这合适吗?”

“无毒不丈夫, 朝中争斗本来就是你死我活的, 大人不可太妇人之心了。”

“好,就这么办。”

4 宫廷激辩

国王已经厌倦了早朝, 厌倦了臣子们在朝中争来争去。

这天出奇的平静, JDBC 大臣和 IO 大臣没有像之前那样争得不可开交, 国王正要宣布 “有事启奏,无事退朝” , 一直以来战战兢兢的 JTA 大臣咳嗽了一声, 发言了 :

“陛下,臣最近得到一个民间上供的设计图,说是民间用了一种新型办法来处理高并发问题 ” JTA 一边把偷来的图纸呈上去,一边用余光迅速地扫了一眼 IO 大臣。

JDBC 在一旁添油加火:“陛下,臣也看过这个设计, 觉得非常不错, 建议帝国设立标准推广。”

IO 大臣一切都明白了,自己还没有出手,这俩老头儿先下手为强了。

国王自然是看不懂,听到两位大臣都这么肯定, 懒洋洋的说: “爱卿此言不错,这个既然属于分布式事务, JTA 大臣,你来领衔把他设计出来。”

IO 大臣看准时机,突然出手:“陛下万万不可, 这个设计有重大缺陷啊!”

“什么缺陷? ” JDBC 大臣和 IO 大臣齐声问道。

IO 大臣胸有成竹, 一切尽在计划之中,那个图纸只不过是个小诱饵而已,这两个愚蠢的老头儿果然上钩。

“陛下,请看这个图纸, 吕秀才给郭芙蓉转账的时候,图纸中写的是:”

“我想请问 JDBC 老头儿, 不, 大臣, 这个事务同时操作了数据库和一个消息队列, 这两个东西是完全不同的, 请问你是怎么实现的?不会还是使用老掉牙的 JTA 吧”

(注: JTA 不仅仅可以支持数据库, 只要是支持 XA 协议的数据源都可以)

JDBC 心中大叫不好,中计了! 唉,自己怎么不仔细研究下图纸呢, 这么一个缺陷竟然没有发现, 冒冒失失地献给陛下,真是不可饶恕啊!

可是他不甘心就此失败, 稍一定神,立刻反击: “先不说缺陷问题, 我想问你这个图纸刚才只有陛下看了, 你怎么知道其中内容?!”

IO 大臣看到他反咬一口,岂能罢休 ,一不做二不休,干脆撕破脸: “陛下, 这张图纸本来是我府中的 InputReader 走遍帝国,遍访民间疾苦画出来的, 我们知道有缺陷, 还没来得及修改,就被他俩给偷了去 !”

“你血口喷人!” JDBC 和 JTA 有些心虚了。

“陛下,我已经抓住了偷窃图纸的佣人, 随时可以传唤。”

国王一切都明白了: 这些大臣之间的争斗真是无处不在啊, 每天如此,都不能让我消停一天。

“爱卿,” 国王对 IO 大臣说, “你先说说怎么解决那个图纸中的缺陷问题吧”

“陛下,其实有很多办法, 比如这一种” IO 大臣从袖中掏出一个图纸,举了起来,让大家都能看到:

“在这里,我们可以添加一个‘事件表’, 转账开始的时候,把吕秀才的 100 两银子扣除, 同时还向事件表插入一行记录: 需要向郭芙蓉转 100 两, 由于这两个表是在同一个数据库中,所以直接使用本地事务就行。不用什么分布式事务。”

“你那个定时运行程序干嘛?” JTA 大臣理解力有限

“就是定时运行, 从事件表中取出记录, 向 MQ 写入消息, 然后把记录的状态改成‘DONE’, 这样下次就不用再去取去处理了。 ”

JDBC 大臣很老练: “那你这个定时运行程序也有问题啊, 比如说它读了数据,向消息队列写入了消息, 还没来得及把事件表的 status 改为 ‘DONE’ 就崩溃了,等到定时运行程序重启以后,岂不再次读取, 再次向 MQ 写入消息,这样郭芙蓉不就得到了 200 两银子,整个系统就不一致了。”

IO 大臣心里有点佩服, 这老头儿还是有两把刷子的。 幸亏我和 InputReader 讨论过各种细节,要不然还真被他给问住, 那在陛下面前就悲催了。

5 幂等性

“其实这里必须得引入一个概念: 幂等性” IO 大臣说

“迷瞪性? 这是什么东西 ” JTA 大臣大惑不解。

“是幂等性, mi ,四声” IO 大臣对朝中有这样不学无术占据高位的家伙感到很悲哀, “这个幂等性说的是当你对一个事物操作的时候,可以一直重复地操作,那个事物不受影响, 例如对郭芙蓉的账号你查询一千次,一万次,账户余额还是那么多,不会变化。 转账操作就不是一个幂等性操作。 每次操作都会导致账号的变化。”

JDBC 大臣也不由地鄙视了下 JTA 老头儿, 他说:“我明白了,你的意思是说那个定时运行的程序可以出错,可以向消息队列写入多次 ‘给郭芙蓉账号增加 100 两银子’ 这样的消息, 但是郭芙蓉那边在执行的时候, 肯定也要判断之前是否执行过了, 如果没有的话就增加, 如果执行过了就简单的抛弃这个消息即可。 ”

IO 大臣向 JDBC 大臣投去了佩服的目光, 两人目光相遇, 碰出来了惺惺相惜的火花。

“唉, 我要是早点和 JDBC/IO 大臣合作多好” 两个人都在暗自吃后悔药。

IO 大臣说: “是的, 郭芙蓉那边在判断是否已经执行过的时候,也需要查询之前的执行记录, 这就意味着之前执行过的也需要用一个表保存下来才行。”

“众位爱卿, 看来已经讨论得差不多了, 接下来怎么办啊?”

没人出声。

“那要不这样, 既然是民间先做出来的东西, 我们官方就不用去凑热闹了, 让他们自生自灭吧” 国王祭出了“无为而治” 的大法, 其实他实在不想再调停这几个大臣之间的争斗了。

IO 大臣想发言却又忍住了,经过这一番较量, 他看清楚了各位大臣的实力, 也理解了国王的苦衷, 如果再这么争斗下去陛下估计会龙颜大怒, 算了,不争了。

傻傻的 JTA 大臣还不死心, 一直给 JDBC 大臣使眼色,只是 JDBC 大臣心中打定了和 IO 大臣一样的主意,微闭双眼开始养神了。

IO 大臣心情平静地回到家中, 幕僚们围上来询问结果, 他们还做着升官发财的美梦。

IO 大臣看着这些急于知道结果而显得特别饥渴的表情, 笑着摆了摆手, 一言不发地离开了。

很久以后,朝中得知民间有个叫做 Dan Pritchet 的人, 把这种方法总结了一下,称之为 BASE 模型, 从此流行开来。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文