springboot集成rocketmq的mmap讲解

一、springboot rocektmq 消息分区demo

以下是 Spring Boot 集成 RocketMQ 实现消息分区的示例代码:

1、在 pom.xml 文件中添加 RocketMQ 的依赖

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

2、配置生产者

在配置文件中配置 RocketMQ 的生产者相关参数:

rocketmq.producer.group=my_group
rocketmq.namesrv.addr=localhost:9876

在代码中通过 @EnableConfigurationProperties 注解将配置类注入到 Spring 容器中:

@Configuration
@EnableConfigurationProperties(RocketMQProperties.class)
public class RocketMQProducerConfig {

    @Autowired
    private RocketMQProperties rocketMQProperties;

    @Bean(destroyMethod = "shutdown")
    public DefaultMQProducer defaultMQProducer() throws MQClientException {
        DefaultMQProducer producer = new DefaultMQProducer(rocketMQProperties.getProducer().getGroup());
        producer.setNamesrvAddr(rocketMQProperties.getNameSrvAddr());
        producer.start();
        return producer;
    }

}

3、发送消息,在发送消息时,可以通过设置消息的 hashKey 来实现消息的分区,例如:

@Service
public class OrderService {

    @Autowired
    private DefaultMQProducer producer;

    public void createOrder(Order order) throws Exception {
        Message message = new Message("OrderTopic", "createOrder", JSON.toJSONBytes(order));
        message.setKeys(order.getId().toString()); // 设置消息的 hashKey
        SendResult sendResult = producer.send(message);
        System.out.println("send result: " + sendResult);
    }

}

在消息发送时,将订单号作为消息的 hashKey,这样可以保证相同的订单号的消息被发送到同一个消息队列中,从而实现消息的分区。

需要注意的是,当消息被发送到相应的分区后,顺序消息的顺序将受到影响,因此需要在消费端按照分区顺序消费消息,以保证消息的顺序性。

二、消息队列中的零复制指什么?

队列中的零复制指的是一种无需在内存中进行数据复制的数据传输技术。在传统的数据传输过程中,发送端的数据需要先复制到操作系统内核缓冲区中,然后再从内核缓冲区复制到网络协议栈中,最终才能被发送到接收端。而在零复制技术中,数据可以直接从发送端的应用程序内存复制到网络协议栈中,从而避免了内核缓冲区的使用。

使用零复制技术可以提高数据传输的效率,减少数据复制的次数和时间,从而降低系统的负载和延迟。在队列系统中,零复制技术可以用于优化消息传输的性能,提高消息的吞吐量和传输效率。

RocketMQ 就是一种使用了零拷贝技术的消息队列系统。在 RocketMQ 中,消息的发送和接收都是通过直接操作内存来实现的,而不需要将消息复制到操作系统的内核缓冲区中,从而避免了不必要的数据复制和数据移动,提高了消息传输的效率和性能。这也是 RocketMQ 能够支持高吞吐量、低延迟的关键因素之一。

三、RocketMQ 如何实现数据可以直接从发送端的应用程序内存复制到网络协议栈中?

RocketMQ 使用了零拷贝技术来实现数据可以直接从发送端的应用程序内存复制到网络协议栈中。其基本原理是通过利用操作系统提供的 mmap 系统调用,将消息发送缓存区直接映射到用户进程的虚拟内存空间中,然后直接将消息数据写入缓存区中。

具体来说,RocketMQ 的零拷贝机制主要涉及以下两个方面:

1、使用 mmap 系统调用将消息发送缓存区映射到用户进程的虚拟内存空间中。这样,消息数据就可以直接写入到发送缓存区中,而无需经过内核缓冲区的复制。当消息数据被写入到发送缓存区中后,发送线程就可以直接将消息数据从发送缓存区中复制到网络协议栈中,从而实现零拷贝传输。

2、使用 ByteBuffer 对象来管理发送缓存区的内存。RocketMQ 在发送缓存区上包装了一个 ByteBuffer 对象,通过 put() 方法将消息数据写入缓存区,然后通过 ByteBuffer 对象提供的 flip() 方法将缓存区的写指针指向消息数据的开始位置。这样一来,发送线程就可以通过 ByteBuffer 对象提供的 get() 方法从缓存区中直接读取消息数据,而无需再进行一次复制。

总之,RocketMQ 的零拷贝机制是通过操作系统提供的 mmap 系统调用和 ByteBuffer 对象来实现的,从而实现了数据可以直接从发送端的应用程序内存复制到网络协议栈中。这样可以避免不必要的数据复制和数据移动,提高了消息传输的效率和性能。

四、什么是操作系统mmap?

mmap 是一种在操作系统中实现文件映射到内存的机制,可以将一个文件或其他对象映射到进程地址空间的一部分,使得进程可以像访问内存一样访问文件,从而实现了文件和内存之间的无缝连接。

在 mmap 机制中,操作系统将文件映射到进程的虚拟地址空间,使得进程可以通过访问该地址空间来读写文件内容,而无需使用 read() 和 write() 等系统调用。此外,如果多个进程映射了同一个文件,它们之间可以通过共享内存的方式来共享数据,从而实现了多进程之间的通信。

mmap 主要有两个优点:

1、通过将文件映射到内存中,可以实现零拷贝机制,从而避免了数据在内存和磁盘之间的频繁复制,提高了性能和效率。

2、可以将文件映射到进程的虚拟地址空间中,使得进程可以像访问内存一样访问文件,从而简化了文件操作的流程。

在实际应用中,mmap 主要用于以下两个方面:

1、将大文件映射到内存中,以便进行快速访问和处理。

2、将多个进程需要共享的数据结构映射到共享内存中,以便进行进程间通信和数据共享。

在消息队列系统中,RocketMQ 使用了 mmap 机制来实现零拷贝传输,从而提高了消息传输的性能和效率。同时,通过将消息发送缓存区映射到进程的虚拟地址空间中,RocketMQ 使得消息可以直接从发送端的应用程序内存复制到网络协议栈中,从而避免了不必要的数据复制和数据移动,提高了消息传输的效率和性能。

五、采用mmap的共享内存方式实现进程通信,用java语言实现一个demo

以下是一个使用 Java 语言实现 mmap 共享内存方式实现进程通信的示例代码:

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MMapDemo {
    private static final int BUFFER_SIZE = 1024 * 1024;
    private static final String FILE_NAME = "shared.dat";

    public static void main(String[] args) throws IOException, InterruptedException {
        File file = new File(FILE_NAME);

        // 创建共享内存
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        MappedByteBuffer buffer = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, BUFFER_SIZE);
        buffer.clear();

        // 在共享内存中写入数据
        buffer.putInt(10);
        buffer.putLong(System.currentTimeMillis());
        buffer.flip();

        // 创建子进程并读取共享内存中的数据
        Process p = Runtime.getRuntime().exec("java ChildProcess");
        p.waitFor();

        // 从共享内存中读取子进程写入的数据
        buffer.clear();
        int num = buffer.getInt();
        long time = buffer.getLong();

        System.out.println("num: " + num);
        System.out.println("time: " + time);

        raf.close();
        file.delete();
    }
}

// 子进程读取共享内存中的数据
class ChildProcess {
    public static void main(String[] args) throws IOException {
        File file = new File(MMapDemo.FILE_NAME);

        // 打开共享内存
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        MappedByteBuffer buffer = raf.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, MMapDemo.BUFFER_SIZE);
        buffer.clear();

        // 从共享内存中读取数据
        int num = buffer.getInt();
        long time = buffer.getLong();

        // 在共享内存中写入数据
        buffer.clear();
        buffer.putInt(num * 2);
        buffer.putLong(System.currentTimeMillis());
        buffer.flip();

        raf.close();
    }
}

该示例代码通过创建一个共享内存区域,并在共享内存中写入数据,然后启动一个子进程来读取共享内存中的数据,并在共享内存中写入数据,最后再从共享内存中读取子进程写入的数据。通过共享内存的方式,实现了进程之间的通信。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容