以前咱们讨论了如何拆分一个订单下单的一个服务(https://www.cnblogs.com/linkstar/p/9610268.html)
从单体到微服务的拆分,当时咱们只是对原来的整个服务作了一个简单的拆分,可是在实际中确定会遇到不少问题,因此咱们这里解决一个最容易也是最有可能在实际中遇到的问题,事务。html
在单体架构中,咱们很容易去维护一个事务,咱们想要对一个事务操做回滚也很容易,而在分离成微服务以后,咱们想要在多个服务上去维护一个事务就比较困难了。这里咱们再也不讨论分步事务的实现,转而讨论一个咱们经常听到的,最终一致性。git
简单的说,不少在实际中的应用多数状况下,想要保证的是只要最后的最结果是对的,中间的过程可能几经周折都没有关系。github
咱们继续拿下单这个例子,想要保证的是,只要最后钱扣了,订单生产了,就对了。假设其中的一个服务挂了,可能通过不断的重试,最终等服务正常以后,结果仍是对了,也就满意。针对这样的状况,咱们称为“最终一致性”。(这里对于它再也不过多解释)segmentfault
那么针对最终一致性为何要使用mq呢?我想不少人也知道网上不少人在说mq实现最终一致性,可是历来没有仔细想一想为何要用mq。我列出这几个缘由来供你参考:
一、mq能够解决http请求出现异常的时候带来的一系列问题
二、mq能够有多个消费者,彻底契合微服务
三、mq本质是队列,在高并发下,能够保证你的数据正常
...架构
并发
生产者的逻辑
一、订单入库
二、消息记录入库
三、发送消息(采用确认模式)
四、mq收到消息以后给生产端一个确认消息
五、生产端监听这个确认消息
六、根据监听结果操做消息表的状态
七、定时任务定时去操做消息状态为1未发送的记录,就是那些没有监听到结果的记录进行从新发送分布式
消费者的逻辑
一、将收到消息的消息入库
二、处理消息失败消息记录的状态就为未处理
三、处理消息成功修改消息记录的状态为处理成功
四、收到相同的消息id的消息直接丢弃
五、定时任务去操做那些未处理,而且已经通过一段时间的消息
六、针对那些一直处理失败的,且很长一段时间都没办法处理成功的消息交由人工或者其余途径处理微服务
一、消息的100%投递
首先咱们须要保证的就是消息必定要投递出去,要是咱们消息都不能保证投递成功,那么后面的逻辑就走不下去了。高并发
二、咱们须要保证幂等性(不管多少次操做,最后形成的结果和只执行一次形成的结果是同样的。)
消息确定会出现重复投递的问题,这里应该由消费端去保证,重复的消息不能进行消费htm
而保证这两个问题的方式就藏在上面的逻辑流程图中,请仔细揣摩其中的用意。
https://github.com/LinkinStars/MicroServiceExample/tree/distributed-transaction
http://www.javashuo.com/article/p-wesansdp-s.html
具体其余细节这里讲的很清楚,这里再也不赘述,针对分布式事务,一直都是一个难题,当前的解决方案有不少,适应不一样的应用场景,因此须要根据实际项目使用场景来选取。