幂等性 本地事务 分布式事务 MQ延时队列-最终一致性

事务的坑:

在同一个类里面,编写两个方法,内部调用的时候,会导致事务设置失效。原因是没有用到代理对象的缘故。

解决:

0)、导入 spring-boot-starter-aop 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1)、启动类加注解:

​ @EnableTransactionManagement(proxyTargetClass = true)

​ @EnableAspectJAutoProxy(exposeProxy=true)

3)、使用 AopContext.currentProxy() 生成当前类的代理对象,再调用本类方法

ProductServiceIml o = (ProductServiceIml)AopContext.currentProxy ();
o.getFirPageProductVo (1,pageSize);

本地事务

@Transactional(timeout 30)//a事务的所有设置就传播到了和他公用一个事务的方法
public void a(){
    b();//和a用一个事务,回滚
    c();//新事务(不回滚)
    int i=10/0;
}


@Transactional(propagation Propagation.REQUIRED,timeout 2)// 和a共用一个事务,相当于没设置超时时间
public void b(){
}


@Transactional(propagation Propagation.REQUIRES_NEW)
public void c(){
}

使用seata做分布式事务

https://seata.io/zh-cn/docs/overview/what-is-seata.html

TC是事务协调器,记录事务的状态

TM是全局事务,记录事务的范围

RM是资源管理,算是分支事务,需要和TC维持连接,实时告诉TC事务成功还是失败

使用:

https://seata.io/zh-cn/docs/user/quickstart.html

高并发场景不考虑这里面的2PC和TCC方式,着重在 最大努力通知 和 可靠消息【看后面的延时队列】

分布式事务

[file:///E:/中%20Chromedown/java~spring/10.尚硅谷——谷粒商城/谷粒商城课件/高级篇/03、本地事务%26分布式事务.pdf](file:///E:/中 Chromedown/java~spring/10.尚硅谷——谷粒商城/谷粒商城课件/高级篇/03、本地事务%26分布式事务.pdf)

使用AT模式,详情看链接【高并发场景一般不考虑,因为里面加了很多的锁,效率比较低】

  • 建表
  • 导入依赖【导入依赖之后,在idea的左侧栏外部库,搜一下seata-all,看看是什么版本,然后再下载对应版本服务器
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
  • 下载服务器压缩包

​ 解压之后,里面的config文件夹,有这两个文件

​ registry.conf: 可以设置注册中心 和 配置中心,默认使用文件

​ file.conf: 如上面设置配置中心为file,生效。可以设置把 **事务日志文件(用来自动回滚的文件)**设置在文件或者db里面

  • 每个微服务的resoures 都要把 registry.conf 和 file.conf 复制进去

    • 要修改file.conf 的配置 或者 改微服务配置
service{
    vgroup_mapping.my_test_tx_group = "default"  
    改成下面,用微服务名取代{}
    vgroup_mapping.{spring.application.name}--fescar-service-group = "default"
}
微服务配置注册到nacos的名字
spring.cloud.alibaba.seata.tx-service-group = {spring.application.name}.servic

​ 配置seata代理数据源【每个要使用分布式事务的微服务都需要配置】

import com.zaxxer.hikari.HikariDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;

@Configuration
public class MySeataConfig {

    @Autowired
    DataSourceProperties dataSourceProperties;

    @Bean
    public DataSource dataSource(DataSourceProperties dataSourceProperties) {
        HikariDataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
        if (StringUtils.hasText(dataSourceProperties.getName())) {
            dataSource.setPoolName(dataSourceProperties.getName());
        }
        return new DataSourceProxy(dataSource);
    }
}
  • 在开启事务大入口的方法上,配上 @GlobalTransactional

​ 在被远程调用的微服务上,配上 @Transactional

使用延时队列实现 柔性事务,达到最终一致性!

【当程序延时收到消息后,程序进行各种判断,判断是否执行成功,若执行失败,回复数据】

常用下面第一种方式实现延时队列,设置队列的过期时间,然后没有消费者监听,队列里的消息只能等到过期,消息过期后,设置把消息转到死信路由

然后死信路由再把消息转到队列里,消费者就可以延时获取到消息

【不使用第二种是因为,队列里的消息,是按顺序出来,而不是按过期时间长短出来,前面的会把后面的塞住(要是有一个没设过期时间,gg)】

导入依赖还有弄好其他的rabbitMq配置之后,创建配置类,添加队列,交换机,绑定关系到容器。

spring boot会自动将这些东西弄给mq!!!

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;

@Configuration
public class MyRabbitMQConfig {


    /* 容器中的Queue、Exchange、Binding 会自动创建(在RabbitMQ)不存在的情况下 */

    /**
     * 死信队列
     *
     * @return
     */@Bean
    public Queue orderDelayQueue() {
        /*
            Queue(String name,  队列名字
            boolean durable,  是否持久化
            boolean exclusive,  是否排他
            boolean autoDelete, 是否自动删除
            Map<String, Object> arguments) 属性
         */
        HashMap<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", "order-event-exchange");
        arguments.put("x-dead-letter-routing-key", "order.release.order");
        arguments.put("x-message-ttl", 60000); // 消息过期时间 1分钟
        Queue queue = new Queue("order.delay.queue", true, false, false, arguments);

        return queue;
    }

    /**
     * 普通队列
     *
     * @return
     */
    @Bean
    public Queue orderReleaseQueue() {

        Queue queue = new Queue("order.release.order.queue", true, false, false);
        return queue;
    }

    /**
     * TopicExchange
     *
     * @return
     */
    @Bean
    public Exchange orderEventExchange() {
        /*
         *   String name,
         *   boolean durable,
         *   boolean autoDelete,
         *   Map<String, Object> arguments
         * */
        return new TopicExchange("order-event-exchange", true, false);


    }

    @Bean
    public Binding orderCreateBinding() {
        /*
         * String destination, 目的地(队列名或者交换机名字)
         * DestinationType destinationType, 目的地类型(Queue、Exhcange)
         * String exchange,
         * String routingKey,
         * Map<String, Object> arguments
         * */
        return new Binding("order.delay.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.create.order",
                null);
    }

    @Bean
    public Binding orderReleaseBinding() {

        return new Binding("order.release.order.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.release.order",
                null);
    }
}

延时队列实现最终一致性的重点是:可靠消息!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沛权

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值