当前位置: 首页 > 知识库问答 >
问题:

在类似LMAX干扰器的模式中,您如何处理较慢的消费者?

艾望
2023-03-14

对于在x86 Linux上运行的具有多个生产者和单个消费者的lmax中断器(如环形缓冲区)中的慢速消费者,我有一个问题。使用类似于lmax的环形缓冲区模式,您会不断覆盖数据,但如果消费者速度较慢,该怎么办。因此,如果在10个大小的环形缓冲区0-9个环形插槽中,您的消费者位于插槽5上,而您的写入程序现在准备好开始写入插槽15,也就是缓冲区中的插槽5(即:插槽5=15%10),您如何处理这种情况?处理这种情况的典型方式是什么,写入程序仍然按照数据输入的顺序生成数据,而客户端将按照相同的顺序接收数据?这确实是我的问题。下面是关于我的设计的一些细节,它工作得很好,只是我目前没有一个很好的方法来处理这个问题。有多个线程执行写操作,一个线程执行读操作。如果不更改当前项目范围之外的现有设计,我无法引入多个读线程,但如果他们将此作为解决方案,我仍然对您的想法感兴趣。

设计细节

我有一个环形缓冲区,该设计目前有多个生产者线程和一个消费者线程。此部分设计已存在,当前无法更改。我正在尝试使用无锁环形缓冲区删除现有的排队系统。我的情况如下。

该代码在x86 Linux上运行,写入程序有多个线程,读取器有一个线程。读写器从一个插槽开始,并且是原子的

 inline data_type incrementSequence() {                                                                                       
        return m_sequence.fetch_add(1,std::memory_order::memory_order_seq_cst);                                                  
    }   


void updateSequence(data_type aOld, data_type aNew) {                                                                        
        while ( !m_sequence.compare_exchange_weak(aOld, aNew, std::memory_order::memory_order_release, std::memory_order_relaxed)
            if  (sequence() < aNew)  {                                                                                           
                continue;                                                                                                        
            }                                                                                                                    
            break;                                                                                                               
        }                                                                                                                        
    }                   
 inline data_type sequence() const {                                                                                          
        return m_sequence.load(std::memory_order::memory_order_acquire);                                                         
    }       
      

共有1个答案

越文康
2023-03-14

环形缓冲区(或通常的FIFO——不必实现为环形缓冲区)旨在平滑突发流量。尽管生产者可能会突然产生数据,但消费者可以处理稳定的输入流。

如果FIFO溢出,这意味着两件事之一:

  1. 你的爆发比你计划的要大。通过增加FIFO大小(或使其大小动态)来解决此问题
  2. 你的生产者比你的消费者跑得快。通过增加用于消耗数据的资源(可能更多的线程)来解决这个问题

在我听来,你现在似乎正处于第二个阶段:你的单一消费者的速度根本赶不上生产商。在这种情况下,唯一真正的选择是通过优化单个消费者或增加更多消费者来加速消费。

这听起来也有点像您的消费者在处理数据时可能会将他们的输入数据留在FIFO中,因此FIFO中的该位置一直被占用,直到消费者完成处理该输入。如果是这样,您可以通过简单地让消费者在FIFO开始处理时立即从FIFO中删除输入数据来解决问题。这会释放该插槽,以便生产者可以继续将输入放入缓冲区。

还有一点:使FIFO大小动态可能是一个问题。问题相当简单:它可以掩盖这样一个事实,即您确实存在第二个问题,即没有必要的资源来处理消费者端的数据。

假设生产者和消费者都是线程池,平衡系统的最简单方法通常是使用固定大小的FIFO。如果生产者开始远远领先于消费者,导致FIFO溢出,那么生产者就会开始阻止。这让使用者线程池消耗更多的计算资源(例如,在更多的内核上运行),以赶上生产者。然而,这确实取决于是否能够添加更多消费者,而不是将系统限制为单个消费者。

 类似资料:
  • 如何监控LMAX Disruptor?假设我有3个环缓冲区,并希望提供一个用户界面来提供环缓冲区的信息。

  • 我试着通过按不同的键来激活不同的视觉效果。例如,当我按下“Z”或“Z”时,特定位置上的一个椭圆向下流动,留下一个痕迹。如果我等待它到达画布边界,没有问题,但当我按“0”激活另一个位置上的另一个椭圆来做同样的事情时,“z”/“z”的椭圆停止流动。当我在椭圆到达画布边框之前按下相同的键时也会发生这种情况。我该怎么解决这个?当我开始编写这个代码的时候,我不知道类和对象,然后我学会了并试图通过创建一个对象

  • 概述 无干扰模式将只在显示器中以全屏模式显示你的文件,可以在菜单栏中的View - 切换无干扰模式进入无干扰模式,快捷键也可以。 定制化 无干扰模式将使某些设置生效,默认设置(位于Packages/Default/Distraction Free.sublime-settings)是: { "line_numbers": false, "gutter": false, "draw_ce

  • 我试图在处理程序之间创建一种循环依赖关系,但我不太清楚如何正确处理。我想要实现的是制作人的变体- 所以,破坏者。handleEventsWith(h1、h2、h3)。然后(h4) 。但我还有其他要求 虽然处理程序1-3并行处理消息,但在它们都完成前一条消息之前,它们都不会开始处理下一条消息。 在第一条消息之后,处理程序1-3等待处理程序4完成最近的消息,然后再处理下一条消息。 使用单个事件处理程序

  • 在使用disruptor时,可能会有一个(多个)消费者落后,并且由于这个缓慢的消费者,整个应用程序都会受到影响。 请记住,每个生产者(发布者)和消费者(EventProcessor)都在一个线程上运行,如何解决消费者速度慢的问题? 我们可以在单个消费者上使用多个线程吗?如果没有,有什么更好的选择?

  • 我想使用Lmax Disruptor进行性能测试: 配置DURUPTOR 以某种方式“暂停”处理 向RingBuffer添加多条消息 “取消暂停”处理 这样,我可以清楚地测量缓冲区清空的速度。如果我“混合”添加了许多消息(这会带来一些延迟)并进行处理,那么在处理速度方面可能会有不太确定的结果。 然而,我似乎没有在LMAX Disruptor(https://lmax-exchange.github