zoukankan      html  css  js  c++  java
  • 支付宝往余额宝转钱怎么保证一致性

    先给大家套一个业务场景,也是很常见的一个异步调用场景:

    • 支付宝往余额宝转钱

    即将服务A假设为支付宝,服务B假设为余额宝。
    于是呢,我们的支付宝往余额宝转100块钱是怎么做的呢?
    特别容易,借助消息队列即可,如下图所示

    一致性解决

    OK,上面这一版有一个致命的问题!如下所示
    事务开始
    (1)给支付宝账户zhangsan,扣100元
    (2)将(给余额宝账户zhangsan,加100元)封装为消息,发送给消息队列
    事务结束

    敢问你,如何保证第一步和第二步是在同一个事务里完成的。换句话说,第一步操作的是数据库,第二步操作的是一个消息队列,你如何保证这两步之间的一致性?
    记住了,任何涉及到数据库和中间件之间的业务逻辑操作,都需要考虑二者之间的一致性。比如,你先操作了数据库,再操作缓存,数据库和缓存之间一致性如何解决?好吧,如果是博主的铁粉,应该知道怎么解决了,回到我们的场景。
    改变思路,加一张事务表,如下图所示

    注意了,此时事务的内容为
    事务开始
    (1)给支付宝账户zhangsan,扣100元
    (2)给事件表插入一条记录
    事务结束

    此时是对同一数据库的两张表操作,因此可以用数据库的事务进行保证。
    另外,起一个定时程序,定时扫描事务表,发现一个状态为'UNFINISHED'的事件,就进行封装为消息,发送到消息中间件,然后将状态改为'FINISHED'.

    幂等性解决

    注意了,这一版还存在一个幂等性问题!
    仔细看,定时程序做了如下三个操作
    (1)定时扫描事务表,发现一个状态为'UNFINISHED'的事件
    (2)将事件信息,封装为消息,发送到消息中间件
    (3)将事件状态改为'FINISHED'

    OK,假设在步骤(2)的时候,发送完消息体,还未执行步骤(3),定时程序阵亡了!然后重启定时程序,发现刚那个事务的状态依然为'UNFINISHED',因此重新发送。这样,就会出现重复消费问题。因此,幂等性也是需要保证的!

    如果是博主的忠实读者,应该知道,博主曾经写过一篇《分布式之消息队列复习精讲》,里头就提到了如何解决幂等性问题。什么?你没看过这篇?拉出去枪毙!
    借用这篇文章里的方案。在消费者端,也维护一个带主键的表,可以选txid为主键,如下图所示

    如果一旦出现重复消费,则在事务里直接报出主键冲突错误,从而保证了幂等性!

  • 相关阅读:
    考试心得 模拟18
    模拟17 题解
    模拟16 题解
    考试心得 模拟17
    模拟15 题解(waiting)
    BZOJ2653 middle 【主席树】【二分】*
    BZOJ3932 CQOI2015 任务查询系统 【主席树】
    与或 【线段树】 *
    BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*
    网络流--最大权闭合子图 *
  • 原文地址:https://www.cnblogs.com/yizhou35/p/13366313.html
Copyright © 2011-2022 走看看