国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Boot + Disruptor 實現(xiàn)消息隊列,告訴你什么叫快、什么叫高效!

這篇具有很好參考價值的文章主要介紹了Spring Boot + Disruptor 實現(xiàn)消息隊列,告訴你什么叫快、什么叫高效!。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

01、背景

工作中遇到項目使用Disruptor做消息隊列,對你沒看錯,不是Kafka,也不是rabbitmq;Disruptor有個最大的優(yōu)點就是快,還有一點它是開源的哦,下面做個簡單的記錄.

02、Disruptor介紹

  1. Disruptor 是英國外匯交易公司LMAX開發(fā)的一個高性能隊列,研發(fā)的初衷是解決內(nèi)存隊列的延遲問題(在性能測試中發(fā)現(xiàn)竟然與I/O操作處于同樣的數(shù)量級)?;?Disruptor 開發(fā)的系統(tǒng)單線程能支撐每秒 600 萬訂單,2010 年在 QCon 演講后,獲得了業(yè)界關(guān)注。
  2. Disruptor是一個開源的Java框架,它被設(shè)計用于在生產(chǎn)者—消費者(producer-consumer problem,簡稱PCP)問題上獲得盡量高的吞吐量(TPS)和盡量低的延遲。
  3. 從功能上來看,Disruptor 是實現(xiàn)了“隊列”的功能,而且是一個有界隊列。那么它的應(yīng)用場景自然就是“生產(chǎn)者-消費者”模型的應(yīng)用場合了。
  4. Disruptor是LMAX在線交易平臺的關(guān)鍵組成部分,LMAX平臺使用該框架對訂單處理速度能達到600萬TPS,除金融領(lǐng)域之外,其他一般的應(yīng)用中都可以用到Disruptor,它可以帶來顯著的性能提升。
  5. 其實Disruptor與其說是一個框架,不如說是一種設(shè)計思路,這個設(shè)計思路對于存在“并發(fā)、緩沖區(qū)、生產(chǎn)者—消費者模型、事務(wù)處理”這些元素的程序來說,Disruptor提出了一種大幅提升性能(TPS)的方案。
  6. Disruptor的github主頁:https://github.com/LMAX-Exchange/disruptor

03、Disruptor 的核心概念

先從了解 Disruptor 的核心概念開始,來了解它是如何運作的。下面介紹的概念模型,既是領(lǐng)域?qū)ο?,也是映射到代碼實現(xiàn)上的核心對象。

04、Ring Buffer

如其名,環(huán)形的緩沖區(qū)。曾經(jīng) RingBuffer 是 Disruptor 中的最主要的對象,但從3.0版本開始,其職責(zé)被簡化為僅僅負責(zé)對通過 Disruptor 進行交換的數(shù)據(jù)(事件)進行存儲和更新。在一些更高級的應(yīng)用場景中,Ring Buffer 可以由用戶的自定義實現(xiàn)來完全替代。

05、Sequence Disruptor

通過順序遞增的序號來編號管理通過其進行交換的數(shù)據(jù)(事件),對數(shù)據(jù)(事件)的處理過程總是沿著序號逐個遞增處理。一個 Sequence 用于跟蹤標識某個特定的事件處理者( RingBuffer/Consumer )的處理進度。

雖然一個 AtomicLong 也可以用于標識進度,但定義 Sequence 來負責(zé)該問題還有另一個目的,那就是防止不同的 Sequence 之間的CPU緩存?zhèn)喂蚕?Flase Sharing)問題。(注:這是 Disruptor 實現(xiàn)高性能的關(guān)鍵點之一,網(wǎng)上關(guān)于偽共享問題的介紹已經(jīng)汗牛充棟,在此不再贅述)。

06、Sequencer

Sequencer 是 Disruptor 的真正核心。此接口有兩個實現(xiàn)類 SingleProducerSequencer、MultiProducerSequencer ,它們定義在生產(chǎn)者和消費者之間快速、正確地傳遞數(shù)據(jù)的并發(fā)算法。

07、Sequence Barrier

用于保持對RingBuffer的 main published Sequence 和Consumer依賴的其它Consumer的 Sequence 的引用。Sequence Barrier 還定義了決定 Consumer 是否還有可處理的事件的邏輯。

08、Wait Strategy

定義 Consumer 如何進行等待下一個事件的策略。(注:Disruptor 定義了多種不同的策略,針對不同的場景,提供了不一樣的性能表現(xiàn))

09、Event

在 Disruptor 的語義中,生產(chǎn)者和消費者之間進行交換的數(shù)據(jù)被稱為事件(Event)。它不是一個被 Disruptor 定義的特定類型,而是由 Disruptor 的使用者定義并指定。

10、EventProcessor

EventProcessor 持有特定消費者(Consumer)的 Sequence,并提供用于調(diào)用事件處理實現(xiàn)的事件循環(huán)(Event Loop)。

11、EventHandler

Disruptor 定義的事件處理接口,由用戶實現(xiàn),用于處理事件,是 Consumer 的真正實現(xiàn)。

12、Producer

即生產(chǎn)者,只是泛指調(diào)用 Disruptor 發(fā)布事件的用戶代碼,Disruptor 沒有定義特定接口或類型。

Spring Boot + Disruptor 實現(xiàn)消息隊列,告訴你什么叫快、什么叫高效!

13、案例-demo

推薦一個 Spring Boot 基礎(chǔ)教程及實戰(zhàn)示例:https://github.com/javastacks/spring-boot-best-practice

通過下面8個步驟,你就能將Disruptor Get回家啦:

1、添加pom.xml依賴

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.4</version>
</dependency>

2、消息體Model

/**
 * 消息體
 */
@Data
public class MessageModel {
    private String message;
}

3、構(gòu)造EventFactory

public class HelloEventFactory implements EventFactory<MessageModel> {
    @Override
    public MessageModel newInstance() {
        return new MessageModel();
    }
}

4、構(gòu)造EventHandler-消費者

@Slf4j
public class HelloEventHandler implements EventHandler<MessageModel> {
    @Override
    public void onEvent(MessageModel event, long sequence, boolean endOfBatch) {
        try {
            //這里停止1000ms是為了確定消費消息是異步的
            Thread.sleep(1000);
            log.info("消費者處理消息開始");
            if (event != null) {
                log.info("消費者消費的信息是:{}",event);
            }
        } catch (Exception e) {
            log.info("消費者處理消息失敗");
        }
        log.info("消費者處理消息結(jié)束");
    }
}

5、構(gòu)造BeanManager

/**
 * 獲取實例化對象
 */
@Component
public class BeanManager implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() { return applicationContext; }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

6、構(gòu)造MQManager

@Configuration
public class MQManager {

    @Bean("messageModel")
    public RingBuffer<MessageModel> messageModelRingBuffer() {
        //定義用于事件處理的線程池, Disruptor通過java.util.concurrent.ExecutorSerivce提供的線程來觸發(fā)consumer的事件處理
        ExecutorService executor = Executors.newFixedThreadPool(2);

        //指定事件工廠
        HelloEventFactory factory = new HelloEventFactory();

        //指定ringbuffer字節(jié)大小,必須為2的N次方(能將求模運算轉(zhuǎn)為位運算提高效率),否則將影響效率
        int bufferSize = 1024 * 256;

        //單線程模式,獲取額外的性能
        Disruptor<MessageModel> disruptor = new Disruptor<>(factory, bufferSize, executor,
                ProducerType.SINGLE, new BlockingWaitStrategy());

        //設(shè)置事件業(yè)務(wù)處理器---消費者
        disruptor.handleEventsWith(new HelloEventHandler());

        // 啟動disruptor線程
        disruptor.start();

        //獲取ringbuffer環(huán),用于接取生產(chǎn)者生產(chǎn)的事件
        RingBuffer<MessageModel> ringBuffer = disruptor.getRingBuffer();

        return ringBuffer;
    }

7、構(gòu)造Mqservice和實現(xiàn)類-生產(chǎn)者

public interface DisruptorMqService {

    /**
     * 消息
     * @param message
     */
    void sayHelloMq(String message);
}

@Slf4j
@Component
@Service
public class DisruptorMqServiceImpl implements DisruptorMqService {

    @Autowired
    private RingBuffer<MessageModel> messageModelRingBuffer;

    @Override
    public void sayHelloMq(String message) {
        log.info("record the message: {}",message);
        //獲取下一個Event槽的下標
        long sequence = messageModelRingBuffer.next();
        try {
            //給Event填充數(shù)據(jù)
            MessageModel event = messageModelRingBuffer.get(sequence);
            event.setMessage(message);
            log.info("往消息隊列中添加消息:{}", event);
        } catch (Exception e) {
            log.error("failed to add event to messageModelRingBuffer for : e = {},{}",e,e.getMessage());
        } finally {
            //發(fā)布Event,激活觀察者去消費,將sequence傳遞給改消費者
            //注意最后的publish方法必須放在finally中以確保必須得到調(diào)用;如果某個請求的sequence未被提交將會堵塞后續(xù)的發(fā)布操作或者其他的producer
            messageModelRingBuffer.publish(sequence);
        }
    }
}

8、構(gòu)造測試類及方法

Spring Boot 基礎(chǔ)就不介紹了,推薦下這個實戰(zhàn)教程:
https://github.com/javastacks/spring-boot-best-practice

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

    @Autowired
    private DisruptorMqService disruptorMqService;
    /**
     * 項目內(nèi)部使用Disruptor做消息隊列
     * @throws Exception
     */
    @Test
    public void sayHelloMqTest() throws Exception{
        disruptorMqService.sayHelloMq("消息到了,Hello world!");
        log.info("消息隊列已發(fā)送完畢");
        //這里停止2000ms是為了確定是處理消息是異步的
        Thread.sleep(2000);
    }
}

測試運行結(jié)果

2020-04-05 14:31:18.543  INFO 7274 --- [           main] c.e.u.d.d.s.Impl.DisruptorMqServiceImpl  : record the message: 消息到了,Hello world!
2020-04-05 14:31:18.545  INFO 7274 --- [           main] c.e.u.d.d.s.Impl.DisruptorMqServiceImpl  : 往消息隊列中添加消息:MessageModel(message=消息到了,Hello world!)
2020-04-05 14:31:18.545  INFO 7274 --- [           main] c.e.utils.demo.DemoApplicationTests      : 消息隊列已發(fā)送完畢
2020-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler    : 消費者處理消息開始
2020-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler    : 消費者消費的信息是:MessageModel(message=消息到了,Hello world!)
2020-04-05 14:31:19.547  INFO 7274 --- [pool-1-thread-1] c.e.u.d.disrupMq.mq.HelloEventHandler    : 消費者處理消息結(jié)束

14、總結(jié)

其實 生成者 -> 消費者 模式是很常見的,通過一些消息隊列也可以輕松做到上述的效果。不同的地方在于,Disruptor 是在內(nèi)存中以隊列的方式去實現(xiàn)的,而且是無鎖的。

這也是 Disruptor 為什么高效的原因。

版權(quán)聲明:本文為CSDN博主「不二天次」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/buertianci/article/details/105327031

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協(xié)程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優(yōu)雅的方式??!

5.《Java開發(fā)手冊(嵩山版)》最新發(fā)布,速速下載!

覺得不錯,別忘了隨手點贊+轉(zhuǎn)發(fā)哦!文章來源地址http://www.zghlxwxcb.cn/news/detail-712201.html

到了這里,關(guān)于Spring Boot + Disruptor 實現(xiàn)消息隊列,告訴你什么叫快、什么叫高效!的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Spring Boot 3.x 系列【32】集成消息隊列

    有道無術(shù),術(shù)尚可求,有術(shù)無道,止于術(shù)。 本系列Spring Boot版本3.0.5 源碼地址:https://gitee.com/pearl-organization/study-spring-boot3 MQ/

    2024年02月04日
    瀏覽(18)
  • 第二章 Spring Boot 整合 Kafka消息隊列 生產(chǎn)者

    第一章 Kafka 配置部署及SASL_PLAINTEXT安全認證 第二章??Spring Boot 整合 Kafka消息隊列?生產(chǎn)者 第三章??Spring Boot 整合 Kafka消息隊列?消息者 ????????Kafka 是一個消息隊列產(chǎn)品,基于Topic partitions的設(shè)計,能達到非常高的消息發(fā)送處理性能。本文主是基于Spirng Boot封裝了Apache 的

    2024年01月25日
    瀏覽(17)
  • Spring Boot進階(62):Redis魔法:用發(fā)布訂閱功能打造高效消息隊列!

    Spring Boot進階(62):Redis魔法:用發(fā)布訂閱功能打造高效消息隊列!

    ? ? ? ? 話說,玩過MQ的同學(xué)可能都知道【發(fā)布訂閱】模式,不就是一種消息傳遞方式嘛;如果沒玩過,那也不打緊,下文我會簡單做個科普。但是對于Redis如何實現(xiàn)MQ的【發(fā)布訂閱】功能?這才是問題的關(guān)鍵,有的同學(xué)就說“壓根沒玩過呀!不造” ,哈哈,bug菌既然敢寫便有

    2024年02月09日
    瀏覽(27)
  • Spring Boot 中的 RabbitMQ 的消息接收配置是什么,原理,如何使用

    Spring Boot 中的 RabbitMQ 的消息接收配置是什么,原理,如何使用

    RabbitMQ 是一個流行的消息隊列系統(tǒng),它可以用于在應(yīng)用程序之間傳遞消息。Spring Boot 提供了對 RabbitMQ 的支持,我們可以使用 Spring Boot 中的 RabbitMQ 消息接收配置來接收 RabbitMQ 中的消息。本文將介紹 RabbitMQ 的消息接收配置的原理和如何在 Spring Boot 中使用它。 在 RabbitMQ 中,消

    2024年02月13日
    瀏覽(22)
  • Spring Boot 如何實現(xiàn)異步消息處理

    Spring Boot 如何實現(xiàn)異步消息處理

    在現(xiàn)代應(yīng)用程序中,異步消息處理是一項至關(guān)重要的任務(wù)。它可以提高應(yīng)用程序的性能、可伸縮性和可靠性,同時也可以提供更好的用戶體驗。Spring Boot提供了多種方式來實現(xiàn)異步消息處理,包括使用Spring AMQP、Spring Kafka和Spring JMS等。本文將介紹如何使用Spring Boot實現(xiàn)異步消息

    2024年02月07日
    瀏覽(45)
  • 【Spring Boot】Spring Boot 集成 RocketMQ 實現(xiàn)簡單的消息發(fā)送和消費

    【Spring Boot】Spring Boot 集成 RocketMQ 實現(xiàn)簡單的消息發(fā)送和消費

    本文主要有以下內(nèi)容: 簡單消息的發(fā)送 順序消息的發(fā)送 RocketMQTemplate的API介紹 環(huán)境搭建: RocketMQ的安裝教程:在官網(wǎng)上下載bin文件,解壓到本地,并配置環(huán)境變量,如下圖所示: 在 Spring boot 項目中引入 RocketMQ 依賴: 在application.yml增加相關(guān)配置: 在 Spring Boot 中使用RocketM

    2024年02月14日
    瀏覽(93)
  • 高效處理消息:使用Spring Boot實現(xiàn)消息重試機制

    高效處理消息:使用Spring Boot實現(xiàn)消息重試機制

    當(dāng)涉及到消息發(fā)送和接收的可靠性,Spring Boot提供了一些機制來確保消息的可靠傳遞。其中包括消息確認機制和重試機制。下面是一個示例代碼,演示如何在Spring Boot中實現(xiàn)可靠的消息發(fā)送和接收。 首先,我們需要配置RabbitMQ的連接信息和相關(guān)屬性。在 application.properties 文件中

    2024年02月11日
    瀏覽(34)
  • Spring Boot集成WebSocket實現(xiàn)消息推送

    Spring Boot集成WebSocket實現(xiàn)消息推送

    項目中經(jīng)常會用到消息推送功能,關(guān)于推送技術(shù)的實現(xiàn),我們通常會聯(lián)想到輪詢、comet長連接技術(shù),雖然這些技術(shù)能夠?qū)崿F(xiàn),但是需要反復(fù)連接,對于服務(wù)資源消耗過大,隨著技術(shù)的發(fā)展,HtML5定義了WebSocket協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實時地進行通訊。

    2023年04月08日
    瀏覽(21)
  • Spring Boot 整合 RabbitMQ 實現(xiàn)延遲消息

    Spring Boot 整合 RabbitMQ 實現(xiàn)延遲消息

    消息隊列(Message Queuing,簡寫為 MQ)最初是為了解決金融行業(yè)的特定業(yè)務(wù)需求而產(chǎn)生的。慢慢的,MQ 被應(yīng)用到了更多的領(lǐng)域,然而商業(yè) MQ 高昂的價格讓很多初創(chuàng)公司望而卻步,于是 AMQP(Advanced Message Queuing Protocol,高級消息隊列協(xié)議)應(yīng)運而生。 隨著 AMQP 草案的發(fā)布,兩個月

    2024年04月08日
    瀏覽(29)
  • redis — 基于Spring Boot實現(xiàn)redis延遲隊列

    redis — 基于Spring Boot實現(xiàn)redis延遲隊列

    1. 業(yè)務(wù)場景 延時隊列場景在我們?nèi)粘I(yè)務(wù)開發(fā)中經(jīng)常遇到,它是一種特殊類型的消息隊列,它允許把消息發(fā)送到隊列中,但不立即投遞給消費者,而是在一定時間后再將消息投遞給消費者。延遲隊列的常見使用場景有以下幾種: 在各種購物平臺上下單,訂單超過30分鐘未支付

    2024年02月13日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包