redis 分布式锁
加锁机制
如果一个客户需要加锁,且客户端面对的是一个redis集群,则客户端会根据hash值获取一台机器来进行加锁,会发送一大段lua脚本进行执行,保证代码的原子性(首先判断锁是否存在,添加一个锁到redis中,最后设置过期时间)
锁互斥机制
当第二个客户端来访问的时候通过判断发现锁已经存在,则判断当前客户端是否存在,显然是不存在的,客户端二则进入while循环阶段,尝试加锁
watch dog 自动延时机制
默认的锁的生存时间为30秒,如果超过30秒,客户端1还想拥有当前锁,则启动看门狗机制,不断延长锁的时间10秒
可重入锁机制
当客户端1再次加锁则,锁对应的数字加一
释放锁机制
锁释放的时候在锁的基数上递减直到为0,再通过del删除锁
分布式事物
两阶段提交(2PC)
1.准备阶段
协调者会给各参与者发送准备命令,你可以把准备命令理解成除了提交事务之外啥事都做完了。
同步等待所有资源的响应之后就进入第二阶段即提交阶段(注意提交阶段不一定是提交事务,也可能是回滚事务)。
假如在第一阶段所有参与者都返回准备成功,那么协调者则向所有参与者发送提交事务命令,然后等待所有事务都提交成功之后,返回事务执行成功。
2.提交阶段
第一种是第二阶段执行的是回滚事务操作,那么答案是不断重试,直到所有参与者都回滚了,不然那些在第一阶段准备成功的参与者会一直阻塞着。
第二种是第二阶段执行的是提交事务操作,那么答案也是不断重试,因为有可能一些参与者的事务已经提交成功了,这个时候只有一条路,就是头铁往前冲,不断的重试,直到提交成功,到最后真的不行只能人工介入处理。
三阶段事物
1、 引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
1.CanCommit阶段
事务询问 协调者 向 参与者 发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待 参与者 的响应。
响应反馈 参与者 接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No
2.PreCommit阶段
在阶段一中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。这里的PreCommit阶段 跟上面的第一阶段是差不多的,只不过这里 协调者和参与者都引入了超时机制 (2PC中只有协调者可以超时,参与者没有超时机制)。。
3.DoCommit阶段
执行commit
补偿事务(TCC)
TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:
Try 阶段主要是对业务系统做检测及资源预留
Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
举个例子,假入 Bob 要向 Smith 转账,思路大概是: 我们有一个本地方法,里面依次调用
首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。
在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。
如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。
优点: 跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些
缺点: 缺点还是比较明显的,在2,3步中都有可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理