Bootstrap

架构设计篇之微服务实战笔记(四)

第五章、微服务的事务与查询

分布式应用中的一致性难题

同步通信和异步通信

使用Saga开发跨多个服务的业务逻辑

利用API组合和CQRS实现微服务查询

5.1、分布式应用的事务一致性

为什么不要使用分布式事务

常见的方案

  • 二阶段提交

  • 三阶段提交

分布式事务适合耗时长的操作

5.2、基于事件的通信

事件和编排

每个服务可以在不了解整个流程结果的情况下响应各种事件,独立执行各种操作。其实就是我们常说的用MQ解藕应用,提升了并发效率和性能,也能从局部控制事务的故障和恢复,还减少了服务流程的复杂度。

5.3、Saga

Saga是一组互相协作的本地事务序列,在Saga中,每一步的操作都是由前一个步骤所触发。

5.3.1、编排型Saga

通过事件来将一个流程中的多个动作进行执行,回滚,补偿

优势和不足

  • 提高了每个服务的自治性

  • 引入额外的复杂度理解整个系统

  • 引入循环依赖问题

5.3.2、编配型Saga

通过维护一套状态机的机制来保证执行的有序,通过Saga日志来保证执行的事务可以保证跟踪和可回滚、补偿。但是同样如果出现重复的故障还是需要人工介入。

优势和不足

  • 逻辑存放到协调器

  • 服务趋向贫血服务,将太多业务迁移到协调器

  • 执行较长的耗时服务,可以采用AWS的Step Workflows,Netf li x的Conductor

5.3.3、交织型Saga

不同于ACID类型的事物,Saga不具备隔离性。每个本地事务的结果对其他事务而言都是立即可见的,所以中间态的时候就会产生其他的业务并行情况干扰正常业务。

处理这种Saga交叉的情况有3种策略:短路,加锁,中断

  • 短路:老的未处理完毕,新的不允许发起

  • 加锁:开发者可以用锁来控制(预防死锁)

  • 中断:开发者可以中断执行的动作,避免了死锁

5.3.4、一致性模式

Saga严重依赖补偿操作。

5.3.5、事件溯源

完全依赖实体上的一系列的事件来表示状态。具体参考GitHub上的awesome-add清单。

5.4、分布式世界中的查询操作

  • 返回和关联大量数据的查询,比如报表

  • 跨多个服务进行分析或者聚合的查询

  • 服务所使用的数据库对某些查询方式支持效果不理想

5.4.1、保存数据副本

开发者可以选择将其他服务通过事件消息发出的数据持久化保存或者缓存起来

  • 可用性优先

5.4.2、读写分离

命令查询职责分离的框架模式(CQRS)

Commanded(Elixir)\CQRS(.NET)\Lagom(Java和Scala)以及Broadway(PHP)

5.4.3、CQRS读写分离的挑战

面临问题:

  • 复制延迟

即时信息流系统Stream-Framework(GitHub)

解决办法:

  • 乐观更新通过版本号的方式

  • 轮询 不断去查询,直到查询最新状态

  • 发布-订阅,通过订阅来获取一手资源

5.4.4、分析和报表

CQRS技术推广到其他使用场景中的,比如数据分析和报表。

将一连串的微服务事件消息转换然后保存到数据仓库中,比如Amazon的Redshift或者Google的BigQuery。