保证顺序消费方案:
- 单线程消费来保证消息的顺序性;
- 对消息进行编号,消费者处理时根据编号判断顺序;
保证高可用方案:
RabbitMQ: 主要有三种模式:单机模式,普通集群模式,镜像集群模式;
单机模式:这种模式很简单,就是一台机器处理所有消息;
普通集群模式:多台机器,当消费者拉取在一台机器中拉取数据的时候,如果不存在,那么就去其他机器中拉取,这种方式容易产生大量的网络传输,耗时比较严重。而且一台机器宕机,数据很可能会丢失;
镜像集群模式:多台机器,每台机器上的数据都一样,这种模式数据不会丢失,但是数据冗余,机器浪费比较严重,大数据场景下不适用;
Kafka: 它主要通过多个broker,每个broker是一个节点。创建一个topic,这个topic可以划分为多个partition,每个partition可以存在于不同的broker上,每个partition就放一部分数据;
kafka 0.8以后,提供了HA机制,就是replica副本机制;kafka会均匀的将一个partition的所有replica分布在不同的机器上,来提高容错性;每个partition的数据都会同步到其他机器上,形成自己的多个replica副本。然后所有replica会选举一个leader出来,那么生产和消费都去leader,其他replica就是follower,leader会同步数据给follower。当leader挂了会自动去找replica,然后会再选举一个leader出来,这样就具有高可用性了。
写数据的时候,生产者就写leader,然后leader将数据落地写本地磁盘,接着其他follower自己主动从leader来pull数据。一旦所有follower同步好数据了,就会发送ack给leader,leader收到所有follower的ack之后,就会返回写成功的消息给生产者。(当然,这只是其中一种模式,还可以适当调整这个行为)
消费的时候,只会从leader去读,但是只有一个消息已经被所有follower都同步成功返回ack的时候,这个消息才会被消费者读到。
保证数据不被丢失方案
消息队列如何保证顺序性?
RabbitMQ:
在 MQ 里面创建多个 queue,同一规则的数据(对唯一标识进行 hash),有顺序的放入 MQ 的 queue 里面;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
KafKa:
给数据指定某个Key,相同Key的数据会保存到同一个partition中,由于数据在partition中是有序的,所以在cunsumer端使用一个单线程消费是没有问题的;
在consumer端使用内存队列排队,队列中的数据使用Hash分发,确保一个线程对应一个队列,这样可以保证数据消费的有序性;
消息队列做分布式事务
RocketMQ 事务消息设计
- 事务发起方首先发送 prepare 消息到 MQ。
- 在发送 prepare 消息成功后执行本地事务。
- 根据本地事务执行结果返回 commit 或者是 rollback。
- 如果消息是 rollback,MQ 将删除该 prepare 消息不进行下发,如果是 commit 消息,MQ 将会把这个消息发送给 consumer 端。
- 如果执行本地事务过程中,执行端挂掉,或者超时,MQ 将会不停的询问其同组的其它 producer 来获取状态。
- Consumer 端的消费成功机制有 MQ 保证。