不公平分发和预取值

文章讨论了消息队列系统中可能出现的不公平分发现象,即消息在消费者间的不均衡分布,以及其原因,如轮询策略、消费者处理能力差异和消息处理时长不均。预取值作为优化手段,允许消费者一次性获取多个消息以提高效率,但需要适当设置以避免消费者过载或消息积压。示例代码展示了如何通过设置预取值为1来避免不公平分发,确保消费者处理完当前消息后再接收新消息。
摘要由CSDN通过智能技术生成

什么是不公平分发

不公平分发(Unfair Distribution)是指在消息队列系统中,当多个消费者同时订阅同一个队列时,消息的分发可能不均衡的情况。这意味着某些消费者可能会接收到更多的消息,而其他消费者则接收较少的消息,导致消息在消费者之间的负载不平衡。

不公平分发可能发生的原因包括:

  1. 轮询分发策略:消息队列系统采用了默认的轮询分发策略,按照消费者的订阅顺序依次将消息发送给消费者。这种方式可能导致在消费者处理速度不同的情况下,某些消费者接收到更多的消息。

  2. 消费者处理能力差异:不同的消费者可能具有不同的处理能力,有些消费者可能处理速度较慢,而其他消费者则更快。如果消息队列系统无法根据消费者的处理能力进行动态调整,就可能导致消息的不公平分发。

  3. 消息处理时长不均:消息的处理时长可能因为消息内容的复杂性或需要执行的操作而不同。如果某些消息的处理时间较长,就会导致接收到这些消息的消费者在相同时间段内处理较少的消息。

不公平分发可能会导致一些消费者处理的消息堆积,而其他消费者则相对空闲。这可能会对系统的整体性能产生负面影响,因为资源没有得到充分利用,同时也可能导致系统的响应时间延长。

什么是预取值

预取值(Prefetch)是指在消息队列系统中,消费者从队列中获取消息时,一次性获取多个消息的能力。当消费者连接到队列并准备开始消费消息时,预取值定义了消费者可以从队列中获取的消息数量。

通常,预取值的设置是为了在一次性处理多个消息时提高效率,并减少消费者与消息队列的通信开销。当消费者处理一条消息时,它可以在本地缓存中保持一定数量的未处理消息,以减少对队列的频繁请求。

预取值的设置是根据消费者的处理能力和系统的负载情况来决定的。如果预取值设置得太高,可能会导致消费者过载或过多的消息积压在本地缓存中,影响系统性能。如果预取值设置得太低,可能会导致消费者的处理速度受到限制,无法充分利用可用资源。

通过适当地设置预取值,可以在消费者和消息队列之间实现一种平衡,以提高系统的吞吐量和响应性能。根据具体的消息队列系统和应用场景,预取值的配置方式可能会有所不同。例如,在RabbitMQ中,可以使用channel.basicQos方法设置预取值。

需要注意的是,预取值并不是消费者一次性获取所有消息的意思,而是指消费者在一次获取消息时可以获取的最大数量。消费者仍然需要逐条处理消息,但通过预取值的设置,可以减少与消息队列的通信次数,提高效率。

案列解释:

以下代码中的采用不公平分发channel.basicQos(1);

其实还是设置预取值为1,含义是在消费者与RabbitMQ之间建立的信道(channel)上设置预取值为1,表示每次只预取一个消息给消费者。这样做的目的是在消费者处理完当前消息之前不再向其发送更多的消息,以避免消息堆积和负载过重。

从而实现避免轮询策略下更快的线程大量空闲等待的情况

public class Worker4 {
    public static final String TASK_QUEUE_NAME = "ack_queue";

    public static void main(String[] args) throws Exception{
        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("C2接收消息处理时间较长");
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            SleepUtils.sleep(30);
            System.out.println( "c2接收到消息:" + new String(message.getBody()));
            //手动,消息的标记tag,是否批量
            channel.basicAck(message.getEnvelope().getDeliveryTag(),false);
        };
        //采用不公平分发
        channel.basicQos(1);
        //采用手动应答
        boolean autoAck = false;
        channel.basicConsume(TASK_QUEUE_NAME,autoAck,deliverCallback,consumerTag ->{
            System.out.println("消费者取消消费");
        });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值