rocketmq学习笔记(自用)

下载rocketmq压缩包,然后解压。
设置环境变量ROCKETMQ_HOME:解压后文件夹地址
设置环境变量NAMESRV_ADDR=localhost:9876
然后就可以测试是否可用。
可以在github上面找rocketmq-externals,打包里面的console项目,
然后运行起来,就可以在网页使用图形界面工具查看rocketmq运行情况(默认使用localhost:9876)

不同topic代表不同的mq通道,代表不同的消息队列
mq会把里面的消息复制多份,分别发送给各个group。也就是每个group都会获得mq的全部消息。(广播)
如果一个group里面有不同的消费者,那么消费者会一起消费该组收到的消息。(group内部负载均衡,不过可以通过设置模式,将负载均衡改成广播模式)
在测试的时候,如果先启动两个消费者,两个消费者同一个组,监听同一个topic,再启动生产者,生产10条消息,消息并不会推送给消费者,不知道为什么。
但是先启动生产者,再启动两个消费者,两个消费者都会收到完整的全部消息,说明广播模式确实生效了。(估计是消费者启动的时候会拉取一次消息)

批量消息注意点:
批量消息应该有相同的topic,相同的waitStoreMsgOK
不能是延时消息
消息内容总长度不超过4M

消费者可以通过tag来过滤消息

sql过滤默认是关闭的,需要在配置文件中添加enablePropertyFilter=true,然后再刷新broker配置。

Springboot整合RocketMQ

初始化一个Springboot项目,然后添加整合依赖。

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

生产者:
在yaml配置文件里面配置name-server地址以及group组
在controller里面自动注入一个RocketMQTemplate变量。
往RocketMQ发消息就用rocketMQTemplate.convertAndSend(“topic10”,user);
消息对应的对象需要实现Serializable接口。
rocketMQTemplate对象有很多方法,分别对应着不同的发送方式,同步异步延时等等。

消费者:
使用service类,实现RocketMQListener<User>接口
onMessage方法就对应着消费者的业务逻辑
消费者就用注解@RocketMQMessageListener(topic = “topic10”,consumerGroup = “group1”)
在注解里面可以设置topic,group,过滤方式,传播方式

消息顺序存取

生产者生产消息的时候通过消息队列选择器,通过实现MessageQueueSelector接口,实现select方法,内部根据消息订单id取模来选择放到不同的消息队列,以确保订单步骤会按照正确顺序执行。

public class Producer {
    public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException {

//         1.谁来发?
        DefaultMQProducer producer = new DefaultMQProducer("group1");
//         2.发给谁?
        producer.setNamesrvAddr("localhost:9876");
        producer.start();
        List<OrderStep> list=new ArrayList<>();
        OrderStep orderStep=null;
        orderStep=new OrderStep(1,"创建");
        list.add(orderStep);
        orderStep=new OrderStep(2,"创建");
        list.add(orderStep);
        orderStep=new OrderStep(1,"推送");
        list.add(orderStep);
        orderStep=new OrderStep(1,"完成");
        list.add(orderStep);
        orderStep=new OrderStep(2,"推送");
        list.add(orderStep);
        orderStep=new OrderStep(2,"完成");
        list.add(orderStep);
        for (final OrderStep step : list) {
            Message message=new Message("topic12","tag1",orderStep.toString().getBytes());
            producer.send(message, new MessageQueueSelector() {
                @Override
                public MessageQueue select(List<MessageQueue> list, Message message, Object o) {
                    int size=list.size();
                    int orderId=(int) (step.getOrderId());
                    int i=orderId%size;
                    return list.get(i);
                }
            },null);
        }

    }
}

消费者通过consumer.registerMessageListener,里面的参数实现MessageListenerOrderly接口,实现顺序监听。

public class Consumer {
    public static void main(String[] args) throws MQClientException {
        //谁来收?
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("group1");
        //从哪里收?
        consumer.setNamesrvAddr("localhost:9876");
        //设置消息模式(指同一个group内部的模式),默认是负载均衡MessageModel。CLUSTERING
        //可以设置成广播模式MessageModel.BROADCASTING
        consumer.setMessageModel(MessageModel.BROADCASTING);
        //监听哪个消息队列?
        consumer.subscribe("topic12","*");
        //消费者顺序监听,一个线程只监听一个队列
        consumer.registerMessageListener(new MessageListenerOrderly() {
            public ConsumeOrderlyStatus consumeMessage(List<MessageExt> list, ConsumeOrderlyContext consumeOrderlyContext) {
                for (MessageExt messageExt : list) {
                    System.out.println(messageExt);
                    byte[] body= messageExt.getBody();
                    System.out.println(new String(body));
                }
                return ConsumeOrderlyStatus.SUCCESS;
            }
        });
        consumer.start();
        System.out.println("消费者起来了");
    }
}

事务(事务消息只与生产者有关):
在这里插入图片描述
生产者使用TransactionMQProducer,然后设置事务监听,最后发送消息

public class Producer {
    public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException {

//         1.谁来发?
        TransactionMQProducer producer = new TransactionMQProducer("group1");
//         2.发给谁?
        producer.setNamesrvAddr("localhost:9876");
        //设置事务监听
    producer.setTransactionListener(new TransactionListener() {
            //正常事务过程
            public LocalTransactionState executeLocalTransaction(Message message, Object o) {
                //把消息保存到数据库
                //用if else来判断是否存入数据库
                return null;
            }
            //事务补偿过程,主动去问事务完成了没有
            public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
                //
                return null;
            }
        });
        producer.start();
//         3.怎么发?
//           4.发什么?
        String msg="hello world";
        Message message = new Message("topic1", "tag1", msg.getBytes());
//         5.发的结果是什么?
        TransactionSendResult transactionSendResult = producer.sendMessageInTransaction(message, null);
        System.out.println(transactionSendResult);
        //别关生产者
    }
}

预选申请空间,然后进行顺序读写,效率高
零拷贝,不分用户态,这样少一次拷贝,效率更高(要求预留空间)
MQ数据存储区域:消费逻辑队列,索引,commitlog(内部有message queue)

异步刷盘:broker收到消息之后写入内容,然后直接返回ACK给生产者。
同步刷盘:生产者发送消息到MQ,MQ挂起生产者发消息的线程,MQ将消息写入内存,
内存数据写入硬盘,硬盘存储后返回success,MQ恢复挂起的生产者线程,再发送ACK给生产者。

高可用:
name-server无状态+全服务器注册
消息服务器主从架构
生产者将相同的topic绑定到多个group组,保证master挂了之后,其他master仍可用
消息消费,RocketMQ自身会根据master压力确认是否由master承担消息读取功能。繁忙的时候自动切换到slave程度读取工作。

负载均衡:
生产者用轮询机制去发送消息,发送给broker里面的message queue
同一个broker内轮询message queue,让每一个message queue只发给一个消费者进行消费,

顺序消息重试,每隔一分钟就会重试
无序消息重试只适合负载均衡模式,可以设置,重试的次数越多,时间间隔就越长。
等到次数达到16次之后就放弃,放弃的消息会放到死信队列中,然后让运维介入

消息幂等性,同一个订单,无论请求多少次,结果都是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值