lekaijun / interview

CSDN博客已清空(受不了广告),以后所有的干货都会往这里放。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

和第三方系统交互的一些经验

①->和第三方交互(http)保证两边某笔交易处理信息一致

  • 失败重试
  • 异步回调
  • 主动查询(job)

②<-和第三方交互(http)保证两边某笔交易处理信息一致

  • 请求落表(幂等性)
  • 主动查询(job)

消息中间件(异步、解耦、削峰)

  • 异步工作场景:落库后快速给调用者应答,随后处理业务
  • 解耦工作场景:多个服务都需要用到某个交易,只需订阅即可
  • 削峰工作场景:降低数据库压力(目前没用过)

分布式事务

①分布式事务(同一服务不同的库)

XA协议(2PC),可以用开源框架atomikos

②分布式事务(内部不同服务【都是rpc接口】)-->同步

tcc(熔断->降级),后面再处理,可以用开源框架byteTcc,tcc-transaction

③分布式事务(内部不同服务【中间件关联】)-->异步

方案一:本地消息列表(异步确保)

  • 生产者:参照《100%消息可靠性投递》
  • 消费者:参照《100%消息可靠性投递》,很多人在这里都提到,如果消费失败,就异步通知生产者回滚之前的业务逻辑 但参照了下淘宝沈询的说辞,分布式事务最好不好搞回滚(回滚的代价太大,一个走不通的消费场景,发生的概率太低,完全可以人工介入 努力送达模型才是王道),又会增加复杂度(为解决回滚后产生的bug可能比消费者处理不了发生的次数都还要多)

方案二:RocketMQ(可靠消息服务)

  • 如果上游服务的数据库没操作成功,下游服务是不会收到任何通知【待确认->[已发送-MQ(一个事务)]】
  • 如果下游服务的数据库操作成功了,可靠消息服务死活都会确保投递一个消息给下游服务,而且一定确保下游服务务必成功处理这条消息 【已发送->已完成

确保消息不会在传输中丢失(100%消息可靠性投递)

原则:通过【消息状态确认】和【消息重发】两个功能,可以确保上游应用、可靠消息服务和下游应用数据的最终一致性

  • 生产者(发送方): 发消息(状态“待发送”)和业务操作在同一个本地事务里。发消息的时候消息并不立即发出,在事务提交的时候再异步将消息发出。
  1. 如果遇到MQ异常或网络问题(状态保持不变),会有另外一个服务(job)不断地将这些消息扫出重新发送,需设置retry次数,时间间隔一次比一次大。
  2. 如果发送消息成功则(状态“已发送”)
 ps:①如何判断消息是否发送投递成功?
     答:收到MQ的正确回执后(MQ Broker监听可以做到)
     ②是不是会碰到ack为false,然后消息重试,但是其实网络恢复了,或者MQ正常了,消息重复投递了
     答:会的,所以需要消费者做到幂等性
  • 消费者(接收方): 前提条件:MQ一定要设置成非自动ack(不同的MQ都会有自己的配置,一般默认自动ack) 原因是万一刚接收到消息,已经ack了,准备消费,结果服务down掉了,后面服务恢复了想消费都没消息了 这里面提供两种方案保证消息一定会被消费掉
  1. 使用本地消息列表,接收到消息直接落表,然后ack;随后开始消费,就算消费失败,由于已经有消息落表,还可以继续重试消费。
    这种方案的弊端是又引入了job,好的地方是当然是快速ack,也是一种有效解决消息堆积的办法,尤其是消费时间比较长的消费者
  2. 不使用本地消息列表,等消费成功再ack,如果消费失败呢,也简单,可以通知MQ再发送一次;如果碰到消费者认为此类消息有问题,
    不需要再次处理,可以通知MQ删除(RabbitMQ的话会进入死信队列)
落表前消息去重(幂等性){实现方案:select + insert(并发不高时可用)}

如何解决消息发送的顺序性的

  1. 通过轮询所有队列的方式来确定消息被发送到哪一个队列(负载均衡策略)。订单号相同的消息会被先后发送到同一个队列中,
  2. 在获取到路由信息以后,会根据算法来选择一个队列,同一个 OrderId 获取到的肯定是同一个队列。

实现高并发

  • 服务拆分:将整个项目拆分成多个子项目或者模块,分而治之,将项目进行水平扩展。
  • 服务化:解决服务调用复杂之后的服务的注册发现问题。
  • 消息队列:解耦,异步处理
  • 缓存:各种缓存带来的并发

实现高可用

  • 集群
  • 限流
  • 降级

About

CSDN博客已清空(受不了广告),以后所有的干货都会往这里放。