分布式知识整理

一、分布式事务

1、tcc(最终一致性)

  • 一般使用tcc分布式事务框架
  • 实现的功能需要修改的代码比较多,需要个个系统配合完成try、commit和cancel方法
  • 有try、commit和cancel三个阶段
  • TCC是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。
  • try阶段保证各自服务本地资源一致
  • commit 和cancel只会有一个被执行
  • try阶段有服务失败将触发cancel 如果cancel失败,那么走补偿机制,保证最终一致性
  • 不会阻塞资源
  • 执行流程
    1) 成功流程:事务框架->try(请求所有服务预留业务资源,不阻塞)->成功->commit(所有服务正式提交修改)
    2) 失败流程:事务框架->try(请求所有服务预留业务资源,不阻塞)->失败->cancel(告知所有服务取消预约)
    3) commit/cancel 如果失败了,那么走补偿机制,保证最终一致性

    3、xa两段提交(强一致性)(阻塞)

  • 分为协调者(xa协调工具)、参与者(各服务)
  • XA是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。
  • 只有try 和commit 两个阶段
  • MySQL中只有InnoDB引擎支持XA协议
  • MySQL中只有当隔离级别为Serializable(最高界别,串行)时候才能使用分布式事务
  • 执行流程
    1) 成功流程:协调者->try(询问所有服务是否可以执行,持有资源的锁)->成功->协调者通知commit(所有服务正式提交修改),解除资源锁定
    2) 失败流程:协调者->try(询问所有服务是否可以执行,持有资源的锁)->失败->协调者通知rollback,解除资源锁定

2、mq事务消息(最终一致性)

  • 实现的功能需要修改的代码相对较少,消费端几乎不需要任何修改
  • 只能保证(生产端的业务和消息投递到mq同时成功)
  • 消费端消费失败走补偿机制,保证最终一致性
  • 执行流程
    1) 服务a向mq发送prepare消息(本地事务,消费端不会收到)->mq得到返回给服务a执行结果->只能服务a本地业务
    2) 服务a本地业务执行成功->向mq发送事务消息的提交commitlog->消息出现在真实的mq消息中->消费端接收处理
    3) 服务a本地业务执行失败->向mq发送事务消息的撤销commitlog->移除事务消息
    4) 如果mq未收到事务的commit/rollback则会回查事务状态,然后继续执行

    4、最大努力通知

  • 不可靠消息:业务活动主动方,在完成业务处理之后,向业务活动的被动方发送消息,直到通知N次后不再通知,允许消息丢失(不可靠消息)。
  • 定期校对:业务活动的被动方,根据定时策略,向业务活动主动方查询(主动方提供查询接口),恢复丢失的业务消息。

    5、可靠消息最终一致性

  • 是指产生消息的业务动作与消息发送的一致
  • 如果业务操作成功,那么由这个业务操作所产生的消息一定要成功投递出去
  • 异步确保性
  • 一般可以使用mq事务消息实现

    二、分布式锁

    1、基于缓存(Redis等)实现分布式锁

  • 主要使用命令:
    1)SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
    2)expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
    2)delete key :删除key。
  • 实现思想:
    1)获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。
    2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
    3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。

2、基于Zookeeper实现分布式锁

因为需要频繁的创建和删除节点,性能上不如Redis方式。

  • 实现思想:
    1)创建一个目录mylock;
    2)线程A想获取锁就在mylock目录下创建临时顺序节点;
    3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
    4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;
    5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。

3、基于数据库实现分布式锁;

性能差,不推荐,不需要了解