持久化和公平分发.py
1、消息持久化
在实际应用中,可能会发生消费者收到Queue中的消息,但没有处理完成就宕机(或出现其他意外)的情况,
这种情况下就可能会导致消息丢失。为了避免这种情况发生,我们可以要求消费者在消费完消息后发送一个回执给RabbitMQ,
RabbitMQ收到消息回执(Message acknowledgment)后才将该消息从Queue中移除;如果RabbitMQ没有收到回执并检测到消费者的RabbitMQ连接断开,
则RabbitMQ会将该消息发送给其他消费者(如果存在多个消费者)进行处理。这里不存在timeout概念,一个消费者处理消息时间再长也不会导致该消息被发送给其他消费者,除非它的RabbitMQ连接断开。 这里会产生另外一个问题,如果我们的开发人员在处理完业务逻辑后,忘记发送回执给RabbitMQ,这将会导致严重的bug——Queue中堆积的消息会越来越多;消费者重启后会重复消费这些消息并重复执行业务逻辑…千面是因为我们在消费者端标记了ACK=True关闭了它们,如果你没有增加ACK=True或者没有回执就会出现这个问题
生产者需要在发送消息的时候标注属性为持久化
# 在队列中添加消息
for i in range(100):
message = '%s Meassage '% i or "Hello World!"
# 发送消息
channel.basic_publish(exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(delivery_mode=2, )) # 标记属性消息为持久化消息需要客户端应答
# 发送消息结束,并关闭通道
print(" [x] Sent %r" % message)
消费者需要发送消息回执
# 订阅回调函数,这个订阅回调函数是由pika库来调用
def callback(ch, method, properties, body):
"""
:param ch: 通道对象
:param method: 消息方法
:param properties:
:param body: 消息内容
:return: None
"""
print(" [x] Received %r" % (body,))
time.sleep(2)
print(" [x] Done")
# 发送消息确认,确认交易标识符
ch.basic_ack(delivery_tag=method.delivery_tag)
我们通过命令查看哪些消费者没有回复ack确认
# Linux
rabbitmqctl list_queues name messages_ready messages_unacknowledged
# Windows
rabbitmqctl.bat list_queues name messages_ready messages_unacknowledged
2、队列持久化
如果我们希望即使在RabbitMQ服务重启的情况下,也不会丢失消息,我们可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。
但依然解决不了小概率丢失事件的发生(比如RabbitMQ服务器已经接收到生产者的消息,但还没来得及持久化该消息时RabbitMQ服务器就断电了),如果我们需要对这种小概率事件也要管理起来,那么我们要用到事务。
由于这里仅为RabbitMQ的简单介绍,所以这里将不讲解RabbitMQ相关的事务。 这里我们需要修改下生产者和消费者设置RabbitMQ消息的持久化**[生产者/消费者]都需要配置**
channel.queue_declare(queue='task_queue', durable=True) # 队列持久化
3、公平分发
默认情况下RabitMQ会把队列里面的消息立即发送到消费者,无论该消费者有多少消息没有应答,也就是说即使发现消费者来不及处理,新的消费者加入进来也没有办法处理已经堆积的消息,因为那些消息已经被发送给老消费者了。类似下面的
在消费者中增加:`channel.basic_qos(prefetch_count=1)`
prefetchCount:会告诉RabbitMQ不要同时给一个消费者推送多于N个消息,即一旦有N个消息还没有ack,则该consumer将block掉,直到有消息ack。
这样做的好处是,如果系统处于高峰期,消费者来不及处理,消息会堆积在队列中,新启动的消费者可以马上从队列中取到消息开始工作。
公平分发.png
工作过程如下:
1. 消费者1接收到消息后处理完毕发送了ack并接收新的消息并处理
2. 消费者2接收到消息后处理完毕发送了ack并接收新的消息并处理
3. 消费者3接收到消息后一直处于消息中并没有发送ack不在接收消息一直等到消费者3处理完毕后发送ACK后再接收新消息
持久化和公平分发.py的更多相关文章
- 【python】-- RabbitMQ 队列消息持久化、消息公平分发
RabbitMQ 队列消息持久化 假如消息队列test里面还有消息等待消费者(consumers)去接收,但是这个时候服务器端宕机了,这个时候消息是否还在? 1.队列消息非持久化 服务端(produc ...
- RabbitMQ简单应用の公平分发(fair dipatch)
公平分发(fair dipatch)和轮询分发其实基本一致,只是每次分发的机制变了,由原来的平均分配到现在每次只处理一条消息 1.MQ连接工厂类Connection package com.mmr.r ...
- RabbitMQ (四) 工作队列之公平分发
上篇文章讲的轮询分发 : 1个队列,无论多少个消费者,无论消费者处理消息的耗时长短,大家消费的数量都一样. 而公平分发,又叫 : 能者多劳,顾名思义,处理得越快,消费得越多. 生产者 public c ...
- rabbitmq 公平分发和消息接收确认(转载)
原文地址:http://www.jianshu.com/p/f63820fe2638 当生产者投递消息到broker,rabbitmq把消息分发到消费者. 如果设置了autoAck=true 消费者会 ...
- RabbitMQ学习第二记:工作队列的两种分发方式,轮询分发(Round-robin)和 公平分发(Fair dispatch)
1.什么是RabbitMQ工作队列 我们在应用程序使用消息系统时,一般情况下生产者往队列里插入数据时速度是比较快的,但是消费者消费数据往往涉及到一些业务逻辑处理导致速度跟不上生产者生产数据.因此如果一 ...
- RabbitMQ的轮询模式和公平分发
一.常用的消息模式 我们在工作的使用中,经常会遇到多个消费者监听同一个队列的情况,模型如下图所示: 当有多个消费者时,我们的消息会被哪个消费者消费呢,我们又该如何均衡消费者消费信息的多少呢: 主要有两 ...
- 工作队列work queues 公平分发(fair dispatch) And 消息应答与消息持久化
生产者 package cn.wh.work; import cn.wh.util.RabbitMqConnectionUtil; import com.rabbitmq.client.Channel ...
- Java使用RabbitMQ之公平分发
发送消息: package org.study.workfair; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Con ...
- RabbitMQ 均衡调度(公平分发机制)
均衡调度是针对Consumer来说的.现在有两个Consumer请求同一个队列的消息.RabbitMQ会将序号为奇数的消息发给第一个Consumer,会将序号为偶数的消息发送给第二个Consumer. ...
随机推荐
- MySQL的视图总结
使用下面格式创建视图: create or replace view viewName as select ..... from ...... where .... 删除视图: drop view v ...
- Git - 常见错误与解决方案
1.windows使用git时出现:warning: LF will be replaced by CRLF 分析: windows中的换行符为 CRLF, 而在linux下的换行符为LF,所以在执行 ...
- ORACLE 当字段中有数据如何修改字段类型
创建视图的时候,因为表太多,里面一些字段类型不一样,PL/SQL报错,为‘表达式必须具有对应表达式相同的数据类型’,发现后,一个字段的类型为CLOB和VARCHAR2(4000)两种,将CLOB进行修 ...
- 在linux和本地系统之间进行数据传输的简单方法--lrzsz
lrzsz是一款在linux里可代替ftp上传和下载的程序. >>提君博客原创 http://www.cnblogs.com/tijun/ << 提君博客原创 安装和使用非 ...
- python数据结构与算法第十七天【概率算法】
1. 古典概率 例如:麻将开始摸到的14张牌中无将的概率,两张相同的牌即为将,则有: 所有的情况:从136张牌中选出14张牌,为C136-14 无将的情况:将不同的牌分组,共有34组,依次取14张牌, ...
- Java权限访问修饰符
私有的,以 private 修饰符指定,在同一类内可见. 默认的,也称为 default,在同一包内可见,不使用任何修饰符. 受保护的,以 protected 修饰符指定,对同一包内的类和所有子类可见 ...
- jmeter 启动报错:not able to find java executable or version
1 运行cmd输入:java -version 查看 提示没有命令 2 查看环境变量path 3 执行 %JAVA_HOME% 提示找不到文件件 4 修改 文件夹名称 5 运行cmd java -ve ...
- Delphi MDI 子窗体的创建和销毁 [zhuan]
1.如果要创建一个mdi child,先看是否有这个child 存在,如果有,则用它,如果没有再创建 //该函数判断MDI 子窗体是否存在,再进行创建和显示function isInclude(for ...
- css繼承
概念:就是上級設置了css屬性,下級默認有同樣的樣式,如果下級需要不一樣的樣式,那麼就需要單獨對下級設置. 範圍: font-family:字體 font-weight:粗細 font-size:尺寸 ...
- PLSQL 汉化
自动导入PLSQL安装目录: 一直下一步就可以了: 之后重新打开: