在分布式环境中使用状态机支持数据的一致性

简介

在本文中,我们将介绍如何在分布式系统中使用transaction以及分布式系统中transaction的局限性。然后我们通过一个具体的例子,介绍了一种通过设计状态机来避免使用transaction的方法。

什么是数据库transaction

Transaction是关系型数据普遍支持的一种操作。Transaction可以包含若干对数据库的操作。如果任何操作失败,所有的操作都被取消,数据保持transaction执行前的状态。这种情况叫回滚(rollback)。假如所有操作成功,transaction被认为成功。这种情况叫做提交(commit)。Transaction需要支持所谓的ACID。因为我们这种主要介绍NO-SQL数据库的transaction,ACID就不详细说了,如果不熟悉大家可以自行阅读。Transaction对于维护数据的完整性非常重要。比如说对于在两个银行账户之间的转账操作,从一个账户扣除金额和向一个账户增加金额就应该放在一个transaction里。否则只完成了扣除操作或者只完成增加操作,都会破坏数据的完整性,恢复起来非常麻烦。

No-SQL数据库的transaction

不少No-SQL数据库也支持transaction,但是普遍来说No-SQL数据库对transaction的支持相对较弱。主要原因是No-SQL数据库一般都是基于分布式的架构设计和实现的,而transaction的某些特性是和分布式系统有冲突的。比如说,在分布式系统中,我们往往放弃数据的强制一致性而追求整体系统的可用性。但是数据可能存在不一致的状态对于维护transaction的原子性和一致性是非常大的挑战。

我们在这里以AWS的DynamoDB为例。DDB支持两种transaction:写transaction和读transaction。写transaction可以支持最多100个写操作,包括put(创建),update(更新),delete(删除),和conditionCheck(条件检查)。而读transaction可以支持最多100个读操作,也就是通过primary key获取一个item,即Get。关于DDB的transaction的介绍可以参考这篇文档。

问题

现在我们在DDB中有四张表。表1保存了某种记录,该记录拥有自己的primary key,同时该记录还拥有3种其它的属性可以作为index。另外3张表即用来保存某种index到该记录的primary key的对应关系。关系如下所示:

需要说明的是每一种index都可能有多个值,也就是说在item里每种index都是一个list。比如说对于一个item,我们可能有3个index1,5个index2,10个index3。这样我们就要在index1表中创建3条记录,在index2表中创建5条记录,在index3中创建10条记录。很明显,我们需要保持item和它相关的index的完整性。也就是说我们不希望出现如下的情况:

  1. Index存在,但是其索引的item已经被删除了;
  2. Index存在,但是它已经不该索引到当前的item了;
  3. Item存在,但是它的某个index丢失了;
  4. 。。。

如果我们考虑使用DDB transaction来解决这个问题,我们会发现我们可能面临下面两个问题:

  • 一个item和它的索引数目大于100,所以DDB transaction无法支持该操作;
  • 因为有太多的数据要被一起更新,有很大的概率更新之间经常互相冲突,造成transaction的commit的成功率很低。

那么我们该如何解决这个问题呢?

解决方案

通过分析,我们发现这个问题其实可以通过设计一个简单的状态机来解决。我们将该方法的细节描述如下。

首先,我们规定在更新item和index时,我们遵循以下的顺序:

  1. 更新index1
  2. 更新index2
  3. 更新index3
  4. 更新item

如果我们其中任何一个步骤失败的话,我们就终止掉本次更新,并且抛出一个异常,然后根据设定在某段时间后重新尝试更新。根据我们执行的过程,我们可能会有如下的状态和状态转换:

最开始假设我们处于一个合法的状态下,也就是说item的RVN和index的RVN是相等的,都是n。然后我们更新index成功,此时我们处于一个临时状态下,也就是index的RVN变成了n+1,但是item的RVN仍然是n。再然后我们更新item成功,我们就转换成下一个合法的状态,也就是item的RVN和index的RVN再次相等,都变成了n+1。有一个例外的不合法状态,就是item的RVN已经变成了n+1,但是index的RVN仍然是n。出现这种状态的原因是这个index被从RVN为n+1的数据中移除出去了,那么此时这个index就不能再被认为是该item的合法索引了。

现在我们在更新数据时逻辑非常简单,我们不需要做很多的比较和检查,仅仅是依照顺序依次更新index和item即可。那么在使用该index查询item时,我们就需要做一些检查工作,确保我们是通过合法的index找到了合法的item。首先,我们需要一个index的值,来获取该index的RVN。然后我们通过该index获取item和item的RVN。然后我们检查的具体逻辑如下:

  1. 假如index的RVN和item的RVN相等,那么我们得到的index和item都是合法的;
  2. 假如index的RVN大于item的RVN,那么我们得到的是一个临时状态数据。我们可以抛出一个异常,然后重新尝试读取数据;
  3. 假如index的RVN小于item的RVN,我们是否可以直接认为数据不合法而放弃呢?是不可以的。原因在于有可能在我们得到index的RVN和得到item的RVN之间有过一次更新,从而使得我们已经有的index的RVN变旧了。所以我们要再次查询一次index的RVN,然后分成下面三种情况进行处理:
    1. 如果新的index的RVN仍然等于之前得到的index的RVN,说明是index被移除的情况,此时我们应该认为通过该index查询不到item;
    2. 如果新的index的RVN和item的RVN相等了,说明我们得到了合法的数据;
    3. 如果新的index的RVN和item的RVN仍然不相等,并且新的index的RVN和之前的index的RNV也不相等,说明我们得到的是一个中间状态的数据。我们可以抛出异常然后重新尝试查询。

通过这个处理逻辑,我们是可以完成保证没有任何合法的数据被遗漏,通过也不会有任何非法的数据被使用的。

结论和扩展

本文中,我们介绍了一种通过设计状态机以达到最终数据一致性的方法来避免使用transaction的方法。在这里我们看到两个问题:第一,在分布式环境中的transaction通过有一定的局限性,并且transaction本身运行的代价也很大,所以我们在决定使用transaction的时候还要经过和其它方法的比较,以及分析可能出现的局限性和问题;第二,基于数据的最终一致性,我们可能会发现其它更简单的方法以避免使用transaction。但是需要说明的是,这里并不是简单的建议不使用transaction。事实上,transaction在很多情况下是最佳解决方案。只是提供一个在使用transaction之外的其它代替方案。

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

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

相关文章

java SSM流浪宠物救助与领养myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM流浪宠物救助与领养管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系…

安卓Java面试题21-30

🔥 21、AsyncTask使用在哪些场景?它的缺陷是什么?如何解决?🔥 AsyncTask 运用的场景就是我们需要进行一些耗时的操作,耗时操作完成后更新主线程,或者在操作过程中对主线程的UI进行更新。 缺陷: AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还…

Fragment

1.网格视图(随便插进来一条) 2.Fragment

谷歌开源的LLM大模型 Gemma 简介

相关链接: Hugging face模型下载地址:https://huggingface.co/google/gemma-7bGithub地址:https://github.com/google/gemma_pytorch论文地址:https://storage.googleapis.com/deepmind-media/gemma/gemma-report.pdf官方博客&…

Linux——文件标识符

目录 一、文件基础 二、常见的C语言文件接口 三、系统文件接口 四、理解语言与系统文件操作的关系 五、如何理解一切皆文件 六、文件标识符再理解 一、文件基础 一个空文件,也会占用磁盘空间,这是因为文件不仅仅有存放在里面的内容,还…

IO:实现文件拷贝的各种方法(观察每种函数中的参数和结束条件)

一、使用fscanf实现&#xff0c;将一个文件中的数据打印到终端上&#xff08;类似于cat一个文件&#xff09; #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat…

数组中删改元素(数据结构、顺序表、线性表)

给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面…

Chapter20-Ideal gases-CIE课本要点摘录、总结(编辑中)

20.1 Particles of a gas Brownian motion Fast modules 速率的数值大概了解下&#xff1a; average speed of the molecules:400m/s speed of sound:approximately 330m/s at STP&#xff08;standard temperature and pressure&#xff09; Standard Temperature and Pres…

ROS 2基础概念#5:执行器(Executor)| ROS 2学习笔记

在ROS 2中&#xff0c;Executor是一个核心概念&#xff0c;负责管理节点&#xff08;Node&#xff09;中的回调函数&#xff0c;如订阅消息的回调、服务请求的回调、定时器回调等。Executor决定了何时以及如何执行这些回调&#xff0c;从而在ROS 2系统中实现异步编程。 ROS 2 …

linux循环之until循环

1.until循环语法 until 循环控制条件 do commands done #until循环是在循环的顶部判断“循环控制条件”&#xff0c;如果“循环控制条件”一直为FALSE&#xff0c;那么就一直循环下去&#xff0c;这个与while循环刚好相反 2.until循环案例 [rootkibana ~]# cat until.sh…

七彩虹八渐变 外贸建站公司wordpress模板

进出口水果wordpress外贸模板 漂亮水果wordpress外贸模板&#xff0c;做水果进出品生意的外贸公司自建站官网模板。 https://www.jianzhanpress.com/?p3516 玩具wordpress外贸模板 简洁玩具wordpress外贸模板&#xff0c;适合做跨境电商外贸公司使用的wordpres外贸s网站主题…

FPGA 按键控制串口发送

按键消抖 消抖时间一般为10ms&#xff0c;我使用的板子是ACX720&#xff0c;晶振为50MHZ&#xff0c;20ns为一周期。 状态机 模块设计 设计文件 timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 2023/01/11 12:18:36 // Design Name: // Module Name…

IPv6扩展头(一)——逐跳选项头(Hop-by-Hop Options Header)

逐跳选项头&#xff08;Hop-by-Hop Options Header&#xff09;是IPv6协议中的一种扩展头部&#xff0c;它允许在数据包传输过程中每个跃点&#xff08;路由器或节点&#xff09;都能够读取并处理该头部中的信息。逐跳选项头的设计初衷是为了提供一种机制&#xff0c;在整个传输…

(学习总结)如何使用ChatGPT API训练自定义知识库

第一步&#xff1a; 安装OpenAI、GPT Index、PyPDF2和Gradio库 pip install openai pip install gpt_index pip install PyPDF2 pip install gradio 第二步&#xff1a;用VScode代码编辑器写app.py代码 记得替换api密钥 from llama_index import SimpleDirectoryReader, …

纯css实现太极八卦图

感觉最近好像闯鬼了&#xff0c;赶紧写个八卦图避避邪&#xff0c;开玩笑了&#xff0c;不废话&#xff0c;上菜&#xff0c;看效果上代码。 效果 代码&#xff0c;你们都是大佬&#xff0c;这里就不解释代码了 &#xff08;hover会转动喔&#xff09;。 <!DOCTYPE html&g…

LabVIEW智能Modbus监控系统

LabVIEW智能Modbus监控系统 在自动化和信息化迅速发展下&#xff0c;传统的监控系统已无法满足现代工业对于数据通讯和处理的高效率和高可靠性要求。为了解决这一问题&#xff0c;设计了一套基于LabVIEW的智能Modbus监控系统。该系统利用LabVIEW的图形化编程环境和Modbus协议的…

数字孪生10个技术栈:数据处理的六步骤,以获得可靠数据。

一、什么是数据处理 在数字孪生中&#xff0c;数据处理是指对采集到的实时或历史数据进行整理、清洗、分析和转化的过程。数据处理是数字孪生的基础&#xff0c;它将原始数据转化为有意义的信息&#xff0c;用于模型构建、仿真和决策支持。 数据处理是为了提高数据质量、整合数…

深入理解Servlet

目录&#xff1a; ServletWeb开发历史Servlet简介Servlet技术特点Servlet在应用程序中的位置Tomcat运行过程Servlet继承结构Servlet生命周期Servlet处理请求的原理Servlet的作用HttpServletRequest对象HttpServletResponse对象ServletContext对象ServletConfig对象Cookie对象与…

SpringBoot快速入门(介绍,创建的3种方式,Web分析)

目录 一、SpringBoot介绍 二、SpringBootWeb快速入门 创建 定义请求处理类 运行测试 三、Web分析 一、SpringBoot介绍 我们可以打开Spring的官网(Spring | Home)&#xff0c;去看一下Spring的简介&#xff1a;Spring makes Java simple。 Spring发展到今天已经形成了一种…

Android 多桌面图标启动, 爬坑点击打开不同页面

备注 &#xff1a; MainActivity 正常带界面的UI MainActivityBt 和 MainActivityUsb 是透明的&#xff0c;即 android:theme"style/TranslucentTheme" ###场景1:只有MainActivity 设置成&#xff1a;android:launchMode"singleTask" 点击顺序&#xff1…