Go微服务: 分布式之通过可靠消息实现最终一致性

通过可靠消息实现最终一致性

  • 可靠消息,就是靠普消息,还是基于之前的这个案例
  • 比如这个订单服务,无论你是先发送消息,还是先新建订单,它其实都是发送的不可靠消息
  • 就是说如果这个消息,像mysql事务那样,只要订单服务不确认,下游就没办法消费
  • 如果你这个订单服务挂了,就可以取消这个消息,就不用做这个本地消息表了
  • 本地消息表,要有一个这个循环的这么一个查询,高并发的时候,你本地的数据库本身压力就大
  • 再弄这么一个查询,一直循环的查,它这个压力也不小,现在看一下基于事务消息,也称为可靠消息
  • 生产者就可以理解为这个订单服务,消费者就可以理解为积分服务,还有库存服务
  • 先看第一个,生产者先发一个半消息给消息队列,消息队列就回我这个半消息成功的信息
  • 这是一个半消息,然后拿到这个半消息成功的结果之后,我们往数据库里写一个Transaction事务
  • 我们就把本地事务执行了,执行之后,也就是到了第4步, 成功情况下就是确认这个半消息
  • 只要到第4步这个commit成功了,消费者就可以消费了,因为你的这个消息已经在这个消息队列中了
  • 这个解决方式是解决了只要我们能发出去的这个消息就是可靠的,只要能提交的消息,本地消息就一定是成功的
  • 因为你本地事务都已经执行成功了,先发半消息,消息队列回给我,回给我之后,我就能收到了,说明已经成功了
  • 然后这个时候你就开始干你本地的事儿,比如订单生产者自己开始建订单,建订单产品表,这都是你的事
  • 我本地能成功了之后,1,2,3步是为了能让消费者成功消费的准备工作
  • 这个思路就是说只要一提交,那我本地这边全部ok, 然后我这个消息队列, 肯定能保证我我的最终一致性
  • 如果在3之前出错,那不会做事务,那相当于准备工作没做好,那下游也不会做相应的这个事情
  • 同时,我们还要思考,有没有其他方面的情况会导致问题
    • 比如,更复杂的网络传输问题,别人的服务宕机了或有bug了
    • 因为微服务在开发的时候,每个小组可以时刻发布自己的服务,它不受控制
  • 如果上述分布式服务出问题了,消息队列也会有一个回查事务消息状态的机制
  • 我会问你这个生产者,哎,你这个状态是啥?然后生产者就会查询这个本地事务状态
  • 第5步和第6步,就是又一次为这个返回事务状态做commit和rollback,就是为下一步的工作做准备
  • 就是消息队列,不知道你这个消息要不要投递,也不能知道别人的状态是什么样的
  • 那消息队列就会问这个生产者,你这个消息事务是啥状态,在第6步得到查询的事务状态是commit
  • 那我消息队列就commit消息投递,一旦消息投递了,这个消费者就可以进行消费了
  • 假如说,返回的这个事务状态是rollback,消息队列就可以把消息扔了
  • 在这整个链路里,有成功的,让消费者消费消息;也有失败,让这个消息队列去丢弃消息
  • 还有中间状态,就是说我不确定这个事务是不是正确的?那询问还是有结果的,就是 commit 或 rollback
  • 其实我们说走到第5步,第6步,还有第7步的时候,他就可以再一次确认我们的消息是否要投递还是丢弃
  • 到这里,一直没有看到说有锁的存在,在高并发的情况下,消息队列就保证了我们最终的一致性
  • 就是说锁的存在,它一定是和高并发是这个对立的,我们尽量不要用锁的方式去考虑我们的并发

积分和库存业务场景的对比

  • 再回过头来看一下这个模型,如果你的生产者是订单,而消费者是库存的话
  • 如果库存不足,消费者是库存服务,库存不足,虽然成功的发送了到这个RocketMQ里
  • 但是库存没有办法成功消费这条消息,这个和其他业务形态上是不一样的
  • 比如订单服务,可以说是送积分,从技术角度来说,积分是没有上限的
  • 还有一种形态,就是我们说发短信,你成功的购买了某某产品等等
  • 这种业务形态, 你的生产者只要把消息放到了消息队列, 消息队列一定是可以保障的
  • 就是说你消息队列是集群吧,你在不挂的情况下,是一定能送达到消费者应用队列里的
  • 比如说, 积分服务,短信服务,你这边已经是commit了
  • 无论你是在第4步commit的,还是说第7步commit的下游是一定能消费到的
  • 但是库存服务不一样,如果库存不足了,你这边又没办法返回
  • 左边是库存服务和订单服务,右边是消息队列
  • 从正向来说,如果服务的提供方发送消息到这个消息队列,也就是生产者发送消息到消息队列
  • 只要消息队列集群不挂,那么我们的消费者是一定能收到这个消息的
  • 就是实现最终的一致性对于积分服务,短信服务的使用都是没有问题的
  • 因为积分理论上是无上限的,我们的短信是一定能发上去的,只要你短信账户里,有足够的余额
  • 但是当库存为零的时候,你的这个消息队列仍然收到了我们发送成功的消息
  • 但下游库存服务是没有办法消费成功的,我们不可能凭空多出来这么多库存
  • 让你去消费,因为没有那么多库存,我们又不能把这个消息队列成功投递库存不足的消息
  • 再返回给这个生产者,这个是不可能的,所以,我们能不能先发送一个归还库存的半消息
  • 这个半消息, 对于库存服务来说, 它是见不到的,我们发完半消息之后
  • 去调用扣减库存的Srv服务,这就是一个Grpc的这么一个调用,先看这个返回失败的情况
  • 如果调用库存失败了,这个时候返回一个rollback,因为一开始就是调用的是归还
  • 那你这个时候就调用rollback,如果我们库存执行失败了,那说明我们库存这个数据是没有变的
  • 既然你库存调用是失败,订单就不会创建, 因为我本地这个数据库就不会变
  • 那么我们两边的这个数据都没变,这个业务也是可以接受的
  • 就是说没有造成数据不一致,那你就不要给我发这个消息来告诉我,你要去归还库存了
  • 那我们直接rollback这个消息,然后这个消息队列, 就可以把这个归还库存的消息给它扔掉了
  • 扔掉之后,看左边这一边就没问题了,数据都没变
  • 你执行失败了,我这边又没执行,或者说,这两边的数据都保持一致,这就是OK的
  • 好,我们再看下一张执行成功的图,看我们订单服务发送一个半消息
  • 然后调用了Grpc扣减那个库存,然后它成功了
  • 成功之后, 我们就会执行这个本地 mysql 事务服务, 其实它可能成功,也可能失败
  • 因为我们如果在微服务里, 由于网络原因或宕机,Bug,停电等各种问题
  • 它都可能导致一个服务的运行失败
  • 如果我们先说这个执行本地mysql事务成功,在第4步成功,执行rollback
  • 还是从数据的角度来看,库存扣减成功,订单执行成功,我们本地也执行成功
  • 那就是说我们两边数据都改变了,这个业务上也是可以接受的
  • 订单生成成功了,库存也扣减了,那就相当于交易成功
  • 那你就不要给我发送这个归还库存的半消息了,所以是 rollback这个半消息
  • 然后,我们把这个消息就扔掉了
  • 那我们再看看,如果第4步执行失败了,就是说我们有任何情况
  • 订单服务有bug,断电或者其他场景,执行失败,那就执行一个commit
  • 因为订单执行失败了,相当于订单数据没有变,那你的库存现在是变了
  • 因为之前第三步已经执行成功了,那这个时候就要告诉库存,说给我扣减了,因为我执行失败了
  • 失败以后,提交一个commit之后,然后,这个库存服务就可以监听到这个消息队列里
  • 因为它 commit 了嘛,这个消息就能看到了,订阅了这个消息之后,就能去归还库存了
  • 如果你这个订单服务,还有一些其他问题,怎么办?其实这个消息队列还提供一种机制
  • 就是回查这个消息,比如说我现在不确定你这个是要提交还是rollback
  • 这个回查机制,就查这个订单的服务,那你还去你这个本地事务的数据库库里去捞数据
  • 你捞对了,就rollback,捞错了,还是commit, 你commit之后
  • 我还是能调用到这个库存服务,然后你再给我归还
  • 这张图就是看到了为了保持这个数据的一致性,我们这边整个业务流程的保证就是这样了
  • 再看上面这张图,还有问题,是在原来的基础上增加了第8条发送延迟消息和监听延迟消息。
  • 就是说我这个库存有一百个,我这个用户买完以后,就是不支付
  • 如果他一周不支付或者一个月不支付,你的库存永远不释放,别人永远买不了
  • 那不就把这个商城的库存给锁死了
  • 当我库存执行成功,这个本地的事务也执行成功的时候,我就把它发送一条延迟消息。
  • 假如我们规定半个小时,时间一到,这个延迟消息就会投递
  • 然后,我们就会根据这个消息去看,这个订单是 支付成功了,还是支付失败了
  • 如果是未支付或者是支付失败都可以,如果你执行失败了,那我就归还库存
  • 因为对商城来说,如果没收到钱,那我就归还库存,半个小时之后,仍然其他的用户就可以买
  • 这样就完美的解决了库存,订单和这个订单下单成功后不支付的这么一个场景
  • 这里的核心重点是:在一开始发送了一个归还库存的半消息
  • 执行commit和rollback的情况是反着来的

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一维信号循环平移小波降噪方法(MATLAB R2021b)

循环平移算法由Coifman和Donoho最先提出,其基本原理是将信号进行循环平移,将平移后的信号降噪后再做逆循环平移,改变平移位数,多次重复上述运算,将获得的所有结果求平均,得到最后的结果。 在理想情况下&am…

【C++】深入理解decltype和decltype(auto)

深入理解decltype和decltype(auto) 一、decltype语法介绍二、decltype的推导规则1. expr不加括号2. expr加上括号 三、关于decltype的CV属性推导四、 decltype(auto) 的使用 一、decltype语法介绍 decltype关键字是C11新标准引入的关键字,它…

html--酷炫背景引导主页

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>ZZVIPS酷炫背景引导主页</title><meta name"viewport" content"widthdevice-width,initial-scale1,maximum-scale1,user-scala…

社区贡献者分享 | OpenVINO™ 代码贡献助力我的开源之路

点击蓝字 关注我们,让开发变得更有趣 作者 | 占俊坚 排版 | 李擎 摘要 在 OpenVINO™ 2024.1 release 版本中&#xff0c;我为 OpenVINO™ 添加了 TensorFlow 中的 Rint operation 以及 PyTorch 中的 aten::bucketize operation 的支持&#xff0c;在此分享我的实现过程&#x…

最快的开源UDP传输工具:Kcptun

Kcptun&#xff1a;极速网络隧道&#xff0c;让数据传输飞起来&#xff01;- 精选真开源&#xff0c;释放新价值。 概览 kcptun 是一个轻量级、高性能的TCP/UDP网络加速工具&#xff0c;由xtaci开发并托管在GitHub上。它通过使用kcp协议&#xff0c;为网络数据传输提供了一个快…

深度解析:AI Prompt 提示词工程的兴起、争议与未来发展

PART1: 提示词工程的兴起 在人工智能领域中&#xff0c;一个新的领域——提示词工程&#xff08;prompt engineering&#xff09;——开始显露头角。 这个领域的核心在于精心设计输入&#xff0c;以引导AI模型产生特定的、期望的输出。 随着AI技术的飞速发展&#xff0c;特别…

移除重复节点---链表

面试题 02.01. 移除重复节点 - 力扣&#xff08;LeetCode&#xff09; 链表指针p和curr 与head指向同一块空间&#xff1b; p和head来比较相同的值&#xff0c;遇到一样的值、就改变这个空间里面struct的成员变量next指针指向的地址&#xff0c;跳向next的next再比较&#xf…

深度网络学习笔记(二)——Transformer架构详解(包括多头自注意力机制)

Transformer架构详解 前言Transformer的整体架构多头注意力机制&#xff08;Multi-Head Attention&#xff09;具体步骤1. 步骤12. 步骤23. 步骤34. 步骤4 Self-Attention应用与比较Self-Attention用于图像处理Self-Attention vs. CNNSelf-Attention vs. RNN Transformer架构详…

Kimichat使用案例010:快速识别出图片中的表格保存到Excel

文章目录 一、介绍二、图片信息三、输入内容四、输出内容五、markdown提示词六、markdown输出一、介绍 如果有一张图片格式的表格,想要快速复制到Excel表格中,那么一般要借助于OCR工具。之前试过不少在线OCR工具,识别效果差强人意。其实,kimichat就可以非常好的完成这个任务…

为什么需要在微服务中使用链路追踪?Spring Cloud 可以选择哪些微服务链路追踪方案?

引言&#xff1a;在当今的软件开发领域中&#xff0c;微服务架构已经成为了构建大型应用程序的主流方式之一。随着微服务数量的增加和服务之间复杂性的提高&#xff0c;对于了解和监控服务之间的调用关系变得越来越重要。而链路追踪技术的出现&#xff0c;为解决这一难题提供了…

心链13---主页切换功能 + loading特效 + 导航栏完善 + 队伍页接口修改

心链 — 伙伴匹配系统 直接取出所有用户&#xff0c;依次和当前用户计算分数&#xff0c;取 TOP N&#xff08;54 秒&#xff09; 优化方法&#xff1a; 切忌不要在数据量大的时候循环输出日志&#xff08;取消掉日志后 20 秒&#xff09;Map 存了所有的分数信息&#xff0c;占…

[ROS 系列学习教程] 建模与仿真 - 使用 Arbotix 控制机器人

ROS 系列学习教程(总目录) 本文目录 一、Arbotix 简介二、安装Arbotix三、配置Arbotix控制器四、配置launch启动文件五、数据交互接口六、在rviz中仿真控制机器人6.1 直接发topic控制6.2 使用键盘控制6.3 编写代码控制机器人移动 前面讲了机器人的建模&#xff0c;是静态的&…

力扣 240.搜素矩阵II

题目描述&#xff1a; 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9…

Kali Linux 2024.2 释出

渗透测试发行版 Kali Linux 释出了最新的 2024.2。 主要新特性包括&#xff1a;桌面环境更新到 GNOME 46&#xff0c;Xfce 环境加入 HiDPI 模式&#xff0c;更新了网络侦察工具 AutoRecon&#xff0c;监视 Linux 进程的命令行工具 pspy&#xff0c;提取和显示 CVE 信息的 Splo…

Oxlint 会取代 Eslint 吗?

最近&#xff0c;一个基于 Rust 的代码检查工具 Oxlint 在国外前端社区引起了热议&#xff0c;许多专家对其给予了高度评价。那么&#xff0c;相比于它的大哥 Eslint&#xff0c;Oxlint 有哪些优势&#xff1f;它会在未来取代 Eslint 吗&#xff1f;本文将讨论这个话题。 Oxc 和…

XUbuntu22.04之ssh+x11显示远程图形到本机(二百四十四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

[羊城杯 2023]CSGO

主函数初始化时&#xff0c;有反调试检测 打个断点在前面&#xff0c;然后nop掉 go语言的主函数是main_main 直接来到main_main&#xff0c;发现能可能是base64变表 在前面打个断点&#xff0c;F9 此处为base64变表&#xff0c;来到v25的地址处 得到变表LMNOPQRSTUVWXYZab…

[大模型]CharacterGLM-6B Transformers部署调用

环境准备 在autodl平台中租一个3090等24G显存的显卡机器&#xff0c;如下图所示镜像选择PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打开刚刚租用服务器的JupyterLab&#xff0c;并且打开其中的终端开始环境配置、模型下载和运行demo。 pip换源和安装依赖包 …

PyQt5 多进程 多任务 多线程实现进度条功能 无边框 含源码

概述&#xff1a; 在项目 中我们常遇到&#xff0c;大量计算或者加载数据时&#xff0c;需要用到多线程&#xff0c;此时只能等待&#xff0c;我们这个时间需要添加一下进度条&#xff0c;告诉用户当前需要等待&#xff0c;这时间就需要用到多线程和等待进度条&#xff1b; 效…

SpringCloudAlibaba基础二 Nacos注册中心

一 什么是 Nacos 官方&#xff1a;一个更易于构建云原生应用的动态服务发现(Nacos Discovery )、服务配置(Nacos Config)和服务管理平台。 集 注册中心配置中心服务管理 平台。 Nacos 的关键特性包括: 服务发现和服务健康监测动态配置服务动态 DNS 服务服务及其元数据管理 …