一、业务场景

关于分布式项目的补偿机制(案例总结)-LMLPHP

给大家整理一下最近遇到的项目问题: A服务生成数据后推送给B服务,此时B服务挂掉,后续如何解决

先说一下我的解决思路,因为我们项目没有用到分布式事务,所以就用补偿机制和手动回滚数据来解决分享思路交流经验


二、补偿解决

1.创建一个数据表记录推送失败的数据
2.创建一个定时任务隔一段时间后重推数据到B系统

记录表里对应的数据会有一个标识号,如果数据成功推送或者补偿成功,修改此标识符合,数据不会重复推送

我这里说的是创建MySQL表来实现对应的补偿。同时还有很多其余的补偿方法

例如

重试机制:A服务可以设计一个重试机制,在B服务挂掉后,定期尝试重新推送数据。如果在一定时间内B服务重启,并能够恢复接收数据,A服务就可以将数据成功推送给B服务。

存储数据:A服务可以将生成的数据暂时存储在一个数据存储系统中(如Redis、Kafka),等待B服务重新恢复后,再从存储系统中读取数据并推送给B服务。

下面是一个简单的定时任务推送案例的Java代码:

import java.util.*;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class OrderTask {
    
    @Autowired
    private RestTemplate restTemplate;
    
    // 定义推送订单信息的方法
    private void pushOrderInfo(OrderInfo orderInfo) {
        String url = "http://logistics-service/push_order_info";
        try {
            String response = restTemplate.postForObject(url, orderInfo, String.class);
            System.out.println("订单信息已成功推送!响应内容为:" + response);
        } catch (Exception e) {
            System.out.println("订单信息推送失败,错误信息为:" + e.getMessage());
        }
    }
    
    // 定时任务:检查未处理的订单信息并重新推送给物流服务
    @Scheduled(fixedRate = 10000) // 每10秒钟执行一次
    private void checkUnprocessedOrders() {
        // 查询未处理的订单信息
        List<OrderInfo> unprocessedOrders = getUnprocessedOrders();
        // 遍历未处理的订单信息,并重新推送给物流服务
        for (OrderInfo order : unprocessedOrders) {
            pushOrderInfo(order);
        }
    }
    
    // 查询未处理的订单信息(这个方法的具体实现可以根据实际情况而定)
    private List<OrderInfo> getUnprocessedOrders() {
        // TODO: 查询未处理的订单信息
        return new ArrayList<>();
    }

}

其中,pushOrderInfo()方法用于将订单信息推送给物流服务,checkUnprocessedOrders()方法则用于定时查询未被处理的订单信息,并重新推送给物流服务。在OrderTask类上,使用了Spring的@Component注解,表示这是一个组件类,可以被Spring容器扫描到并实例化。使用了Spring的@Autowired注解,表示需要注入RestTemplate对象,用于发送HTTP请求。在checkUnprocessedOrders()方法上,使用了Spring的@Scheduled注解,表示这是一个定时任务,可以定期执行指定的方法。这里设置了fixedRate属性为10000,表示每隔10秒钟执行一次。在实际使用中,可以根据具体需求来设置定时任务的执行频率。


三、数据一致性保障

我们再回到最初的业务问题,如果A生成100个单据,推送给B,此时B服务挂掉,此时A系统上已经有对应的100个单据数据了,此时两个系统数据不同步,如果对A系统单据提交或者取消操作会出现系统异常等错误。

关于分布式项目的补偿机制(案例总结)-LMLPHP

解决办法:A系统生成100个单据,A推送B失败,检查代码里面是否做了事务回滚,如果不能回滚,手动方法补偿删除A生成的100个单据。如上方法在异常里面执行即可。执行结束后我们可以发邮件或者钉钉通知的方法告诉 系统开发人员此处 推送数据失败等。开发或者运营 再进行人为的检查排查问题。

说明:这样的好处就是不会让错误的数据出现在系统中。保障了数据的一次性。

弊端:不同于如上的定时任务补偿,没有做到很智能化,要新增人力来排查问题。如服务挂掉后,此方案还要人力重新推送。定时任务则实现了直接推送数据。

对比定时任务:如果是因为服务挂掉。定时任务的弊端在于可能在短暂的时间内会造成两个系统数据不一致的问题。


四、总结学习

分布式项目的补偿机制是指在分布式系统中,当出现数据传输错误、节点宕机等意外情况时,通过一定的方法修复或补偿数据损失,保证系统的稳定性和可靠性。

一般来说,分布式项目的补偿机制主要分为以下几个方面:

  1. 重试机制:当某个节点出现错误时,可以通过多次重试来尝试重新发送数据,直到成功为止。

  2. 异常捕获机制:通过捕获异常信息,及时发现和处理错误,避免错误的传播和扩大化。

  3. 数据备份机制:在分布式系统中,进行数据备份是非常重要的,可以通过多个节点进行数据备份,保证在某个节点出现故障时,数据可以从备份节点中恢复。

  4. 数据一致性机制:在分布式系统中,保证数据一致性是非常关键的,可以通过分布式一致性算法(如Paxos、Raft)来保证数据的一致性和可靠性。

  5. 事务回滚机制:当某些操作出现错误时,可以通过事务回滚机制将数据恢复到操作前的状态,保证数据的准确性和完整性。

总之,分布式项目的补偿机制需要结合具体的情况和业务需求进行选择和设计,才能真正保证系统的可靠性和稳定性。


📖☕️🌊📝📚🎩🚀
📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤️ 分享👥 留言💬thanks!!!

📚愿我们奔赴在各自的热爱里!

06-07 10:13