事物,锁,数据库层面事物,应用层面事物,MQ事物,TCC补偿事物,2PC,3PC(2,3阶段事物提交)等

一、事物和锁

1、事务与锁是不同的。事务具有ACID(原子性、一致性、隔离性和持久性),锁是用于解决隔离性的一种机制。

2、事务的隔离级别通过锁的机制来实现。另外锁有不同的粒度,同时事务也是有不同的隔离级别的

3、开启事务就自动加锁。

4、事务的隔离级别

1)READ UNCOMMITTED(读取未提交内容)

所有事务可以看到未提交事务的执行结果,本隔离级别很少用到实际应用中,读取未提交的数据,又称为“脏读”。

2)READ COMMITTED(读取提交内容)

大多数数据库的默认隔离级别是此级别,但不是MySQL默认的。一个事务在开始的时候只能看见已提交事务所做的改变。一个事务从开始到提交前所做的任何改变都是不可见的,除非提交。这种隔离级别也称为不可重复读。

3)REPEATABLE READ(可重复读)

此隔离级别是为了解决可重复读隔离级别导致的问题即一个事务多个实例并发读取数据时会看到不同的结果。此隔离级别不会看到其他事务提交后的结果,即事务即使提交了我也看不到。此级别也称为“幻读”。

4)SERIALIZABLE(可串行化)

可串行化是最高的隔离级别,它通过强制事务排序,使之不可重读,解决了幻读的问题。此隔离级别会在每个读的数据行上加共享锁,使用这种隔离级别会产生大量的超时现象,一般实际开发中不会用到。

5、mysql加锁机制

1)根据类型可分为共享锁(SHARED LOCK)和排他锁(EXCLUSIVE LOCK)或者叫读锁(READ LOCK)和写锁(WRITE LOCK)。

2)根据粒度划分又分表锁和行锁。表锁由数据库服务器实现,行锁由存储引擎实现。mysql必须使用索引才会行级锁,否则就会表级锁。但是也不是绝对的,执行计划分析如果小表查询速度比使用索引快也会表级锁不是行级锁。

3)mysql提供了3种事务型存储引擎,InnDB、NDB Cluster和Falcon。

4)一个事务执行的任何过程中都可以获得锁,但是只有事务提交或回滚的时候才释放这些锁。这些都是隐式锁定,也可以显式锁定,InnoDB支持显式锁定,例如:

       4.1)SELECT .... LOCK IN SHARE MODE (加共享锁)

       4.2)SELECT .....FOR UPDATE(加排他锁)

5)多版本并发控制(重要)

5.1)Mysql的事务存储引擎不是简单实用行加锁机制,而是叫多版本并发控制(MVCC)技术,和行加锁机制关联实用。以便应对更高的并发,当然是以消耗性能作为代价。

5.2)每种存储引擎对MVCC的实现方式不同,InnoDB引擎的简单实现方式如下:

5.3)InnoDB通过为每个数据航增加两个隐含值的方式来实现。这两个隐含值记录了行的创建时间,以及过期时间。每一行存储事件发生时的系统版本号。每一次开始一个新事务时版本号会自动加1,每个事务都会保存开始时的版本号,每个查询根据事务的版本号来查询结果。

5.4)MySQL使用以下几种机制进行隔离性的实现:         

     a.锁机制,通过使用加锁机制,使用其它事务无法到读某事务末提交前的数据更新,解决脏读问题; mySQL 有:共享锁,排他锁,根据粒度,有行锁,表锁。         

    b.MVCC机制:事务存储引擎使用多版本并发控制(MVCC)技术,和行加锁机制关联使用         MySQL 的InnoDB,XtraDB 引擎通过 使用MVCC 来解决幻读问题。

二、分布式事物和分布式锁(https://blog.csdn.net/peng_0129/article/details/80000564)

1、什么是分布式锁?

1.1)锁是单个进程用来协调多个线程对共享资源进行同步访问。分布式锁就是用来协调多个进程下的所有线程多共享资源的同步访问。

1.2)实现方式

     1.2.1)redis版本

           关键点:redis本身是单线程的,而且 SETNX操作是一个原子操作。redis结构(lockName, lockTimeout)

     1.2.2) Zookeeper 版本

           完全分布式锁是全局同步的,这意味着在任何时刻没有两个客户端会同时认为它们都拥有相同的锁,使用 Zookeeper 可以实现分布式锁,需要首先定义一个锁节点(lock root node)。

需要获得锁的客户端按照以下步骤来获取锁:

                1.2.2.1)保证锁节点(lock root node)这个父根节点的存在,这个节点是每个要获取lock客户端共用的,这个节点是PERSISTENT的。

                 1.2.2.2) 第一次需要创建本客户端要获取lock的节点,调用 create( ),并设置节点为EPHEMERAL_SEQUENTIAL类型,表示该节点 为临时的和顺序的。如果获取锁的节点挂掉,则该节点自动失效,可以让其他节点获取锁。

                  1.2.2.3)在父锁节点(lockroot node)上调用 getChildren( ) ,不需要设置监视标志。 (为了避免“羊群效应”).

                  1.2.2.4)按照Fair竞争的原则,将步骤3中的子节点(要获取锁的节点)按照节点顺序的大小做排序,取出编号最小的一个节点做为lock的owner,判断自己的节点id是否就为owner id,如果是则返回,lock成功。如果不是则调用 exists( )监听比自己小的前一位的id,关注它锁释放的操作     (也就是exist watch)。  

                  1.2.2.5)如果第4步监听exist的watch被触发,则继续按4中的原则判断自己是否能获取到lock。 

                  1.2.2.6) 释放锁:需要释放锁的客户端只需要删除在第2步中创建的节点即可。

        注意事项:

          一个节点的删除只会导致一个客户端被唤醒,因为每个节点只被一个客户端watch,这避免了“羊群效应”。

        分布式锁总结解决方法:

             这里利用zookeeper的EPHEMERAL_SEQUENTIAL类型节点及watcher机制,来简单实现分布式锁。

            主要思想:

            1、开启10个线程,在disLocks节点下各自创建名为sub的EPHEMERAL_SEQUENTIAL节点;

            2、获取disLocks节点下所有子节点,排序,如果自己的节点编号最小,则获取锁;

            3、否则watch排在自己前面的节点,监听到其删除后,进入第2步(重新检测排序是防止监听的节点发生连接失效,导致的节点删除情况);

            4、删除自身sub节点,释放连接;

2、什么是分布式事务?

2.1)分布式事务就是一系列操作分布在各个应用当中

2.2)实现方式

       2.2.1)结合MQ消息中间件实现的可靠消息最终一致性

              可靠消息最终一致性,需要业务系统结合MQ消息中间件实现,在实现过程中需要保证消息的成功发送及成功消费。即需要通过业务系统控制MQ的消息状态
        2.2.2)TCC补偿性事务解决方案  

               TCC补偿性,分为三个阶段TRYING,CONFIRMING-CANCELING。每个阶段做不同的处理。
                       a:TRYING阶段主要是对业务系统进行检测及资源预留
                       b:CONFIRMING阶段是做业务提交,通过TRYING阶段执行成功后,再执行该阶段。默认如果TRYING阶段执行成功, CONFIRMING就一定能成功。

                 c:CANCELING阶段是回对业务做回滚,在TRYING阶段中,如果存在分支事务TRYING失败,则需要调用CANCELING将已预留的资源进行释放。

         2.2.3)最大努力通知型方案

                 最大努力通知xing型,这种方案主要用在与第三方系统通讯时,比如:调用微信或支付宝支付后的支付结果通知。这种方案也是结合MQ进行实现,例如:通过MQ发送http请求,设置最大通知次数。达到通知次数后即不再通知。

三,数据库层面分布事物,应用层面分布式事物

详情见:https://blog.csdn.net/Michaelwubo/article/details/81476417

详情见:https://blog.csdn.net/Michaelwubo/article/details/81476591

四,2pc和3pc

详情见:https://blog.csdn.net/Michaelwubo/article/details/81476547

猜你喜欢

转载自blog.csdn.net/Michaelwubo/article/details/81475284