1.1消息队列学习笔记

(1)为什么使用消息队列啊?

核心的有3个:解耦、异步、削峰

(2)消息队列有什么优点和缺点啊?

优点:解耦、异步、削峰

缺点

增加系统复杂度;

增加系统故障率;

某个消费者失败会有数据一致性问题。

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

kafka:多个broker组成,每个broker是一个节点;每个topic是一类消息,分为多个partition在不同的broker上每个partition就放一部分数据。

分布式消息队列,一个topic的数据分散放在多个机器上的,每个机器就放一部分数据。

 

kafka 提供replica副本机制保证HA。每个partition都会同步到其他机器上,形成自己的多个replica副本提高容错性。有replica选举一个leader出来负责生产和消费,其他replica就是follower。leader会把写的数据同步到所有follower上去,读直接读leader上数据。

 kafka会均匀的将一个partition的所有replica分布在不同的机器上,这样才可以提高容错性

每组多副本的partition会选举一个leader

多副本+leader选举形成了高可用性。

如何保证消息不被重复消费啊(如何保证消息消费时的幂等性)?

使用消息队列如何保证幂等性,这是架构里要考虑的一个问题。需要结合具体的业务来看

rabbitmq、kafka,都有可能会出现消费重复消费的问题mq无法自己保证的,是程序逻辑给保证的

 

 

一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性

怎么保证消息队列消费的幂等性?

(1)消费时基于数据库的唯一键来保证重复数据不会重复插入多条

(2)消费时写redis,没问题了,反正每次都是set,天然幂等性

(3)消费时通过全局唯一id查看是否消费过,消费后写状态或redis

消费时通过全局唯一id查db或redis是否消费过,查无消费后写状态或redis

 

 

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

用mq有个基本原则,数据不能多一条,也不能少一条不能多,就是重复消费和幂等性问题。不能少,就是数据不能搞丢了。

 

丢数据,mq一般分为两种,1mq自己弄丢了,2消费的时候弄丢了

 

(1)rabbitmq

1)生产者弄丢了数据

生产者发送数据搞丢了。

1可以开启rabbitmq事务机制,但同步阻塞消耗性能吞吐量低

 

2可以开启confirm模式,生产者确认模式来判断成功或者重试发送。confirm机制是异步的,异步回调应答

一般在生产者避免数据丢失,都是用confirm机制的。

 

Confirm 确认。证实,证明。

 

2)rabbitmq弄丢数据

为防止rabbitmq自己弄丢了数据,必须开启rabbitmq的持久化极小的概率没来得及持久化就挂了,会导致内存里的一点点数据会丢失。

 

3)消费端弄丢了数据

刚从rabbitmq消费到,还没处理,结果进程挂了,rabbitmq认为你都消费了,这数据就丢了。

rabbitmq提供消费者ack机制关闭自动ack,处理完消费手动调用ack。rabbitmq消费分配给别的consumer去处理,这里要考虑幂等性问题

 

(2)kafka

 

  1. 消费端弄丢了数据

消费端在处理完消息后手动提交offset。如果处理完没提交offset进程挂了,保证幂等性

消费到了消息,自动提交offset, kafka以为已消费,没处理就挂了,消息丢

 关闭自动提交offset,在处理完消息手动提交offset,可以保证数据不会丢。会重复消费,比如刚处理完没提交offset,进程挂了,要自己保证幂等性。

 

生产环境碰到的问题,kafka消费者消费到了数据之后是写到一个内存的queue里先缓冲一下,消费者会自动提交offset。此时重启系统,会导致内存queue里还没来得及处理的数据丢失

 

2)kafka弄丢了数据

 

新选举的leader还没同步挂掉leader的数据,就会丢了一些数据啊。生产会遇到过follower切换为leader之后会丢失一些数据

 

进行leader切换时,数据不会丢失 设置如下4个参数

1每个partition必须有至少2个副本

2确保leader至少感知有一个follower,

3acks=all  所有replica副本写入才算写成功,

4一旦写入失败就不断重试,卡在这里retries=MAX

 

如果设置ack=all,生产者会动重试,直到所有写入

 

 

7)如何保证消息的顺序性?

 

消息是有先后顺序的:增加、修改、删除;顺序变了最终结果就不一样

 

 

1 )rabbitmq:拆分多个queue,每个queue一个consumerconsumer按keyid写N个内存queue,,然后N个线程分别消费一个内存queue即可。

 

2)kafka:一个topic,一个partition,一个consumer,内部单线程消费,按keyid写N个内存queue,然后N个线程分别消费一个内存queue即可。

8)如何解决消息队列的延时以及过期失效问题?

 

消费端不消费了,或者消费缓慢大量消息积压在mq里

 

(1)大量消息在mq里积压了几个小时了还没解决

1在数量不太多的时候修复consumer ,让程序自己缓慢恢复。

2数据量超大,修复consumer,紧急扩容 ,用以前十倍的partition 同时将consumer实例和consume queuer内存队列扩大十倍,消费完挤压数据恢复到原先部署架构。

(2)如果rabbitmq超时数据已经清理丢失。等过了高峰期批量重导将丢失的数据,写个临时程序查出来,重新灌入mq里面去,把数据给他补回来。

(3)消息积压在mq里,很长时间都没处理掉,此时导致mq都快写满了,临时写程序消费一个丢弃一个,快速消费掉所有消息。然后走第二个方案,到了晚上再补数据。

发布了13 篇原创文章 · 获赞 0 · 访问量 139

猜你喜欢

转载自blog.csdn.net/vip9850/article/details/105431425