有时候在想我可以做些什么,一件有价值的事,一件让自己开心,也能让别人夸赞的事,也许是个系统,也许是个业务,也许小而美,也许平凡中伟大,真是一个好问题啊~ 也许首先要做的是写一篇博客,记录一下生活,依然-五一快乐
LMAX开发的高性能队列,传说可以达到单机每秒600万交易~YYDS是吗
Disruptor 主要解决了 JDK 内置线程安全队列的性能和内存安全问题;其在无锁的情况下还能保证队列有界、线程安全
是基于事件异步驱动模型实现的
- 采用RingBuffer数据结构
- 支持高并发,低延时,高吞吐量的高性能工作队列;
- Disruptor是单机的本地内存队列,类似ArrayBlockingQueue
特点
- 高性能
- 低延迟
- 无锁设计
- 多生产者/消费者模型
- 单机-纯内存
- 可配置性强:提供多种事件处理策略;可通过配置不同的事件处理器来实现不同的处理逻辑
- 时间重用
- 事件分发机制:单播、广播
- 生命周期管理
- 异步处理
为什么比ArrayBlockingQueue快?
- 无锁设计:CAS
- 批量处理:一次获取多个事件处理
- 内存预分配:消除GC停顿
- 缓存优化:消除伪共享
使用场景
- 可用于撮合引擎、支付系统交易匹配
- 股票行情处理(每秒百万级报价)
- 游戏服务器战斗结算
- log4j2基于Disruptor实现异步日志处理
- SOFATracer:蚂蚁金服开源的分布式应用链路追踪工具使用Disruptor
- Storm:开源的分布式实时计算系统,基于Disruptor实现工作进程内发生的消息传递
- HBase:分布式列存储数据库系统,基于Disruptor提高写并发性能
- Canal+Dis实现高效数据同步
Disruptor核心

可以看到有几个概念,我们一一介绍下
发送者,没啥好说的

它是环形数组结构,首尾相连,用作不同上下文间传递数据的buffer;
数组结构;结合SequenceBarrier机制,实现线程与线程之间高效的数据交互,数组元素不会被回收,避免频繁GC,同时数组对处理器的缓存机制更友好
无锁设计,CAS保证线程安全
RingBuffer拥有一个序号,这个序号指向数组中下一个可用元素,不论存取都是用CAS操作
特点:它只有一个指针,创建时大小就被固定了,初始化时维护一个object[] entries数组元素
生产者向RingBuffer写入消息时RingBuffer不是直接向数组元素entries指向event对象,而是先获取event对象,更改event对象中的detail属性
消费者也是从RingBuffer读取event,读取对象中的detail属性
由此可见,在生产和消费过程中 ,RingBuffer中的数组元素entries没有发生任何变化,没有产生临时对象,数组中的元素一直存活,直到RingBuffer消亡,降低GC,提高性能
优势
-
简化多线程同步的复杂度,像摩天轮转圈一样的数据容器,座位数量固定,但乘客不断上下,循环往复,两个指针(头指针、尾指针)像追逐游戏般移动;当指针达到数组末尾时,自动回到起点;指针的魔法移动:不用if判断,改用取模运算实现循环 next_pos = (current_pos + 1) % buffer_size
-
环形缓冲区=环形队列,固定尺寸,无需重复申请内存,首尾相连,可以做到覆盖旧数据-对象复用,减少GC压力,适合缓存数据流
-
预分配连续内存
-
消除了伪共享,如图,用的填充的方式

注意
- 在缓冲区满的时候写数据,有两种策略可以使用:第一覆盖掉老数据;第二抛出异常
- 读数据时,一定要读出缓冲区中最老的数据(如果被覆盖了,那最老的一定是下一位)
- 环中有开始位置、结束位置,读索引=最早放入的数据;写索引=下一个要写入的位置
- 环形缓冲区大小必须是2的幂
- 避免在EventHandler中阻塞操作(会拖慢整个处理链)
- 监控序列差值 getCursor()
-
sequence:
序号管理器,顺序增长,每个Consumer都维护一个Sequence,通过它标识和定位RingBuffer中的每一个事件,可以跟踪Consumer事件处理进度,它有AtomicLong的大多数功能特性,而且它消除了CPU伪共享的问题(通过填充的方式)
里面是个long value,简单理解是高并发下优化的long类型

Disruptor的核心,生产者与缓存RingBuffer之间的桥梁,
- 有当前写的进度Sequence cursor
- 有所有消费者进度的数组
Sequence[] gatingSequences
这几个变量在AbstractSequencer抽象类中,都是重要参数
protected final int bufferSize;
protected final WaitStrategy waitStrategy;
protected final Sequence cursor = new Sequence(Sequencer.INITIAL_CURSOR_VALUE);
protected volatile Sequence[] gatingSequences = new Sequence[0];
接口;它有两个实现类:SingleProducerSequencer(单生产者实现)、MultiProducerSequencer(多生产者实现),它主要作用是实现生产者和消费者之间快速、正确传递数据的并发算法
生产者发布event的时候首先需要预定一个 sequence,Sequencer 就是计算和发布 sequence 的,下面分别介绍
SingleProducerSequencer
单生产者用到,发布过程
- 通过 Sequencer.next(n) 来预定下面 n 个可以写入的位置序号,后面我们可以解析下源码
- 根据序号获取事件,然后修改事件数据,然后发布 event
MultiProducerSequencer
多生产者场景使用,后面可以看下源码
协调屏障,用来跟踪发布者的游标和事件处理者的序列号,保证事件的有序性
是消费者与RingBuffer之间的桥梁,消费者直接访问的是SequenceBarrier不是RingBuffer,因此SequenceBarrier能减少RingBuffer的并发冲突
处理Event的循环,在循环中获取Disruptor的事件,然后把事件分配给各个handler,消费者就是通过WorkProcessor这个类workHandler.onEvent(event)将事件分配出去的,EventHandler处理器获取并消费
处理器,就是消费者,负责具体的业务逻辑实现
| 策略名称 | 原理 | 生产者类型 | 延迟级别 | CPU使用率 | 适用场景 |
|---|---|---|---|---|---|
| BlockingWaitStrategy | 锁阻塞 | 单/多 | 高 | 低 | 稳定性优先的后台任务 |
| SleepingWaitStrategy | 自旋 + sleep() | 单/多 | 中 | 低 | 异步日志、非实时监控 |
| YieldingWaitStrategy | 自旋 + yield() | 单/多 | 低 | 低 | 高性能交易系统(低延迟) |
| BusySpinWaitStrategy | 完全自旋 | 单/多 | 最低 | 100% | 极端低延迟场景(高频交易) |
| PassiveWaitStrategy | 被动等待 | 单/多 | 中 | 低 | 批量处理任务、宽松的延时要求 |
| TimeoutBlockingWaitStrategy | 阻塞 + 超时 | 单/多 | 中 | 低 | 需要超时控制的场景 |
注:选择策略时需权衡延迟、CPU占用及部署复杂度。例如:
-
金融撮合系统可能优先选择 Yielding 或 BusySpin 策略以满足低延迟;
-
日志处理系统则适合 Sleeping 策略以平衡资源消耗与性能。
框架结构如下(官方原图)
可以看到都是围绕着RingBuffer来行动的,生产者根据等待策略和配置发送到RingBuffer,消费者通过ProducerBarrier和ConsumerBarrier处理RingBuffer

官方例子
举一个官方使用的小demo
定义一个事件
public class LongEvent
{
private long value;
public void set(long value)
{
this.value = value;
}
@Override
public String toString()
{
return "LongEvent{" + "value=" + value + '}';
}
}
定义一个委托事件工厂
import com.lmax.disruptor.EventFactory;
public class LongEventFactory implements EventFactory<LongEvent>
{
@Override
public LongEvent newInstance()
{
return new LongEvent();
}
}
定义一个消费者
public class LongEventHandler implements EventHandler<LongEvent>
{
@Override
public void onEvent(LongEvent event, long sequence, boolean endOfBatch)
{
System.out.println("Event: " + event);
}
}
好了,初始化并开始调用使用
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.examples.longevent.LongEvent;
import com.lmax.disruptor.examples.longevent.LongEventFactory;
import com.lmax.disruptor.examples.longevent.LongEventHandler;
import com.lmax.disruptor.util.DaemonThreadFactory;
import java.nio.ByteBuffer;
public class LongEventMain
{
public static void main(String[] args) throws Exception
{
LongEventFactory factory = new LongEventFactory();
int bufferSize = 1024;
Disruptor<LongEvent> disruptor =
new Disruptor<>(factory, bufferSize, DaemonThreadFactory.INSTANCE);
disruptor.handleEventsWith(new LongEventHandler());
disruptor.start();
RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
LongEventProducer producer = new LongEventProducer(ringBuffer);
ByteBuffer bb = ByteBuffer.allocate(8);
for (long l = 0; true; l++)
{
bb.putLong(0, l);
producer.onData(bb);
Thread.sleep(1000);
}
}
}
这个是上面用到的生产者的事件封装
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.examples.longevent.LongEvent;
import java.nio.ByteBuffer;
public class LongEventProducer
{
private final RingBuffer<LongEvent> ringBuffer;
public LongEventProducer(RingBuffer<LongEvent> ringBuffer)
{
this.ringBuffer = ringBuffer;
}
public void onData(ByteBuffer bb)
{
long sequence = ringBuffer.next(); // <1>
try
{
LongEvent event = ringBuffer.get(sequence); // <2>
event.set(bb.getLong(0)); // <3>
}
finally
{
ringBuffer.publish(sequence);
}
}
}
这个只是简单的例子,具体还有其他更好用的API,有时间可以慢慢看
多消费者模式
这个戏就多了,跟工作流似的,可以支持多种消费模式
多消费者:并行的、广播模式
//注册多个消费者
disruptor.handleEventsWith(new LongEventHandler(),
new LongEventHandler1(),
new LongEventHandler2());
多消费者:并行的、消费者组模式
同组内消费者之间互斥,一个事件只会被同组内单个消费者处理,但可以支持多个消费者组,消费者组之间完全隔离,互不影响,代码实现方式有两点不同之处:
- 消费者需要实现WorkHandler接口,而不是 EventHandler 接口;
- 使用handleEventsWithWorkerPool设置Disruptor的消费者,而不是handleEventsWith方法



多个消费者组之间航道执行模式
//注册消费者
disruptor.handleEventsWithWorkerPool(new LongWorkHandler(), new LongWorkHandler(), new LongWorkHandler())
.thenHandleEventsWithWorkerPool(new OtherWorkHandler(), new OtherWorkHandler(), new OtherWorkHandler());

多消费者:链式、菱形、六边形执行模式

// 链式处理
disruptor.handleEventsWith(new LongEventHandler11())
.then(new LongEventHandler12());
disruptor.handleEventsWith(new LongEventHandler21())
.then(new LongEventHandler22());
// 菱形处理
disruptor.handleEventsWith(new LongEventHandler1(), new LongEventHandler2())
.then(new LongEventHandler3());
// 六边形处理
LongEventHandler handler11 = new LongEventHandler();
LongEventHandler handler12 = new LongEventHandler();
LongEventHandler handler21 = new LongEventHandler();
LongEventHandler handler22 = new LongEventHandler();
LongEventHandler handler3 = new LongEventHandler();
disruptor.handleEventsWith(handler11, handler21);
disruptor.after(handler11).handleEventsWith(handler12);
disruptor.after(handler21).handleEventsWith(handler22);
disruptor.after(handler12, handler22).handleEventsWith(handler3);
源码解读
生产过程
这是发布时调用的next获取下一个序列号的源码
public <A> void publishEvent(EventTranslatorOneArg<E, A> translator, A arg0)
{
final long sequence = sequencer.next();
translateAndPublish(translator, sequence, arg0);
}
public long next(int n) {
// 检查申请的数量必须大于0
if (n < 1) {
throw new IllegalArgumentException("n must be > 0");
}
// 当前生产者已申请到的最后一个序号
long nextValue = this.nextValue;
// 将要申请的最后一个序号(期望申请 n 个)
long nextSequence = nextValue + n;
// wrapPoint 是“数据回绕点”,用于判断是否会覆盖未消费数据
// 比如 RingBuffer size=16,当前nextSequence=20,则 wrapPoint=4
long wrapPoint = nextSequence - bufferSize;
// 上次缓存的 gatingSequence(消费者中消费最慢的那个位置)
long cachedGatingSequence = this.cachedValue;
// 触发两个场景下的判断:
// 1. wrapPoint > cachedGatingSequence → 说明可能覆盖未消费数据,需要重新检查
// 2. cachedGatingSequence > nextValue → 极端情况(比如消费者快于生产者)
if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue) {
// 设置 cursor 的 volatile 值,内存屏障,确保生产者修改对消费者可见
cursor.setVolatile(nextValue); // StoreLoad 屏障
long minSequence;
// 自旋等待,直到 wrapPoint <= 最慢消费者的位置,确保不会覆盖数据
while (wrapPoint > (minSequence = Util.getMinimumSequence(gatingSequences, nextValue))) {
// parkNanos 是轻量级自旋,避免 CPU 忙等(等待1纳秒,频繁检查)
LockSupport.parkNanos(1L); // 实际生产中可替换为更优的 waitStrategy
}
// 更新缓存,避免每次都计算 gatingSequences
this.cachedValue = minSequence;
}
// 更新 nextValue,表示当前生产者已经申请到了 nextSequence
this.nextValue = nextSequence;
// 返回新分配的最大序号(注意:返回的是末尾序号,通常你自己还要处理 head-tail 区间)
return nextSequence;
}
获取到下一个序列号会调用translateAndPublish,在finally中publish
private <A> void translateAndPublish(EventTranslatorOneArg<E, A> translator, long sequence, A arg0)
{
try
{
translator.translateTo(get(sequence), sequence, arg0);
}
finally
{
sequencer.publish(sequence);
}
}

这时候就涉及到我们配置的事single还是multi了,好我们看下single
public void publish(long sequence)
{
cursor.set(sequence);
waitStrategy.signalAllWhenBlocking();
}
可以看到调用WaitStrategy等待策略了

我们主要看下BlockingWaitStrategy,可以看到它是通过ReentrantLock锁住保证线程安全的,通过Condition等待-释放策略通知消费端可以消费了
public final class BlockingWaitStrategy implements WaitStrategy
{
private final Lock lock = new ReentrantLock();
private final Condition processorNotifyCondition = lock.newCondition();
public void signalAllWhenBlocking()
{
lock.lock();
try
{
processorNotifyCondition.signalAll();
}
finally
{
lock.unlock();
}
}
}
消费流程
WorkProcessor负责从 RingBuffer 中消费事件,并通过 WorkHandler 进行处理
WorkProcessor.run() 是一个持续运行的消费循环:
- 每个
WorkProcessor是一个独立的工作线程(通常是实现了Runnable的类)。 - 多个
WorkProcessor共同竞争workSequence(共享的工作序号)来获取任务的处理权,避免重复消费。 - 每个线程一旦抢到任务,就从
RingBuffer中获取事件,执行WorkHandler.onEvent()进行业务处理
public void run() {
boolean processedSequence = true; // 标识上一个事件是否已处理完
long cachedAvailableSequence = Long.MIN_VALUE; // 缓存可用的最大事件序号
long nextSequence = sequence.get(); // 当前处理器要处理的下一个序号
T event = null;
while (true) {
try {
// 如果上一个事件已经处理完成,尝试获取下一个事件处理权
if (processedSequence) {
processedSequence = false;
// 通过 CAS(Compare-And-Set)竞争下一个可处理的序号
// 保证每个 WorkProcessor 处理唯一的事件,防止重复消费
do {
nextSequence = workSequence.get() + 1L;
sequence.set(nextSequence - 1L); // 设置本线程的序号(还没正式消费)
} while (!workSequence.compareAndSet(nextSequence - 1L, nextSequence));
}
// 判断事件是否已发布(数据是否准备好)
if (cachedAvailableSequence >= nextSequence) {
// 从 RingBuffer 中获取事件
event = ringBuffer.get(nextSequence);
// 调用业务逻辑处理器处理事件
workHandler.onEvent(event);
// 标记事件处理完成
processedSequence = true;
} else {
// 当前事件尚未发布,阻塞等待发布
cachedAvailableSequence = sequenceBarrier.waitFor(nextSequence);
}
}
// catch 块略去,可以处理 AlertException、InterruptedException 等
}
// 线程退出前清理操作
notifyShutdown();
// 设置运行标志为 false,表明该 WorkProcessor 停止运行
running.set(false);
}
waitFor() 方法解释(来自 SequenceBarrier):
public long waitFor(final long sequence)
throws AlertException, InterruptedException, TimeoutException {
checkAlert(); // 检查是否中断或关闭
// 调用 WaitStrategy(如 BlockingWaitStrategy、BusySpinWaitStrategy 等)等待目标序号可用
long availableSequence = waitStrategy.waitFor(sequence, cursorSequence, dependentSequence, this);
if (availableSequence < sequence) {
return availableSequence; // 数据未准备好,提前返回
}
// 过滤掉尚未真正“发布”的数据(Disruptor 会预分配槽位,但未必写完数据)
return sequencer.getHighestPublishedSequence(sequence, availableSequence);
}
public long getHighestPublishedSequence(long lowerBound, long availableSequence) {
for (long sequence = lowerBound; sequence <= availableSequence; sequence++) {
if (!isAvailable(sequence)) {
return sequence - 1; // 找到第一个未发布的事件,返回上一个可用序
}
}
return availableSequence; // 全部发布了,返回最大值
}
在消费时我们实现了implements EventHandler,然后onEvent方法中消费,但是看源码是调用的WorkHandler的onEvent消费,那么问题来了,他俩啥区别
EventHandler 和 WorkHandler 的区别是啥?
先汇总下,然后再解释
| 消费接口 | 模式 | 使用类 | 方法签名 | 是否共享消费事件 |
|---|---|---|---|---|
| EventHandler | 发布-订阅 (EventProcessor) | BatchEventProcessor | onEvent(event, sequence, endOfBatch) | 不, 所有消费者都收到事件(广播) |
WorkHandler<T> | 工作队列 (WorkHandler) | WorkerPool / WorkProcessor | onEvent(event) | 是的, 多消费者分担处理(每个事件只被一个消费线程处理) |
下面可以看到EventProcessor有3个实现类,其中就有这两个使用类

BatchEventProcessor发布-订阅模式
看下BatchEventProcessor处理上是差不多的
public final class BatchEventProcessor<T>
implements EventProcessor
private final EventHandler<? super T> eventHandler;
@Override
public void run()
{
if (running.compareAndSet(IDLE, RUNNING))
{
sequenceBarrier.clearAlert();
notifyStart();
try
{
if (running.get() == RUNNING)
{
processEvents();
}
}
finally
{
notifyShutdown();
running.set(IDLE);
}
}
}
private void processEvents()
{
T event = null;
long nextSequence = sequence.get() + 1L;
while (true)
{
try
{
final long availableSequence = sequenceBarrier.waitFor(nextSequence);
if (batchStartAware != null)
{
batchStartAware.onBatchStart(availableSequence - nextSequence + 1);
}
while (nextSequence <= availableSequence)
{
event = dataProvider.get(nextSequence);
eventHandler.onEvent(event, nextSequence, nextSequence == availableSequence);
nextSequence++;
}
sequence.set(availableSequence);
}
}
}
可以看到最终也是调用了eventHandler.onEvent这个的
典型用途:你想对事件做不同的处理,如日志、分析、持久化,可以同时配置多个 EventHandler
WorkHandler<T> —— 工作队列模式
多个消费者 竞争性消费事件(一个事件只被处理一次),适合“负载均衡”处理任务
典型用途:多个线程并发处理任务,像线程池
其他问题
如何消除伪共享?
先介绍下什么是伪共享,什么问题,如何消除吧,后面在linux的介绍上再写一遍
来张图看下内存、L1,L2,L3缓存和CPU的位置关系

什么是伪共享问题?
伪共享是 多核CPU架构 中特有的性能问题,当多个线程频繁修改 同一缓存行(Cache Line)中的不同变量 时,会导致 缓存失效风暴,引发严重的性能下降,比如
class Data {
volatile long x; // 线程A频繁修改
volatile long y; // 线程B频繁修改
}
x和y位于同一缓存行(假设起始地址对齐)
假设:有两个线程同时访问并修改X和Y这两个变量,X和Y恰好在同一个缓存行上,这两个线程分别在不同的CPU上执行。
线程A修改x,线程B修改y,由于x被更新了,所以缓存行失效,或者y被更新了,缓存行也失效,会重新去内存中读取数据到L3,本来两个相互不影响,现在会相互影响
程序执行效率明显下降
如何消除?
那自然是好几种,都有填充法(经典)、字段重排序、@Contended注解、线程局部变量这几种
Disruptor用的是经典的填充法空间换时间
原理:通过填充无用字段,让x和y分布在不同的缓存行
class Data {
volatile long x;
// 填充7个long(56字节)+ 对象头8字节 = 64字节
private long p1, p2, p3, p4, p5, p6, p7;
volatile long y;
}
来看RingBuffer如何做的,可以看到RingBuffer变量INITIAL_CURSOR_VALUE的前后都填充了7个long,一个long8个字节,前后加一起就是56+56=112个字节,一行缓存行时64,完全够用了
前面介绍的Sequence也是一样,就是为了让它自己占用一个内存行,不和其他冲突,减少缓存失效的情况,提高性能
abstract class RingBufferPad{
protected long p1, p2, p3, p4, p5, p6, p7;
}
abstract class RingBufferFields<E> extends RingBufferPad{}
public final class RingBuffer<E> extends RingBufferFields<E> implements Cursored, EventSequencer<E>, EventSink<E>{
public static final long INITIAL_CURSOR_VALUE = Sequence.INITIAL_VALUE;
protected long p1, p2, p3, p4, p5, p6, p7;
}
如何管理消费者和生产者之间的依赖关系
通过SequenceBarrier进行依赖管理,
消费者的processer,通过 SequenceBarrier获取生产者的生产序号
数据覆盖问题如何解决?
gatingSequences:记录每个消费者当前消费到的序号
举例
有环形队列-数组结构如下,有16个位置
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
index: [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]
sequence是累加的数字,生产者准备写的序号是20,那么下一个位置就是20-16=4,超过一圈的第4个位置
但是如果消费者最慢只读到了3,说明4号位置还没有被消费,不能写!
需等待消费者前进:LockSupport.parkNanos(1L); // 轻量级自旋等待
总结:Disruptor用 gatingSequences 追踪最慢的消费者位置,如果最慢位置<要写的位置,则自旋等待,防止覆盖写入
背压问题如何解决?
背压问题就是数据不能覆盖,而消费者速度赶不上生产者就会产生积压,自旋,等待,直到有消费者把老数据消费掉
Disruptor是故意卡住的,因为不能覆盖,那如何解决?
- 多加消费者线程(推荐)
- 优化消费逻辑,不要阻塞,不要琐(推荐)
- 加大RingBuffer(必须是2的幂)
- 限速生产者
- 异步持久化,分发任务,比如发到MQ中去消费
自旋的问题
LockSupport.parkNanos(1L); 短暂暂停线程,更轻量
风险
- 如果积压严重,自旋时间长会浪费CPU时间片
- 自旋线程太多可能导致CPU资源被抢占,拖垮系统
如何合理设置RingBuffer容量?
RingBuffer容量越大:能承受的积压越多,占内存也越多;能应对消费抖动
Disruptor 各种模式推荐配置总览表
| 模式类型 | 推荐消费者数 | 推荐 bufferSize(2的幂) | 单机 TPS 参考值 | 推荐应用场景 |
|---|---|---|---|---|
| 单生产者 + 单消费者 | 1 | 1024~8192 | 10W+ TPS | 简洁快速任务、事件驱动、日志过滤、游戏帧更新 |
| 单生产者 + 多消费者(WorkPool) | 4~8 | 8192~65536 | 20W~50W TPS | 高并发数据处理、日志异步处理、风控处理 |
| 单生产者 + 多消费者(广播/订阅) | 2~4 | 65536~131072 | 3W~8W TPS(取决于最慢消费) | 数据同步、多系统广播、审计追踪、多模块分发 |
| 多生产者 + 单消费者 | 1 | ≥16384(注意 padding) | 10W~20W TPS | 多线程写入场景,日志合并、数据聚合 |
| 多生产者 + 多消费者(WorkPool) | 4~16 | 65536~131072 | 50W+ TPS(需调优) | 极限吞吐场景,撮合引擎、实时日志平台、交易系统 |
| 应用 | 采用模式 | 配置建议 |
|---|---|---|
| 游戏逻辑帧分发 | 单生产 + 单消费 | bufferSize: 2048,TPS: 1W+,极低延迟 |
| 日志异步写盘 | 单生产 + WorkPool | 消费者数: 4,bufferSize: 16384,TPS: 5W |
| 实时订单风控检测 | 单生产 + 多 WorkHandler | 消费者数: 8,bufferSize: 65536,TPS: 10W |
| 审计日志广播(分模块处理) | 单生产 + 广播 | 消费者数: 3,bufferSize: 131072,TPS: 5W |
| 交易撮合系统 | 多生产 + 多 WorkPool | 消费者数: 16,bufferSize: 131072,TPS: 50W+,需多核调优 |
当然了,上面这些配置只是参考,我也是从其他地方找来的,大家如果线上要用一定一定一定要经过严格的压测才能得出结论哈
参考:https://mp.weixin.qq.com/s?__biz=MzIyNDU2ODA4OQ==&mid=2247501790&idx=1&sn=e86cea20c7eb8075227aea9be87f97dc&chksm=e80e71a8df79f8be3fe59a81be769a9f669e607e47ec33b786fe7e249fbb32a55b2a5075f185#rd
https://mp.weixin.qq.com/s/1Bxsw3tszrbLqfzPg0wqxQ
生命自有出路
578

被折叠的 条评论
为什么被折叠?



