消息队列
用处:系统解耦,异步,削峰
缺点:系统的可用性降低,引用了太多的外部依赖,复杂度提高,需要考虑mq的消息保证,如丢失,重复.传递顺序等.一致性,
消息高可用性
首先RabbitMQ现在使用镜像集群的模式,(跟主从差不多的思想),在向队列插入数据时会同时向镜像队列中插入数据.
Kafka的高可用性,由多个broker组成,每个broker是一个节点,当你创建一个topic时,会将其划分成多个partition,每个partition可以存放在不同的broker,每个partition就放一部分数据.思想跟HDFS高可用性的思想差不多,将整个拆分并将每个分区复制到几台broker中.天然的分布式消息队列.
那么这中间一定有一个leader,在写数据的时候,leader会负责把数据同步到所有follower上去,读的时候直接读leader上的数据,为啥不读slave那?如果读slave涉及到分布式数据一致性问题,增加系统的复杂度,.
消息幂等性
原因,kafka有offset的概念,在每个消息写进去,都有一个offset,代表消息的序号,然后counsumer消费了数据后,每隔一段时间,会把自己消费过的消息的offset提交一下,表示我已经消费过.下次如果重启,则就让其继续从上次消费到的offset来继续消费.
但是如果在重启的时候有些consumer消息处理未提交offset那么在重启后会在消费一次.
其实就是在修改数据的时候进行条件唯一性判断.尽量使用赋值而不是计算操作.
消息可靠性
我们可以在生产者,消费者中开启confirm模式,当生产者向队列发送数据,只有队列返回值证明已经成功才算成功,在消费的时候,消费者在消费完成后向队列发送消费完成,这样队列才删除消息否则不删除.
这时我们还需要考虑一个问题就是如果队列将消息丢失该怎么办,首先我们开启队列持久化尽量保证消息写入磁盘中.如果想要最大防止消息丢失,可以在消息持久化后队列才向生产者返回ack指令.
消息顺序性
虽然使用mq将消息串行话,但是在并发中一切串行皆是浮云,所以就需要我们改变mq的设计
一种方法,设置一个消费者中间件,将所有的消息进行排列然后发送到相应的队列中.
二种方法,将相同的特征的数据放到一个queue中.
消息积压,延迟,过期失效问题.
积压
大量的消息存在消息队列中得不到消费,这时一般只能临时紧急扩容.创建一个消费者中间件做一个消息路由转发的功能,将积压的消息发送到扩容的队列中.
消息时间过期
假设使用rabbitmq,那么它可以设置消息过期时间,TTL.那么如果消费者消费能力慢导致消息过期,那么可能会造成消息的大量丢失问题.这是我们可以为队列绑定一个死信队列,在消息过期后会自动转移到死信队列中.我们为死信队列添加一个消费者,将消息保存下来,并在消费者有能力消费时进行消费.