High Performance(2)Ringbuffer and Disruptor

本文详细介绍了Disruptor的工作原理及其实现细节,包括Ringbuffer、Disruptor组件、简单生产者消费者模式等。通过具体代码示例,展示了如何在高并发场景下高效地进行事件处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

High Performance(2)Ringbuffer and Disruptor

1. Disruptor Introduction
a set circle array, lock-free ring buffer
Component - Ringbuffer
current number % size = order number   12%10=2 
the end of the array is managed by consumer.

Component - Sequence
thread safe, counter

Component - SequenceBarrier
consumers wait for sequence

Component - WaitStrategy
BusySpinWaitStrategy, BlockingWaitStrategy, SleepingWaitStrategy, YieldingWaitStragegy
PhasedBackoffWaitStrategy

BactchEventProcessor
consumer

WorkProcessor
consumers share one sequence

WorkerPool
All the WorkProcessor which share the same Sequence are managed by WorkerPool

2. Simple Producer and Consumer
All the example codes are in easydisruptor.
dependencies
libraryDependencies ++= Seq(
    "org.scalatest"       %   "scalatest_2.10"            % "1.9.1"   % "test",
    "org.specs2"          %%  "specs2"                    % "1.13"    % "test",
    "com.lmax"            %   "disruptor"                 % "3.3.0"
)

model
package com.sillycat.easydisruptor.model
class LongEvent(){
  var value = Long.MinValue
}
factory
package com.sillycat.easydisruptor.factory
import com.lmax.disruptor.EventFactory
import com.sillycat.easydisruptor.model.LongEvent

class LongEventFactory extends EventFactory[LongEvent] {
  def  newInstance():LongEvent = {
    return new LongEvent()
  }
}

translator
package com.sillycat.easydisruptor.translator

import com.sillycat.easydisruptor.model.LongEvent
import java.nio.ByteBuffer
import com.lmax.disruptor.EventTranslatorOneArg;

class CustomEventTranslatorOneArg extends EventTranslatorOneArg[LongEvent,ByteBuffer]{

  def translateTo(event: LongEvent, sequence: Long, bb: ByteBuffer) = {
    event.value = bb.getLong(0)
  }

}

consumer
package com.sillycat.easydisruptor.consumer

import com.lmax.disruptor.EventHandler
import com.sillycat.easydisruptor.model.LongEvent

class LongEventHandler extends EventHandler[LongEvent]{

  def onEvent(event:LongEvent,sequence:Long,endOfBatch:Boolean): Unit ={
    println("Event: " + event.value)
  }

}

producer
package com.sillycat.easydisruptor.producer

import com.lmax.disruptor.RingBuffer
import java.nio.ByteBuffer
import com.sillycat.easydisruptor.translator.CustomEventTranslatorOneArg
import com.sillycat.easydisruptor.model.LongEvent

class LongEventProducer(ringBuffer: RingBuffer[LongEvent]) {
  val translator = new CustomEventTranslatorOneArg()
  def onData(bb:ByteBuffer) = {
    ringBuffer.publishEvent(translator,bb)
  }
}

App to run
package com.sillycat.easydisruptor

import java.util.concurrent.Executors
import com.sillycat.easydisruptor.factory.LongEventFactory
import com.lmax.disruptor.dsl.Disruptor
import com.sillycat.easydisruptor.consumer.LongEventHandler
import com.sillycat.easydisruptor.producer.LongEventProducer
import java.nio.ByteBuffer

object LongEventApp extends App{
  val executor = Executors.newCachedThreadPool()
  val factory = new LongEventFactory()

  // Specify the size of the ring buffer, must be power of 2.
  val bufferSize = 1024

  val disruptor = new Disruptor(factory, bufferSize, executor)
  //set consumer/handler
  disruptor.handleEventsWith(new LongEventHandler())
  disruptor.start()

  val ringBuffer = disruptor.getRingBuffer()
  val producer = new LongEventProducer(ringBuffer)

  val bb = ByteBuffer.allocate(8);
  for( a <- 1 to 10){
    bb.putLong(0, a)
    producer.onData(bb)
    Thread.sleep(1000)
  }
  sys.exit(0)
}

We can also define the Disruptor as follow:
val disruptor = new Disruptor[LongEvent](factory, bufferSize, executor,ProducerType.SINGLE, new SleepingWaitStrategy())


References:
http://developer.51cto.com/art/201306/399341.htm
http://liuxun.org/blog/disruptor-yi-ge-kai-yuan-de-gao-xiao-nei-cun-wu-suo-dui-lie/
http://ziyue1987.github.io/pages/2013/09/22/disruptor-use-manual.html

http://lmax-exchange.github.io/disruptor/

More Example
https://code.google.com/p/disruptor/source/browse/trunk/code/src/perf/?r=421#perf%2Fcom%2Flmax%2Fdisruptor


### Disruptor库中的RingBuffer用法与实现 #### 初始化RingBuffer 在Servlet实例化时初始化RingBuffer是一种常见做法,这可以确保在整个应用生命周期内只创建一次RingBuffer对象[^1]。 #### RingBuffer的工作机制 RingBuffer内部维护着一系列槽(slot),这些槽用于存储事件数据。为了追踪当前处理位置,“指针”被用来表示下一个可用的位置。“指针”的类型为Java `long`型(64位有符号整数), 并通过不断递增来指向新的位置[^2]。 #### 创建和配置RingBuffer 下面是一个简单的例子展示如何设置并启动一个基于Disruptor框架的RingBuffer: ```java import com.lmax.disruptor.RingBuffer; import com.lmax.disruptor.dsl.Disruptor; // 定义事件工厂 public class LongEventFactory implements EventFactory<LongEvent> { @Override public LongEvent newInstance() { return new LongEvent(); } } // 主程序入口 public static void main(String[] args) throws InterruptedException { // 设置缓冲区大小(必须是2的幂) int bufferSize = 1024; // 构建Disruptor实例 Disruptor<LongEvent> disruptor = new Disruptor<>(new LongEventFactory(), bufferSize, Executors.defaultThreadFactory()); // 启动Disruptor disruptor.start(); // 获取RingBuffer引用 RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); } ``` 这段代码展示了如何定义事件工厂以及怎样构建和启动Disruptor实例。这里需要注意的是,环形缓冲区(`RingBuffer`) 的容量应当设定成2的次方数以优化性能。 #### 发布事件到RingBuffer 当向RingBuffer发布新事件时,通常会经历以下几个过程: - 请求下一个序号(next sequence number) - 填充对应slot的数据 - 提交该事件(publish) 以下是具体的实现方式: ```java try { long sequence = ringBuffer.next(); // 预留一个slot try { LongEvent event = ringBuffer.get(sequence); event.setValue(valueToPublish); // 将实际值赋给event } finally { ringBuffer.publish(sequence); // 发布事件 } } catch (Exception e){ System.err.println("Error publishing event"); } ``` 此段代码说明了如何安全地获取序列号、填充事件内容并将之提交至RingBuffer中。特别注意,在操作完成后调用了publish方法以便通知消费者线程存在待处理的新消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值