高性能キューかく乱チュートリアル

かく乱何ですか

かく乱が英国の外国為替会社は、LMAXキュー高性能を開発したオリジナルの意図は、メモリレイテンシキューの問題を解決することでした開発である(同じ大きさのオーダーであっても、I / O操作でパフォーマンステストで見つかりました)。かく乱は、のQConのスピーチの後、2010年には、業界の注目へのアクセスを毎秒600万件のオーダーをサポートすることができ、シングルスレッドのシステムをベースに開発しました。2011年には、Martin Fowler氏に捧げエンタープライズ・アプリケーション・ソフトウェアの専門家は説明長い記事を書きました。同じ年にも受賞Oracleの公式公爵を獲得しました。データ構造の観点からは、かく乱のサポートがある>消費者-プロデューサーモード循環キューすることができますロックなしの条件でパラレル消費のために、また、消費のために準じて行うことができません消費者の間の依存関係を持っています。この記事では、かく乱によって、古典的なシーンのいくつかを達成する方法を示します。

依存追加

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.4.2</version>
</dependency>
复制代码

シングルプロデューサーシングル・コンシューマ・モデル

まず、作成しOrderEventたメッセージの内容として円形のキューに配置されるクラス。

@Data
public class OrderEvent {
    private String id;
}
复制代码

作成OrderEventProducerプロデューサーとして使用されるクラスを。

public class OrderEventProducer {
    private final RingBuffer<OrderEvent> ringBuffer;
    public OrderEventProducer(RingBuffer<OrderEvent> ringBuffer) {
        this.ringBuffer = ringBuffer;
    }
    public void onData(String orderId) {
        long sequence = ringBuffer.next();
        try {
            OrderEvent orderEvent = ringBuffer.get(sequence);
            orderEvent.setId(orderId);
        } finally {
            ringBuffer.publish(sequence);
        }
    }
}
复制代码

作成しOrderEventHandlerたクラスを実装し、EventHandler<T>かつWorkHandler<T>、消費者として、インターフェース。

@Slf4j
public class OrderEventHandler implements EventHandler<OrderEvent>, WorkHandler<OrderEvent> {
    @Override
    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) {
        log.info("event: {}, sequence: {}, endOfBatch: {}", event, sequence, endOfBatch);
    }
    @Override
    public void onEvent(OrderEvent event) {
        log.info("event: {}", event);
    }
}
复制代码

あなたは、次の3つのカテゴリの上に作成した後、我々はすでに持っている事件类生产者消费者これら3つの要素。次はメインメソッドのシリーズを通じて、このプロセスを示しています。

@Slf4j
public class DisruptorDemo {
    public static void main(String[] args) throws InterruptedException {
        Disruptor<OrderEvent> disruptor = new Disruptor<>(
                OrderEvent::new,
                1024 * 1024,
                Executors.defaultThreadFactory(),
                ProducerType.SINGLE,
                new YieldingWaitStrategy()
        );
        disruptor.handleEventsWith(new OrderEventHandler());
        disruptor.start();
        RingBuffer<OrderEvent> ringBuffer = disruptor.getRingBuffer();
        OrderEventProducer eventProducer = new OrderEventProducer(ringBuffer);
        eventProducer.onData(UUID.randomUUID().toString());
    }
}
复制代码

シングルプロデューサーより多くの消費者

消費者はより多くの場合、あなただけが呼び出す必要がありhandleEventsWith、複数の消費者への送達の方法に。次のコードは、2つの消費者に渡します。

- disruptor.handleEventsWith(new OrderEventHandler());
+ disruptor.handleEventsWith(new OrderEventHandler(), new OrderEventHandler());
复制代码

2つのコンシューマ上の着信の繰り返しでは、複数の消費者の場合には達成したい場合は、消費者が消費者のみになります、あなたが呼び出す必要があり、各メッセージ、メッセージを消費しますhandleEventsWithWorkerPool方法を。

- disruptor.handleEventsWith(new OrderEventHandler());
+ disruptor.handleEventsWithWorkerPool(new OrderEventHandler(), new OrderEventHandler());
复制代码

そして、より多くの生産者や多くの消費者

実際の開発では、複数のプロデューサがメッセージを送信、メッセージを処理するより多くの消費者が当たり前です。これは、かく乱もサポートされています。そして、より多くの生産者や多くの消費者のコードは次のよう:

@Slf4j
public class DisruptorDemo {
    public static void main(String[] args) throws InterruptedException {
        Disruptor<OrderEvent> disruptor = new Disruptor<>(
                OrderEvent::new,
                1024 * 1024,
                Executors.defaultThreadFactory(),
                // 这里的枚举修改为多生产者
                ProducerType.MULTI,
                new YieldingWaitStrategy()
        );
        disruptor.handleEventsWithWorkerPool(new OrderEventHandler(), new OrderEventHandler());
        disruptor.start();
        RingBuffer<OrderEvent> ringBuffer = disruptor.getRingBuffer();
        OrderEventProducer eventProducer = new OrderEventProducer(ringBuffer);
        // 创建一个线程池,模拟多个生产者
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(100);
        for (int i = 0; i < 100; i++) {
            fixedThreadPool.execute(() -> eventProducer.onData(UUID.randomUUID().toString()));
        }
    }
}
复制代码

消費者の優先順位

かく乱は、はるか以上の内容よりも、物事を行うことができます。実際の場面では、我々は通常のビジネス・ロジックは、消費のチェーンを形成しているため。例えば、メッセージは、によって行われなければならない消费者A -> 消费者B -> 消费者Cために消費します。消費者を設定する際に.then実装します。次のとおりです。

disruptor.handleEventsWith(new OrderEventHandler())
         .then(new OrderEventHandler())
         .then(new OrderEventHandler());
复制代码

もちろん、handleEventsWithとのhandleEventsWithWorkerPoolすべてのサポート.then、およびそれらを組み合わせて使用することができます。たとえば、あなたが従うことができ消费者A -> (消费者B 消费者C) -> 消费者D、消費者のために

disruptor.handleEventsWith(new OrderEventHandler())
         .thenHandleEventsWithWorkerPool(new OrderEventHandler(), new OrderEventHandler())
         .then(new OrderEventHandler());
复制代码

概要

これらは一般的な方法かく乱高性能キューです。実際には、生成者 -> 消费者パターンは、メッセージキューの数によって簡単に上記の効果を行うことができ、非常に一般的です。違いは、キュー達成する方法が、ロックなしにかく乱メモリでは、ということです。また、これは理由は、効率的なかく乱です。

参考リンク

おすすめ

転載: juejin.im/post/5df5fc99518825123e7af4ae