RabbitMQ与Redis对比
RabbitMQ是一种比较流行的消息中间件,之前我一直使用redis作为消息中间件,但是生产环境比较推荐RabbitMQ来替代Redis,所以我去查询了一些RabbitMQ的资料。相比于Redis,RabbitMQ优点很多,比如:
具有消息消费确认机制
队列,消息,都可以选择是否持久化,粒度更小、更灵活。
可以实现负载均衡
RabbitMQ应用场景
异步处理:比如用户注册时的确认邮件、短信等交由rabbitMQ进行异步处理
应用解耦:比如收发消息双方可以使用消息队列,具有一定的缓冲功能
流量削峰:一般应用于秒杀活动,可以控制用户人数,也可以降低流量
日志处理:将info、warning、error等不同的记录分开存储
RabbitMQ消息模型
这里使用Python的pika这个库来实现RabbitMQ中常见的6种消息模型。没有的可以先安装:
pip install pika
1.单生产单消费模型:即完成基本的一对一消息转发。
# 生产者代码
import pika
credentials = pika.PlainCredentials('chuan', '123') # mq用户名和密码,没有则需要自己创建
# 虚拟队列需要指定参数 virtual_host,如果是默认的可以不填。
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost',
port=5672,
virtual_host='/',
credentials=credentials))
# 建立rabbit协议的通道
channel = connection.channel()
# 声明消息队列,消息将在这个队列传递,如不存在,则创建。durable指定队列是否持久化
channel.queue_declare(queue='python-test', durable=False)
# message不能直接发送给queue,需经exchange到达queue,此处使用以空字符串标识的默认的exchange
# 向队列插入数值 routing_key是队列名
channel.basic_publish(exchange='',
routing_key='python-test',
body='Hello world!2')
# 关闭与rabbitmq server的连接
connection.close()
# 消费者代码
import pika
credentials = pika.PlainCredentials('chuan', '123')
# BlockingConnection:同步模式
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost',
port=5672,
virtual_host='/',
credentials=credentials))
channel = connection.channel()
# 申明消息队列。当不确定生产者和消费者哪个先启动时,可以两边重复声明消息队列。
channel.queue_declare(queue='python-test', durable=False)
# 定义一个回调函数来处理消息队列中的消息,这里是打印出来
def callback(ch, method, properties, body):
# 手动发送确认消息
ch.basic_ack(delivery_tag=method.delivery_tag)
print(body.decode())
# 告诉生产者,消费者已收到消息
# 告诉rabbitmq,用callback来接收消息
# 默认情况下是要对消息进行确认的,以防止消息丢失。
# 此处将auto_ack明确指明为True,不对消息进行确认。
channel.basic_consume('python-test',
on_message_callback=callback)
# auto_ack=True) # 自动发送确认消息
# 开始接收信息,并进入阻塞状态,队列里有信息才会调用callback进行处理
channel.start_consuming()
2.消息分发模型:多个收听者监听一个队列。
# 生产者代码
import pika
credentials = pika.PlainCredentials('chuan', '123') # mq用户名和密码
# 虚拟队列需要指定参数 virtual_host,如果是默认的可以不填。
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost',
port=5672,
virtual_host='/',
credentials=credentials))
# 建立rabbit协议的通道
channel = connection.cha