RocketMQ

1.安装部署

        windows环境演示:

        官方地址:  https://rocketmq.apache.org/release_notes/release-notes-4.3.2/

        配置rocketMq环境变量

        启动nameserver命令: start mqnamesrv.cmd

        启动broker: start mqbroker.cmd -n localhost:9876

验证是否启动成功: jsp -l

以上来看,我们nameserver以及broker都启动完成了 

2.结构介绍

        nameserver:  一个无状态节点,用于部署集群,每个集群没有任何信息同步

        broker: broker分为master和slaver节点,每个broker与nameserver集群中的所有节点建立长连接,定时(30s)注册Topic信息到NameServer; NameServer定时(10s)扫描所有存活的Broker的连接,如果2分钟没有心跳,自动断开

        Producer:  Producer与NameServer中任意一个节点建立长连接,定期从NameServer中拉取Topic路由的信息,并且提供Topic服务的Master(Broker)建立长连接,定时向Master发送心跳

        Producer定时(30s)从NameServer中获取所有的Topic队列

        Produce每隔30s,向所有关联的broker发送心跳        

        broker每隔10s扫描存活的连接,如果2分钟没有收到心跳数据,自动与producer断开连接

        Consumer:  Producer与NameServer中任意一个节点建立长连接,定期从NameServer中拉取Topic路由的信息,并且提供Topic服务的Master丶slaver(Broker)建立长连接,定时向Master丶slaver发送心跳

        Consumer既可以从master订阅消息,也可以从slaver订阅消息,取决于broker的配置

        Consumer定时(30s)从NameServer中获取所有的Topic队列

        Consumer每隔30s,向所有关联的broker发送心跳   

代码实现:

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.4.3</version>
    </dependency>

    <dependency>
        <groupId>org.apache.rocketmq</groupId>
        <artifactId>rocketmq-spring-boot-starter</artifactId>
        <version>2.1.1</version>
    </dependency>
</dependencies>

配置文件:

rocketmq:
  name-server: 127.0.0.1:9876
  producer:
    group: topic-default-group

Producer:

@Controller
public class DemoController {

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @RequestMapping("/consumer")
    @ResponseBody
    private String consumer(){
        Map map = new HashMap();
        map.put("id",2);
        map.put("name","ff0");
        rocketMQTemplate.convertAndSend("topicA",map);
        return "OK";
    }
}

发送成功

Consumer:

@Component
@RocketMQMessageListener(consumerGroup = "topic-default-group", topic = "topicA")
public class DemoConsumer implements RocketMQListener<String> {


    @Override
    public void onMessage(String s) {
        System.out.println(s);
    }
}

成功消费

3.特性/优势

        

   
        

        3.1顺序消费

        例如:我们需要保证  订单创建 --> 订单支付  --> 订单完成  --> 订单推送,整个流程的局部一致性

        消息发送Producer:

@RequestMapping("/consumerOrder")
    @ResponseBody
    private String consumerOrder() throws InterruptedException {
        rocketMQTemplate.syncSendOrderly("topicA","订单创建","order = 1");
        rocketMQTemplate.syncSendOrderly("topicA","订单支付","order = 1");
        rocketMQTemplate.syncSendOrderly("topicA","订单完成","order = 1");
        rocketMQTemplate.syncSendOrderly("topicA","订单推送","order = 1");
        return "OK";
    }

 主要是通过第三个参数 order = 1,会根据它的hash值计算,放到对应的哪个队列,从而保证局部的消息都在一个队列

        Consumer:

     3.2事务型消息

  1.producer发送事务消息(prepared消息)

@RequestMapping("/transaction")
    @ResponseBody
    private String transaction() {
        Message<String> message = MessageBuilder.withPayload("锁定库存").build();
        TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction("topicStock", message, null);
        System.out.println("发送状态:" + result.getLocalTransactionState());
        return "success";
    }

2.执行本地事务

@Component
@RocketMQTransactionListener
@Slf4j
public class TransactionStockListener implements RocketMQLocalTransactionListener {


    private ConcurrentHashMap<String, Object> localTrans = new ConcurrentHashMap<>();

    /**
     * 发送prepare消息成功,用于执行本地事务
     * @param message 消息
     * @param o
     * @return 返回事务状态
     */
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {

        try {


            log.info("【本地业务执行完毕】 msg:{}, Object:{}", message, o);

            // 用于记录消息事务,一般创建日志表来记录
            localTrans.put(message.getHeaders().getId()+"", message.getPayload());

            // 执行本地事务,创建订单
            System.out.println("订单创建完毕");

            // 提交事务
            return RocketMQLocalTransactionState.COMMIT;

        } catch (Exception e) {

            e.printStackTrace();

            log.error("【执行本地业务异常】 exception message:{}", e.getMessage());

            // 回滚事务
            return RocketMQLocalTransactionState.ROLLBACK;

        }
    }

    /**
     *
     * @param message  通过transactionId判断该消息的事务状态
     * @return
     */
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        log.info("【执行检查任务】");

        return RocketMQLocalTransactionState.UNKNOWN;
    }
}

主要是为了保证消息事务与本地事务一致性

localTrans为了记录本地事务日志,一般用于日志表记录做补偿操作

补偿机制: 定时任务扫描发送待发送的消息,重新发送消息

3.消费消息

这一步主要是为了关注Commit状态的消息,被消费端成功消费,Rollback状态的消息,无法消费

@Component
@RocketMQMessageListener(consumerGroup = "topic-default-group", topic = "topicStock")
public class StockConsumer implements RocketMQListener<String> {


    @Override
    public void onMessage(String s) {
        // 库存扣减消息
        System.out.println(s);
    }
}

 4.消息存储

        

RocketMQ消息主要是通过 CommitLog和ConsumerQueue来完成

CommitLog: 用于存储消息的物理文件

ConsumerQueue: 用户记录msg在Commit Log的offset以及消息的大小和tag

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值