RocketMq入门学习-生产者原理

生产者概述

rocketMq中生产消息的一方称为生产者
在这里插入图片描述
生产者组:一个逻辑概念,在创建生产者实例的时候,需要指定一个生产者组名

//1. 创建消息生产者,并指定生产者组名
DefaultMQProducer producer = new DefaultMQProducer("async-producer");

RocketMQ客户端中的生产者有两个独立实现类:

 org.apache.rocketmq.client.producer.DefaultMQProducer
 org.apache.rocketmq.client.producer.TransactionMQProducer

前者用于生产普通消息、顺序消息、单向消息、批量消息、延迟消息,后者主要用于生产事务消息。

一个生产者组可以生产多个topic的消息。

生产者实例:一个生产者组中可以部署多个进程,每个进程都可以称为一个生产者实例。
Topic:主题名字,一个Topic由若干Queue组成。

消息类型和消息结构

rocketMq中message类

package org.apache.rocketmq.common.message;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class Message implements Serializable {
    private static final long serialVersionUID = 8445773977080406428L;

    //主题名字(必填):表示消息要到的发送主题 ,可以通过RocketMQ Console创建
    private String topic;
    //选填,消息的标记,完全由应用设置,RocketMQ不做任何处理,类似于memcached中flag的作用。
    private int flag;
    //消息属性,主要存储一些消息的元数据信息,消息扩展信息,Tag、keys、延迟级别都保存在这里
    private Map<String, String> properties;
    //消息体,字节数组。需要注意生产者使用什么编码,消费者也必须使用相同的编码解码,否则会产生乱码。
    private byte[] body;
    //事务id,仅在事务消息中使用到
    private String transactionId;

    public Message() {
    }

    public Message(String topic, byte[] body) {
        this(topic, "", "", 0, body, true);
    }

    public Message(String topic, String tags, String keys, int flag, byte[] body, boolean waitStoreMsgOK) {
        this.topic = topic;
        this.flag = flag;
        this.body = body;

        if (tags != null && tags.length() > 0) {
            this.setTags(tags);
        }

        if (keys != null && keys.length() > 0) {
            this.setKeys(keys);
        }

        this.setWaitStoreMsgOK(waitStoreMsgOK);
    }

    public Message(String topic, String tags, byte[] body) {
        this(topic, tags, "", 0, body, true);
    }

    public Message(String topic, String tags, String keys, byte[] body) {
        this(topic, tags, keys, 0, body, true);
    }

    //setKeys():设置消息的key,多个key可以用MessageConst.KEY_SEPARATOR分隔或者直接用另一个重载方法。如果Broker中messageIndexEnable=true 则会根据key创建消息的hash索引,帮助用户进行快速查询。
    public void setKeys(String keys) {
        this.putProperty(MessageConst.PROPERTY_KEYS, keys);
    }

    void putProperty(final String name, final String value) {
        if (null == this.properties) {
            this.properties = new HashMap<String, String>();
        }

        this.properties.put(name, value);
    }

    void clearProperty(final String name) {
        if (null != this.properties) {
            this.properties.remove(name);
        }
    }

    //putUserProperty():如果还有其他扩展信息,可以存放在这里,内部是一个Map,重复调用会覆盖旧值。
    public void putUserProperty(final String name, final String value) {
        if (MessageConst.STRING_HASH_SET.contains(name)) {
            throw new RuntimeException(String.format(
                "The Property<%s> is used by system, input another please", name));
        }

        if (value == null || value.trim().isEmpty()
            || name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException(
                "The name or value of property can not be null or blank string!"
            );
        }

        this.putProperty(name, value);
    }

    public String getUserProperty(final String name) {
        return this.getProperty(name);
    }

    public String getProperty(final String name) {
        if (null == this.properties) {
            this.properties = new HashMap<String, String>();
        }

        return this.properties.get(name);
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    public String getTags() {
        return this.getProperty(MessageConst.PROPERTY_TAGS);
    }

    //setTags():消息过滤的标记,用户可以订阅某个Topic的某些Tag,这样Broker只会吧订阅了topic-tag的消息发送个消费者。
    public void setTags(String tags) {
        this.putProperty(MessageConst.PROPERTY_TAGS, tags);
    }

    public String getKeys() {
        return this.getProperty(MessageConst.PROPERTY_KEYS);
    }

    public void setKeys(Collection<String> keyCollection) {
        String keys = String.join(MessageConst.KEY_SEPARATOR, keyCollection);

        this.setKeys(keys);
    }

    public int getDelayTimeLevel() {
        String t = this.getProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL);
        if (t != null) {
            return Integer.parseInt(t);
        }

        return 0;
    }

    //setDelayTimeLevel():设置延迟级别,延迟多久消费者可以消费。
    public void setDelayTimeLevel(int level) {
        this.putProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(level));
    }

    public boolean isWaitStoreMsgOK() {
        String result = this.getProperty(MessageConst.PROPERTY_WAIT_STORE_MSG_OK);
        if (null == result) {
            return true;
        }

        return Boolean.parseBoolean(result);
    }

    public void setWaitStoreMsgOK(boolean waitStoreMsgOK) {
        this.putProperty(MessageConst.PROPERTY_WAIT_STORE_MSG_OK, Boolean.toString(waitStoreMsgOK));
    }

    public void setInstanceId(String instanceId) {
        this.putProperty(MessageConst.PROPERTY_INSTANCE_ID, instanceId);
    }

    public int getFlag() {
        return flag;
    }

    public void setFlag(int flag) {
        this.flag = flag;
    }

    public byte[] getBody() {
        return body;
    }

    public void setBody(byte[] body) {
        this.body = body;
    }

    public Map<String, String> getProperties() {
        return properties;
    }

    void setProperties(Map<String, String> properties) {
        this.properties = properties;
    }

    public String getBuyerId() {
        return getProperty(MessageConst.PROPERTY_BUYER_ID);
    }

    public void setBuyerId(String buyerId) {
        putProperty(MessageConst.PROPERTY_BUYER_ID, buyerId);
    }

    public String getTransactionId() {
        return transactionId;
    }

    public void setTransactionId(String transactionId) {
        this.transactionId = transactionId;
    }

    @Override
    public String toString() {
        return "Message{" +
            "topic='" + topic + '\'' +
            ", flag=" + flag +
            ", properties=" + properties +
            ", body=" + Arrays.toString(body) +
            ", transactionId='" + transactionId + '\'' +
            '}';
    }
}

RocketMQ支持普通消息、分区有序消息、全局有序消息、延迟消息和事务消息

普通消息:普通消息也称为并发消息,和传统的队列相比,并发消息没有顺序,但是生产消费都是并行进行的,单机性能可达十万级别的TPS。

分区有序消息:与kafka中的分区类似,把一个Topic消息分为多个分区保存和消费,在一个分区内的消息就是传统的队列,遵循FIFO的原则。

全局有序消息:如果把一个topic的分区数设置为1,那么该topic中的消息就是单分区,所有消息都遵循FIFO的原则。

延迟消息:消息发送后,消费者要在一定时间后,或者指定某个时间点才可以消费。在没有延迟消息时,基本的做法是基于定时计划任务调度,定时发送消息。在RocketMQ中只需要在发送消息时设置延迟级别即可实现。

事务消息:主要涉及分布式事务,即需要保证在多个操作同时成功或者同时失败时,消费者才能消费消息。RocketMQ通过发送half消息、处理本地事务、提交消息或者回滚消息优雅地实现分布式事务。

生产者高可用

工作中不管Broker、Namesrv出现什么情况,我们都希望发送消息都不要出现未知状态或者消息丢失。在消息发送的过程中,客户端、Broker、Namesrv都有可能发生服务器损坏,掉电等各种故障。当这些故障发生时,RockerMQ是怎么处理的呢?

知乎文章中写的很全面,并附有代码,可以参考
https://zhuanlan.zhihu.com/p/434104817

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值