消息中间件 python 消息中间件的应用场景_消息队列


一:消息队列MQ(中间件)

***MQ属于消息队列中间件,主要用于企业间的数据互通。

1.为什么使用消息队列?

消息队列主要的的应用场景(不可否认还有其他的,但此处只介绍主要几个),即以下六字真言:解耦,异步,削峰。

(1),解耦:

传统模式的缺点:

*系统间耦合性太强,接入新系统需要频繁改动代码。

中间件模式的优点:

*将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要做任何修改。

(2)异步:

传统模式的缺点:

*一些非必要的业务逻辑以同步的方式运行,太耗费时间。

中间件模式的优点:

*将消息写入消息队列,非必要业务逻辑以异步的方式运行,加快响应速度。

(3)削峰

传统模式缺点:

*并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常。

中间件模式的优点:

*系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是被允许的。

2.使用消息队列的缺点:

分析:一个使用了MQ的项目,如果连这个问题都没有考虑进去,就使用了MQ,那就给自己的项目带来了风险,我们引入一个技术,就需要对这个技术的弊端有充分的认识,才能做好预防。不能给自己挖坑。

MQ使用的弊端,可以从以下两个方面来回答:

*系统可用性降低:加入消息队列进去,消息队列挂了,系统就呵呵了,因此,系统的可用性降低了。

*系统复杂性增加:要多考虑很多方面的问题,如一致性问题,如何保证消息不被重复消费,如何保证消息可靠传输等。

3.消息队列如何选型?

常见的消息队列有ActiveMQ,RabbitMQ,RocketMQ,Kafka,以及ZeroMQ等其他MQ。

分析:在项目中用了MQ,肯定事先要对业界流行的MQ进行调研,需要了解每种MQ的优缺点,如:需要考虑为什么要用这种MQ?

(1);ActiveMQ,可在ActiveMQ社区了解:http://activemq.apache.org/

(2):RabbitMQ,可在RabbitMQ社区了解:http://www.rabbitmq.com/

rabbitma比activemq更新较活跃,


消息中间件 python 消息中间件的应用场景_消息中间件 python_02


4.如何保证消息队列是高可用的?

(1) 分析:引入消息队列后,系统的可用性下降。在生产中,没人使用单机的消息队列,故高可用耳朵消息队列至关重要,需要有很深入的了解才行,需考虑你的消息中间件如何保证高可用?只会订阅和发布消息则是不行的,考虑消息队列的高可用,就需要对消息队列的集群模式有深入的了解才行!

如:rocketMQ,他的集群就有多master模式,多master多slave异步复制模式,多master多slave同步双写模式,多master多slave模式部署架构图:

该部署架构图与kafka很相似,只是Name server集群,而在kafaka中是使用zookeeper来代替,都是用来保存和发现master和slave用的。通信过程如下:

producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master建立长链接,且定时向Broker发送心跳,Producer只能将消息发送到Broker master,但是Consumer则不一样,他同时和提供Topic服务的Master和Slave建立长链接,既可以从Broker Master订阅消息,也可以从Broker Slave订阅消息.

(2),kafka架构:

一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer Group,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。

至于rabbitMQ,也有普通集群和镜像集群模式,自行去了解,比较简单,两小时即懂。

要求,在回答高可用的问题时,应该能逻辑清晰的画出自己的MQ集群架构或清晰的叙述出来。

处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步

那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步

1、将queue的持久化标识durable设置为true,则代表是一个持久的队列

2、发送消息的时候将deliveryMode=2

这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据

(3)消费者丢数据

消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时rahbitMQ会立即将消息删除,这种情况下如果消费者出现异常而没能处理该消息,就会丢失该消息。

至于解决方案,采用手动确认消息即可


消息中间件 python 消息中间件的应用场景_kafka_03


(1)生产者丢数据

在kafka生产中,基本都有一个leader和多个follwer。follwer会去同步leader的信息。因此,为了避免生产者丢数据,做如下两点配置

1. 第一个配置要在producer端设置acks=all。这个配置保证了,follwer同步完成后,才认为消息发送成功。

2. 在producer端设置retries=MAX,一旦写入失败,这无限重试

(2)消息队列丢数据

针对消息队列丢数据的情况,无外乎就是,数据还没同步,leader就挂了,这时zookpeer会将其他的follwer切换为leader,那数据就丢失了。针对这种情况,应该做两个配置。

1. replication.factor参数,这个值必须大于1,即要求每个partition必须有至少2个副本

2. min.insync.replicas参数,这个值必须大于1,这个是要求一个leader至少感知到有至少一个follower还跟自己保持联系

这两个配置加上上面生产者的配置联合起来用,基本可确保kafka不丢数据

(3)消费者丢数据

这种情况一般是自动提交了offset,然后你处理程序过程中挂了。kafka以为你处理好了。再强调一次offset是干嘛的

offset:指的是kafka的topic中的每个消费组消费的下标。简单的来说就是一条消息对应一个offset下标,每次消费数据的时候如果提交offset,那么下次消费就会从提交的offset加一那里开始消费。

比如一个topic中有100条数据,我消费了50条并且提交了,那么此时的kafka服务端记录提交的offset就是49(offset从0开始),那么下次消费的时候offset就从50开始消费。

解决方案也很简单,改成手动提交即可。