最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot+Disruptor實現(xiàn)特快高并發(fā)處理

 更新時間:2026年04月28日 08:36:24   作者:皮皮林551  
文章介紹了Disruptor的概念、核心組件、應(yīng)用場景及其工作原理,Disruptor是一個高性能的消息隊列框架,由LMAX開發(fā),適用于解決生產(chǎ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)的方案。

03、Disruptor 的核心概念

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

04、Ring Buffer

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

05、Sequence Disruptor

通過順序遞增的序號來編號管理通過其進行交換的數(shù)據(jù)(事件),對數(shù)據(jù)(事件)的處理過程總是沿著序號逐個遞增處理。一個 Sequence 用于跟蹤標識某個特定的事件處理者( RingBuffer/Consumer )的處理進度。雖然一個 AtomicLong 也可以用于標識進度,但定義 Sequence 來負責該問題還有另一個目的,那就是防止不同的 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 沒有定義特定接口或類型。

Disruptor 核心概念圖

13、案例-demo

通過下面 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
publicclass 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
publicclass BeanManager implements ApplicationContextAware {

    privatestatic 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);
    }

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

6、構(gòu)造 MQManager

@Configuration
publicclass 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
publicclass 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)造測試類及方法

@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 為什么高效的原因。

以上就是SpringBoot+Disruptor實現(xiàn)特快高并發(fā)處理的詳細內(nèi)容,更多關(guān)于SpringBoot Disruptor高并發(fā)處理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot日志進階實戰(zhàn)之Logback配置經(jīng)驗和方法

    SpringBoot日志進階實戰(zhàn)之Logback配置經(jīng)驗和方法

    本文給大家介紹在SpringBoot中使用Logback配置日志的經(jīng)驗和方法,并提供了詳細的代碼示例和解釋,包括:滾動文件、異步日志記錄、動態(tài)指定屬性、日志級別、配置文件等常用功能,覆蓋日常Logback配置開發(fā)90%的知識點,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • Java設(shè)計模式之橋接模式

    Java設(shè)計模式之橋接模式

    這篇文章介紹了Java設(shè)計模式之橋接模式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • 利用Java實現(xiàn)更改Word中的頁面大小和頁面方向

    利用Java實現(xiàn)更改Word中的頁面大小和頁面方向

    這篇文章主要為大家詳細介紹了一種高效便捷的方法——通過Java應(yīng)用程序,以編程方式更改Word中的頁面大小和頁面方向,感興趣的可以了解一下
    2023-03-03
  • Linux部署springboot項目彩色日志打印方式

    Linux部署springboot項目彩色日志打印方式

    這篇文章主要介紹了Linux部署springboot項目彩色日志打印方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • MyBatis實現(xiàn)兩種查詢樹形數(shù)據(jù)的方法詳解(嵌套結(jié)果集和遞歸查詢)

    MyBatis實現(xiàn)兩種查詢樹形數(shù)據(jù)的方法詳解(嵌套結(jié)果集和遞歸查詢)

    樹形結(jié)構(gòu)數(shù)據(jù)在開發(fā)中十分常見,比如:菜單數(shù)、組織樹, 利用 MyBatis 提供嵌套查詢功能可以很方便地實現(xiàn)這個功能需求。本文主要介紹了兩種方法,感興趣的可以了解一下
    2021-09-09
  • 在MyBatis中進行分頁查詢的兩種方法詳解

    在MyBatis中進行分頁查詢的兩種方法詳解

    在 MyBatis 中進行分頁查詢通常有兩種方法:一種是通過手動拼接 LIMIT 和 OFFSET,另一種是使用 MyBatis 插件(如 MyBatis-PageHelper)來自動處理分頁邏輯,下面分別介紹這兩種方法,需要的朋友可以參考下
    2025-11-11
  • SpringMVC設(shè)置全局異常處理器的步驟

    SpringMVC設(shè)置全局異常處理器的步驟

    在項目中我們有需求做一個全局異常處理,來規(guī)范所有出去的異常信息,這篇文章主要介紹了SpringMVC設(shè)置全局異常處理器,需要的朋友可以參考下
    2024-03-03
  • Java 阻塞隊列和線程池原理分析

    Java 阻塞隊列和線程池原理分析

    這篇文章主要介紹了Java 阻塞隊列和線程池原理分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • SpringBoot整合MyBatis Plus實現(xiàn)基本CRUD與高級功能

    SpringBoot整合MyBatis Plus實現(xiàn)基本CRUD與高級功能

    Spring Boot是一款用于快速構(gòu)建Spring應(yīng)用程序的框架,而MyBatis Plus是MyBatis的增強工具,本文將詳細介紹如何在Spring Boot項目中整合MyBatis Plus,并展示其基本CRUD功能以及高級功能的實現(xiàn)方式,需要的朋友可以參考下
    2024-02-02
  • Java 獲取當前類名和方法名的實現(xiàn)方法

    Java 獲取當前類名和方法名的實現(xiàn)方法

    這篇文章主要介紹了 Java 獲取當前類名和方法名的實現(xiàn)方法的相關(guān)資料,這里不僅提供了實現(xiàn)方法并比較幾種方法的效率,需要的朋友可以參考下
    2017-07-07

最新評論

新干县| 时尚| 秦皇岛市| 黄大仙区| 宁国市| 益阳市| 社旗县| 灵宝市| 西充县| 子长县| 肃北| 凤山市| 疏勒县| 霍州市| 彩票| 永登县| 宁远县| 襄汾县| 东乡族自治县| 南丹县| 阳谷县| 河津市| 广汉市| 平遥县| 若尔盖县| 云霄县| 中西区| 九龙坡区| 梧州市| 宣武区| 舞阳县| 云龙县| 孝感市| 德令哈市| 韶山市| 富蕴县| 婺源县| 曲松县| 秦皇岛市| 上饶市| 全州县|