消息队列常见实战问题

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

一、rabbitmq的高可用

a.单机模式

b.普通集群模式(无高可用性)

    【连接获取数据方式】创建的queue只会放到一个mq上,消费的时候如果连接的另一个实例。那么需要去存放数据的queue拉取数据。

    【设置连接方式】

         1)随机 的获取实例连接所有的queue。缺点:有拉取数据的性能问题

         2)指定到有queue的mq上。缺点:单实例的性能瓶颈

     【事故处理方式】存放了queue的实例宕机了,未开启持久化的话,其它实例会拉取不到数据。开启了持久化的话,需要服务器恢复了才能继续使用。

c.镜像集群模式

      【存储数据的方式】创建的queue和queue里的消息都会存在于多个实例上,每次写消息都会自动把消息到多个实例queue进行消息同步。

       缺点:1.同步数据导致网络带宽压力和消耗很重。2.没有扩展性,新增的机器也包含了这个queue的全部数据。

       优点:一个机器坏了,其余机器可以顶上。

 二、kafka的高可用性

      【存放原理】每台服务器上会创建一个broker进程,每台机器+机器上的broker进程,就可以认为是kafka集群中的一个节点。创建一个topic可以指定三个partition。例如写三条数据可能会放到三个partition里面。

      【高可用机制】kafka 0.8以后是有高可用机制,副本机制,每个partition都会有一个副本。主的是leader,副本是follower,写和读数据都是从leader中。leader写入的时候会将数据同步到follower上。

2.如何保证消息不被重复消费?

       a)写库时,先根据主键查一下,发现已经插入了,就更新

       b)如果是写redis,那就没问题,每次都是set,天然幂等性。

       c)

         1)如果是创建订单什么的,可以消费的时候,先向redis里面插入一下。如果第二次消费的时候发现已经存在了就不消费了。

         2)加上唯一键的约束

3.如何保证消息的可靠性传输(如何处理消息丢失的问题)?

一、rabbitmq

     1)生产者丢失了数据

          可以选择rabbitmq的事务功能,发送之前开启事物(channel.txSelect),如果失败了,回滚事务(channel.txRollback),成功了的话,提交事务(channel.txCommit)。缺点消耗性能

         可以开启确认模式,如果成功会给ok消息。如果没成功的话,会回调nack接口

     2)rabbitmq弄丢了数据

        设置持久化。极其少见,尚未持久化,自己就挂了。

       【设置持久化的两个步骤】1.queue的持久化 2.发送消息的deliverymode设置为2,就是将消息设置为持久化。

     3)消费端丢了数据

         利用rabbitmq的ack确认机制。未消费成功,不确认,消息会让另一个消费者消费。

二、kafka

1)消费端丢了数据

        消费了一个offset之后,但是消费失败,kafka自动提交了offset。那么这时候可以关闭自动提交offset,在处理完之后自己手动提交offset。但是这时候会出现重复消费,比如消费完了,但是提交offset的时候出错了。这时候会重新发一次,这时候我们就要保证幂等性措施了。

2)kafka弄丢了数据

        leader尚未同步成功数据给follower。

      【解决方案】可以设置4个参数:

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

               在kafka服务端设置min.insync.replicas参数:这个值必须大于1,这个是要求一个leader至少感知到有至少一个follower还跟自己保持联系,没掉队,这样才能确保leader挂了还有一个follower吧

               在producer端设置acks=all:这个是要求每条数据,必须是写入所有replica之后,才能认为是写成功了

               在producer端设置retries=MAX(很大很大很大的一个值,无限次重试的意思):这个是要求一旦写入失败,就无限重试,卡在这里了

3)生产者弄丢了数据

         设置了ack=all,一定不会丢失,要求所有的follwer收到了leader的数据,才认为本次写成功了。如果没有满足就会不断的重试。

4.如何保证消息的顺序性?

(1)rabbitmq:一个queue,多个consumer,这不明显乱了

   【解决方案】rabbitmq:拆分多个queue,每个queue一个consumer,就是多一些queue而已,确实是麻烦点;或者就一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理

(2)kafka:一个topic,一个partition,一个consumer,内部多线程,这不也明显乱了

   【解决方案】kafka:一个topic,一个partition,一个consumer,内部单线程消费,写N个内存queue,然后N个线程分别消费一个内存queue即可

5.如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

    一、大量数据在mq里面挤压了几个小时还没有解决

     1)先修复cosumer,确保恢复消费速度,然后将现有consumer都停掉。

     2)新建一个topic,partition是原来的10倍,然后建立好原先10或20倍的queue数量

     3)写临时的程序,将挤压的数据发到刚创建的queue里面

     4)部10台消费者

     5)等消费完之后,恢复到原先的部署框架

   二、mq设置了过期时间,queue到达一定程度的积压后给清理掉,会导致大量数据丢失

        把数据查出来进行补救,手动发到mq里面

   三、mq长时间没有处理掉,mq快写满了

        临时写个程序。消费一个丢弃一个,都不要了,快速消费掉所有的数据。然后走着补方案

 

你可能感兴趣的:(——消息中间件,ζ框架技术)