• 微服务框架下的数据一致性第一篇


      微服务作为当下最火热的服务框架,其给我们开发带来了很多的好处,例如功能复用,独立部署,系统容错等,但是同时也有一些不方便的地方,其中最突出的就是数据一致性的问题,今天我们开始讨论一下这个数据一致性的解决方案:

       在没有使用微服务的时候我们一般都是使用同一个数据库,只要我们使用ACID的数据强一致性就可以解决问题,但是微服务下不同的模块使用不同的数据库,这样就无法保证数据的一致性,我们就需要讨论新的方案----分布式下的数据一致性问题。首先我们需要了解的是两个理论:CAP理论和BASE理论

      CAP理论
        CAP 是指在一个分布式系统下, 包含三个要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),并且三者不可得兼。

        C:Consistency,一致性,所有数据变动都是同步的。

        A:Availability,可用性,即在可以接受的时间范围内正确地响应用户请求。

        P:Partition tolerance,分区容错性,即某节点或网络分区故障时,系统仍能够提供满足一致性和可用性的服务。

      在分布式系统下,我们保证了分区容错性,所以只能在可用性和数据一致性上面做取舍,现实决定了我们只能选择可用性,所以数据的一致性我们只能通过后期的补偿机制来达到了。

      BASE理论:
        BASE 理论主要是解决 CAP 理论中分布式系统的可用性和一致性不可兼得的问题。BASE 理论包含以下三个要素:

        BA:Basically Available,基本可用。

        S:Soft State,软状态,状态可以有一段时间不同步。

        E:Eventually Consistent,最终一致,最终数据是一致的就可以了,而不是时时保持强一致。

      BASE理论与ACID的数据库强一致性不同,是对CAP理论的支持,通过牺牲强一致性来保证系统的可用性,这样会导致数据在一段时间内可能出现不同步的情况,一旦出现异常,需要进行回滚等操作。但是这样的操作也是可以达到最终的数据一致性的。

      介绍完上面的理论,下面的我们看一下我们正在使用的分布式解决方案吧!

      方案主要是分为三个模块,上游应用主要是处理业务并发送MQ消息,可靠消息服务和MQ消息组件负责协调上下游消息的传递并保证数据的一致性,下游应用负责监听MQ消息并执行自身的业务。如图所示:

      

      第一阶段:

      注意点:上游应用将本地执行和消息发送绑定在同一事务中,要么同时成功,要么同时回滚

      步骤:
        上游应用发送待确认消息到可靠消息系统----不会导致出现一致性问题

        可靠消息系统保存待确认消息并返回----不会导致出现一致性问题

        上游应用执行本地业务----不会导致出现一致性问题

        上游应用通知可靠消息系统确认业务已执行并发送消息----会导致出现一致性问题

        可靠消息系统修改消息状态为发送状态并将消息投递到 MQ 中间件----会导致出现一致性问题

      上游应用执行完成,下游应用尚未执行或执行失败时,此事务即处于 BASE 理论的 Soft State 状态

       第二阶段:

      

      注意点:
        下游应用监听 MQ 消息并执行业务,并且将消息的消费结果通知可靠消息服务。

        可靠消息的状态需要和下游应用的业务执行保持一致,可靠消息状态不是已完成时,确保下游应用未执行,可靠消息状态是已完成时,确保下游应用已执行。

      步骤:
        下游应用监听 MQ 消息组件并获取消息----会导致出现一致性问题

        下游应用根据 MQ 消息体信息处理本地业务----会导致出现一致性问题

        下游应用向 MQ 组件自动发送 ACK 确认消息被消费----会导致出现一致性问题

        下游应用通知可靠消息系统消息被成功消费,可靠消息将该消息状态更改为已完成----会导致出现一致性问题

       为了确保上下游数据的最终一致性,在可靠消息系统中,需要开发消息状态确认和消息重发两个功能以实现 BASE 理论的 Eventually Consistent 特性。

    分析:

       在上游应用与消息中间件交互的时候,如果消息中间件或者上游应用发生宕机,就有可能没有将MQ消息发送出去,一旦发生这种情况,就会导致上游应用已经执行业务操作完毕,但是MQ消息并没有收到,上游应用也无法确认追踪到这一情况,最终导致无法给下游应用正确的反馈,数据最终一致。面对这种情况,我们通常会使用confirm机制和returnMessage机制来确认上游应用已经发送消息成功。总结下就是:

      如果消息没有到exchange,则confirm回调,ack=false

      如果消息到达exchange,则confirm回调,ack=true

      exchange到queue成功,则不回调return

      exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)

      在下游应用与消息中间件交互的时候,如果发生宕机的情况,就会发生下游业务执行完成,但是MQ并未接收到反馈消息,这个时候MQ还是一直会向其发送消息,这个时候就需要保证接口的幂等性了。

      上游应用对应的是消息状态确认,下游应用对应的是消息重发。以上就是我们系统解决分布式系统下数据一致性的方案的思路。

      Confirm机制的最大优点在于异步,生产者在发送消息以后,即可继续执行其他任务。而服务器返回Confirm后,会触发生产者的回调函数,
    生产者在回调函数中处理Confirm信息。如果消息服务器发生异常,导致该消息丢失,会返回给生产者一个nack,表示消息已经丢失,这样生产者就可以通过重发消息,
    保证消息不丢失。Confirm机制在性能上要比事务优越很多。但是Confirm机制,无法进行回滚,就是一旦服务器崩溃,生产者无法得到Confirm信息,
    生产者其实本身也不知道该消息是否已经被持久化,只有继续重发来保证消息不丢失,但是如果原先已经持久化的消息,并不会被回滚,这样队列中就会存在两条相同的消息,系统需要支持去重。

    代码地址:https://github.com/shouchengdai/rabbitmq_test

    参考博客:

      http://www.cnblogs.com/study-everyday/p/7605619.html?tdsourcetag=s_pctim_aiomsg

        https://www.jishux.com/p/9faed5edeec96a46?tdsourcetag=s_pctim_aiomsg

     

  • 相关阅读:
    如何在Ubuntu Server 18.04上安装Microsoft的Procmon
    如何在Ubuntu 20.04上安装Wine 5.0
    如何在Kali Linux 2020中启用SSH服务
    如何在Ubuntu 20.04 LTS Focal Fossa上安装Apache Groovy
    如何使用命令在Ubuntu 20.04 Linux上安装Vmware Tools
    在Ubuntu 20.04 LTS Focal Fossa上安装Zabbix Agent
    hdu 2089 不要62
    hdu 2093 成绩排名
    hdu 2104 hide handkerchief
    leetcode147对链表进行插入排序
  • 原文地址:https://www.cnblogs.com/daishoucheng/p/9838773.html
Copyright © 2020-2023  润新知