Water2Wine

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
1. 为什么要用消息队列

消息队列比较核心的使用场景有3个:解耦、异步、削峰

解耦:将生产者和消费者解耦
这个需要去考虑一下系统中是否有类似的场景,就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用MQ给他异步化解耦,也是可以的,就需要去考虑在项目里是不是可以运用MQ

异步:生产者可能需要同步调用消费者,有了MQ集群,生产者发送消息和消费者调用就不再是同步了,消费者可以并行的调用MQ集群中的消息-----回调函数就是用在这里了!!!

削峰:将可能在短时间内集中上线的设备存储在消息队列中,控制器可以根据自己的处理速度逐步处理

2. 消息队列的优缺点

优点:

在特殊场景下有对应的好处:解耦、异步、削峰

缺点:

系统可用性降低:系统引入的外部依赖越多,越容易挂掉

系统复杂性提高:如何保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?

一致性问题:A系统处理完了直接返回成功了,但是如果BCD三个系统里有一个失败了,那数据就不一致了

3. 消息队列在实际应用中的一些问题
如何保证消息队列高可用

kafka首先是分布式的,即同一个生产者生产的消息会分布在不同的机器上

有一个副本机制,每一个partition都会有几个副本机器,同一类partition会选举一个leader,只有了leader可以对外读写,其他机器为follower

如何保证消息不被重复消费,如何保证消费的时候是幂等的

每条消息都有一个offset,代表了这个消息的顺序的序号,按照数据进入kafka的顺序,会给每条数据分配一个offset,代表了这个数据的序号
消费者从kafka去消费的时候,是按照这个顺序去消费的;消费者会去提交offset给zookeeper,就是告诉kafka我已经消费到offset=???这条数据了;zk里面就记录了消费者当前消费到了offset=几的那条消息;zk会告诉kafka,这样kafka就知道我下一次改给消费者哪条数据了
消费者不是说消费完一条数据就立马提交offset的,而是定时定期提交一次offset。这也就意味着可能会存在一定的重复消费

幂等性:一个数据,或者一个请求,重复多次,确保对应的数据是不会改变的,不能出错
如何保证MQ幂等性,需要结合具体业务来谈(这个我要结合华为的业务谈,这个需要找一找)
比如增加一个redis的set集合之类的,或者kafka可以通过设置producer端参数来完成

如何保证消息的可靠性传输,要是消息丢失了怎么办

消费者中间件生产者三端都有可能有消息可靠性问题

消费端弄丢了数据:
每消费一条消息提交一次offset(而不是主动提交,这是在消费之前的),注意保证幂等性
业务代码中部分消费dmq采用了异步方式,即取出消息后执行commit操作,然后对消息进行异步处理,如果出现异常则会导致dmq消息丢失
dmq一致性消费框架主要用于解决这个问题,实现的基本原理是消息取出后进行数据库持久化,然后进行commit,业务消费成功后对持久化的数据删除,如果出现消费异常数据将会保存在数据库中,业务可通过查询接口再次获取,消费成功后执行删除操作

kafka弄丢了数据:
leader和follower不同步可能导致
这个需要设置4个参数:
给这个topic设置replication.factor参数:这个值必须大于1,要求每个partition必须有至少2个副本
在kafka服务端设置min.insync.replicas参数:这个值必须大于1,这个是要求一个leader至少要跟1个follower保持联系
在producer端设置asks=all:这个是要求每条数据,必须是写入所有replica之后,才能认为是写成功能了
在producer端设置retries=MAX:这个是要求一旦写入失败,就无限重试,卡在这里了

生产者会不会弄丢数据:
如果按照上述思路设置了acks=all,一定不会丢,因为会无限重试

如何保证消息的顺序性

kafka需要保证顺序的数据会读入同一个partition给同一个消费者消费,但是消费时是多线程消费的,这时候可能会导致顺序性问题
解决方案是引入中间队列,将需要保证顺序的消息放入同一个内存队列,给同一个线程消费

如何解决消息队列的延时以及过期失效问题
消息队列满了怎么处理

清空kafka并重启

posted on 2020-08-04 16:43  Water2Wine  阅读(437)  评论(0)    收藏  举报