本地事务、分布式事务、

本文探讨了进程间通信的不同方式,如管道、信号、信号量、消息队列、共享内存和套接字,以及数据库事务的原子性、隔离性、持久性和一致性实现,包括两阶段提交和三阶段提交。重点介绍了MVCC和分布式事务中的可靠消息队列在这些问题上的作用。
摘要由CSDN通过智能技术生成

进程之间的通讯方式

管道(Pipe)
管道其实类似于两个进程间的桥梁,用于进程间传递少量的字符流和字节流。
管道的典型的应用就是命令行中的“|”操作符号:比如说,命令“ps -ef | grep java"就是管道操作符命令
信号(Signal)
信号是用来通知目标进程有某种事件发生的。除了用于进程间的通信外,信号还可以被发送给进程自身。信号的典型应用机会kill命令。比如“kill - 9 ppid",意思就是由Shell进程向指定PID的进程发送SIGKILL信号
信号量
信号量是用用于两个进程之间同步协作的手段。相当于操作系统提供的一个特殊变量。我们可以在信号量上,进行wait()和notify()操作。
消息队列(Message Queue)
前面三种方式都只适合少量信息传递。而消息队列用于进程间通讯的方法。进程可以向队列中添加消息,而被赋予读权限的进程则可以从队列中消费消息。消息队列就克服了信号承载信息量少,管道只能用于无格式字节流,以及缓冲区大小受限等缺点,但实时性相对受限制

共享内存
允许多个进程可以访问同一块空间,这是效率最高的进程间通讯的形式。进程间的内存地址空间是独立隔离的,但操作系统提供了让进程主动创建、映射、分离、控制某一个内存的接口。由于内存是多进程间共享的。所以往往会和其他通信机制结合使用

本地套接字
消息队列和共享内存这两种方式,只适合用于单机多进程间的通讯。而套接字接口,是更为普适的进程间通信机制,可用于不同机器之间的进程通信。(Socket)

本地事务如何实现原子性和持久性

原子性:要么同时成功,要么同时失败
隔离性:在不同业务的处理过程中,A事务和B事务是相互隔离独立的,互不影响
持久性:所有被提交的事务被成功提交后都能够正确的被持久化,不丢失数据
一致性:事务操作前后结果是一致的,比如总共有100块钱,不管怎么转账,总和就是100块钱
本地事务
就是指操作特定单一事务资源的、不需要“全局事务管理器”进行协调的事务。本地事务最基础的一种事务处理方案、通常只适用于单个服务使用单个数据源的场景,他是直接依赖底层数据库的支持。
事务的开启、终止、提交、回滚、嵌套、设置隔离级别、乃至与应用的代码贴近的传播方式,全部都要依赖底层数据库的支持
通过写日志来保证持久性和原子性是业界比较主流的做法,这个做法的困难点就是如何处理日志“写入中”的中间状态,才能保证严谨,也能够高效
还有一种Shadow Paging实现原子性和持久性,大概思路就是对数据的变动会写到硬盘的数据中,但并不是直接地修改原先的数据,而是将原来的数据复制一份副本保留原数据,修改副本,同时保存两份,一份修改前的数据,一份修改后的数据,这种的坏处就是性能比较差

本地事务如何实现隔离性

现代数据库几乎都提供了以下三种锁:
写锁(Write Lock):只有持写锁的事务才能对数据进行写入
读锁(Read Lock) :多个事务可以对同一个数据添加多个读锁,数据被加上读锁后就不能被加上写锁,所以其他事务不能对该数据进行写入,但是仍然可以读取,如果该数据只有一个事务加了读锁,那可以直接升级成写锁。
范围锁(Range Lock) 对于某个范围直接加排他锁,在这个范围内的数据不能被读取,也不能被写入。

本地事务的四种隔离级别
串性化:所有事务都串性排队执行,对所有事务的读写都加上读锁、写锁、范围锁
可重复读(Reapeatable Read) :就是对事务所涉及到的数据加读锁和写锁,并且持续到事务结束,但不再加范围锁。所以会存在幻读的情况

读以提交:以提交读事务涉及到的数据加的写锁,会持续到事务结束,但加的读锁在查询操作完成后会马上释放。所以会存在不可重复读问题

读未提交:未提交读涉及到的数据只加写锁,这会一致持续到事务结束,但完全不加读锁。
MVCC基础原理
mvcc是一种读取优化策略,它的“无锁”是特指读取时不需要加锁。MVCC的基础思路就是对数据库的任何修改都不会直接覆盖之前的数据,而是产生一个新的版本副本与老版本共存,以此来达到读取时可以完全不加锁的目的
这句话的版本,可以理解为数据的每一行记录都存在两个看不见的字段:
create_version和delete_version,这两个字短纪录的值都是事务ID(事务ID是一个全局严格递增的数值)然后
**数据插入时:**create_version记录插入数据的事务ID,delete_version为空
数据被删除时:delete_version记录删除数据的事务ID,create_version为空
**数据被修改时:**将修改视为“删除旧数据,插入新数据”即先将原来的数据复制一份,原用的数据delete_version记录修改为事务ID,create_version为空,复制出来的新数据create_version记录修改数据的事务ID,delete_version为空

隔离级别是可重复读:相当于读取create_version小于当前事务ID的记录即可,在这个前提下,如果数据仍然有多个版本,则取最新(事务ID最大的)
隔离级别是读以提交:总是取最新的版本即可
mvcc只是针对读+写的场景优化,写+写没有优化空间

全局事务和共享事务是如何实现的

全局事务即外部事务:一种适用于单个服务使用多个数据源场景的事务解决方案
XA协议
XA事务处理框架的核心内容就是定义了,全局的事务管理器(Transacntion Manager,用于协调全局事务)和局部的资源管理器(Resource Manager,用于驱动本地事务)直接的通讯接口
XA接口是双向的,是一个事务管理器和多个资源管理器之间通信的桥梁,通过协调多个数据源的动作保持一致,来实现全局事务的统一提交或统一回滚。
Java 专门定义了一套全局事务处理标准:它主要有两个接口
事务管理器的接口:javax.transaction.TransactionManager,这套接口是Java EE服务器提供给容器事务使用的,另外还提供了一套Javax.transaction.UserTransaction接口,用于给程序员通过程序代码手动开启、提交和回滚事务。

两阶段提交
准备阶段:又叫做投票阶段。在这一阶段,协调者询问事务的所有参与者是否准备好提交,如果已准备好提交回复Prepare,否则回复no-preapare
提交阶段:又叫执行阶段,协调者如果准备阶段收到所有事务参与者回复的Prepare消息,首先会在本地持久化状态为Commit指令。所有参与者立即执行提交操作,如果中间有任意一个事务参与者回复了no-preapare全部回滚
对于数据库来说,提交阶段的操作相对是比较轻的,通常能够快速完成,但是回滚阶段相对比较耗时。
两阶段提交问题
单点问题:协调者在两阶段提交中的角色很重要,协调者等待参与者回复可以有超时机制,允许参与者宕机,但是协调者宕机了,所有参与者都会受到影响。如果协调者者一直没有回复,所有参与者都必须等待
性能问题 两阶段提交过程中,所有事务参与者相当于被绑定成为一个统一调度的整体,期间经过两次远程服务调用、三次持久化(准备阶段写重做日志,协调者做状态持久化、提交阶段在日志中写入Commit record)整个过程需要持续到集群中最慢的那一个处理操作结束为止。这性能很差
一致性风险部分协调者受到commit命令,部分没收到,导致部分事务数据提交,部分没提交

三阶段提交
为了阶段两阶段提交的单点问题、性能问题、数据一致性问题,三阶段提交出现,就是在提交阶段,增加一个doCommit询问阶段,评估一下每个事务参与者数据库的自身状态,评估该事务是否可以顺利完成,但是最终一致性问题还是存在

分布式事务之可靠消息队列

持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值