系统经sharding改造之后,原来单一的数据库会演变成多个数据库,如何确保多数据源同时操作的原子性和一致性是不得不考虑的一个问题。总体上看,目前对于一个分布式系统的事务处理有三种方式:分布式事务、基于Best Efforts 1PC模式的事务以及事务补偿机制。我们下面对这三种处理方式一一进行分析。
分布式事务
这是最为人们所熟知的多数据源事务处理机制。本文并不打算对分布式事务做过多介绍,读者可参考此文:关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 。在这里只想对分布式事务的利弊作一下分析。
 
优势:
1. 基于两阶段提交,最大限度地保证了跨数据库操作的“原子性”,是分布式系统下最严格的事务实现方式。
2. 实现简单,工作量小。由于多数应用服务器以及一些独立的分布式事务协调器做了大量的封装工作,使得项目中引入分布式事务的难度和工作量基本上可以忽略不计。
 
劣势:
系统“水平”伸缩的死敌。基于两阶段提交的分布式事务在提交事务时需要在多个节点之间进行协调,最大限度地推后了提交事务的时间点,客观上延长了事务的执行时间,这会导致事务在访问共享资源时发生冲突和死锁的概率增高,随着数据库节点的增多,这种趋势会越来越严重,从而成为系统在数据库层面上水平伸缩的”枷锁”, 这是很多Sharding系统不采用分布式事务的主要原因。
 
基于Best Efforts 1PC模式的事务
与分布式事务采用的两阶段提交不同,Best Efforts 1PC模式采用的是一阶段端提交,牺牲了事务在某些特殊情况(当机、网络中断等)下的安全性,却获得了良好的性能,特别是消除了对水平伸缩的桎酷。Distributed transactions in Spring, with and without XA一文对Best Efforts 1PC模式进行了详细的说明,该文提供的Demo代码更是直接给出了在Spring环境下实现一阶段提交的多数据源事务管理示例。不过需要注意的是,原示例是基于spring 3.0之前的版本,如果你使用spring 3.0+,会得到如下错误:java.lang.IllegalStateException: Cannot activate transaction synchronization – already active,如果使用spring 3.0+,你需要参考spring-data-neo4j的实现。鉴于Best Efforts 1PC模式的性能优势,以及相对简单的实现方式,它被大多数的sharding框架和项目采用。
 
事务补偿机制
对于那些对性能要求很高,但对一致性要求并不高的系统,往往并不苛求系统的实时一致性,只要在一个允许的时间周期内达到最终一致性即可,这使得事务补偿机制成为一种可行的方案。事务补偿机制最初被提出是在“长事务”的处理中,但是对于分布式系统确保一致性也有很好的参考意义。笼统地讲,与事务在执行中发生错误后立即回滚的方式不同,事务补偿是一种事后检查并补救的措施,它只期望在一个容许时间周期内得到最终一致的结果就可以了。事务补偿的实现与系统业务紧密相关,并没有一种标准的处理方式。一些常见的实现方式有:对数据进行对帐检查;基于日志进行比对;定期同标准数据来源进行同步,等等。
 
小结
分布式事务,最严格的事务实现,但性能是个大问题;Best Efforts 1PC模式,性能与事务可靠性的平衡,支持系统水平伸缩,大多数情况下是最合适的选择;事务补偿机制,只能适用于对事务性要求不高,允许数据“最终一致”即可的系统,牺牲实时一致性,获得最大的性能回报。

DB 分库分表(4):多数据源的事务处理的更多相关文章

  1. DB 分库分表的基本思想和切分策略

    DB 分库分表的基本思想和切分策略 一.基本思想 Sharding的基本思想就要把一个数据库切分成多个部分放到不同的数据库(server)上,从而缓解单一数据库的性能问题.不太严格的讲,对于海量数据的 ...

  2. DB 分库分表(5):一种支持自由规划无须数据迁移和修改路由代码的 Sharding 扩容方案

    作为一种数据存储层面上的水平伸缩解决方案,数据库Sharding技术由来已久,很多海量数据系统在其发展演进的历程中都曾经历过分库分表的Sharding改造阶段.简单地说,Sharding就是将原来单一 ...

  3. DB 分库分表(2):全局主键生成策略

    DB 分库分表(2):全局主键生成策略 本文将主要介绍一些常见的全局主键生成策略,然后重点介绍flickr使用的一种非常优秀的全局主键生成方案.关于分库分表(sharding)的拆分策略和实施细则,请 ...

  4. DB 分库分表(1):拆分实施策略和示例演示

    DB 分库分表(1):拆分实施策略和示例演示 第一部分:实施策略 1.准备阶段 对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系统业务逻辑和数据库schema.一个好的建议是绘制一 ...

  5. DB 分库分表(3):关于使用框架还是自主开发以及 sharding 实现层面的考量

    当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产品可供参考,同时很多团队也会选择自主开发实现,而不管是选 ...

  6. 三、SpringBoot 整合mybatis 多数据源以及分库分表

    前言 说实话,这章本来不打算讲的,因为配置多数据源的网上有很多类似的教程.但是最近因为项目要用到分库分表,所以让我研究一下看怎么实现.我想着上一篇博客讲了多环境的配置,不同的环境调用不同的数据库,那接 ...

  7. 基于AOP和HashMap原理学习,开发Mysql分库分表路由组件!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 什么?Java 面试就像造火箭 单纯了! 以前我也一直想 Java 面试就好好面试呗 ...

  8. Django 数据库读写分离 分库分表

    多个数据库 配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BA ...

  9. 超实用的mysql分库分表策略,轻松解决亿级数据问题

    一.分库分表的背景 在数据爆炸的年代,单表数据达到千万级别,甚至过亿的量,都是很常见的情景.这时候再对数据库进行操作就是非常吃力的事情了,select个半天都出不来数据,这时候业务已经难以维系.不得已 ...

随机推荐

  1. BZOJ4241历史研究题解--回滚莫队

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4241 分析 这题就是求区间权值乘以权值出现次数的最大值,一看莫队法块可搞,但仔细想想,莫 ...

  2. 05 正确运行一个Go程序

    Go代码文件,程序中必须指定启动函数main() Hello.go package main //声明为main包,即可以编译成二进制程序 import "fmt" //导入fmt ...

  3. JavaScript函数式编程——柯里化

    柯里化原理 如何实现柯里化 柯里化的应用 一.柯里化原理 柯里化:在数学和计算机科学中,柯里化是一种使用多个参数的一个函数转换成一系列使用一个参数的函数的技术. 前端使用柯里化的用途主要就应该是简化代 ...

  4. 禁用div元素(不可点击)

    style="pointer-events: none;" 可以封装使用 .disable { pointer-events: none; } //禁用 $.fn.disable ...

  5. yii2 response多次输出问题的查找

    { "IsSuccess": 1, "ErrMsg": "OK", "Data": { "IsSuccess& ...

  6. 使用脚本启动fabric时出错

    Error: got unexpected status: BAD_REQUEST -- error authorizing update: error validating ReadSet: rea ...

  7. docker一键搭建Nginx+PHP环境(含自动部署命令)

    文章的主要部分是一步一步的教程,文章的最后是我整理好的一键安装命令,自动下载并安装docker,构建镜像,启动容器集群(压缩包内注释覆盖范围达到80%) 大家可以看完教程亲自尝试下,也可以直接执行一键 ...

  8. 怎么处理Win7电脑打开软件速度慢的情况?

    很多使用Win7系统的用户都会发现这么一个问题,就是电脑在使用过一段时间后,打开一个应用软件的速度就会变慢,非常耽误时间.下面就和大家分享一个解决Win7系统应用软件打开速度慢的小技巧. Win7系统 ...

  9. /proc/filesystems各字段含义

    /proc/filesystems A text listing of the filesystems which were compiled into the kernel. Incidentall ...

  10. Tomcat控制台日志输出到本地文件

    记事本打开startup.bat文件,修改如下内容 “call “%EXECUTABLE%” start %CMD_LINE_ARGS%” 改为 call "%EXECUTABLE%&quo ...