这是中间件之消息队列篇,涉及知识包括,可用于八股文复习宝典,也可用于加深知识,建议大家以闯关的模式进行阅读,然后根据内容查漏补缺,欢迎提问相互学习交流。
之前已经完成了
接下来还将更新
中间件之消息队列篇概览 常用消息队列有哪些,引入队列的优缺点 消息队列的发送方式有哪几种,使用场景分别是怎样的? 延迟消息使用场景 如何作消息的重复消费处理 消息队列如何保证消息的可靠性传输
常用消息队列有哪些,引入队列的优缺点
优点:解耦系统、异步化、削峰 缺点: 系统可⽤性降低、复杂度增高、维护成本增高
主流消息队列Apache ActiveMQ、Kafka、RabbitMQ、RocketMQ ActiveMQ:官方地址,点击即可查看更多 Apache出品,历史悠久,支持多种语⾔的客户端和协议,支持多种语言Java, .NET, C++等,基于JMS Provider的实现 缺点:吞吐量不高,多队列的时候性能下降,存在消息丢失的情况,比较少大规模使用 Kafka:官方地址,点击即可查看更多 是由Apache软件基⾦会开发的⼀个开源流处理平台,由Scala和Java编写。Kafka是⼀种高吞吐量的分布式发布订阅消息系统,它可以处理大规模的网站中的所有动作流数据(网页浏览,搜索和其他用户的行动),副本集机制,实现数据冗余,保障数据尽量不丢失;支持多个生产者和消费者 缺点:不支持持批量和⼴播消息,运维难度大,⽂档比较少, 需要掌握Scala RabbitMQ:官方地址,点击即可查看更多 是⼀个开源的AMQP实现,服务器端⽤Erlang语⾔编写,⽀持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、用于在分布式系统中存储转发消息,在易用性、扩展性、⾼可用性等方面表现不错 缺点:使用Erlang开发,阅读和修改源码难度大 RocketMQ:官方地址,点击即可查看更多 阿里开源的⼀款的消息中间件, 纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应⽤的特点, 性能强劲(零拷⻉技术),支持海量堆积, 支持指定次数和时间间隔的失败消息重发,⽀持consumer端tag过滤、延迟消息用等,在阿⾥内部进行大规模使用,适合在电商,互联网金融等领域使⽤ 缺点:成熟的资料相对不多,社区处于新生状态但是热度高
消息队列的发送方式有哪几种,使用场景分别是怎样的? 发送⽅式⼀般分三种 SYNC 同步发送 应用场景(没有绝对,都看业务场景而定):重要通知邮件、报名短信通知、营销短信系统等 ASYNC 异步发送 应用场景:对RT时间敏感,可以支持更高的并发,回调成功触发相对应的业务,比如注册成功后通知优惠卷系统发放优惠券 ONEWAY 无需要等待响应 应用场景:主要是⽇志收集,适用于某些耗时非常短,但对可靠性要求并不高的场景, 也就是LogServer, 只负责发送消息,不等待服务器回应且没有回调函数触发,即只发送请求 不等待应答
延迟消息使用场景 什么是延迟消息: Producer 将消息发送到消息队列 broker服务端,但并不期望这条消息立刻投递,而是推迟到在当前时间点之后的某⼀个时间投递到 Consumer 进行消费 使用场景⼀:通过消息触发⼀些定时任务,⽐如在某⼀固定时间点向⽤户发送提醒消息 使用场景⼆:消息⽣产和消费有时间窗⼝要求,比如在XX电商交易中超时未支付关闭订单的场景,在订单创建时会发送⼀条 延时消息。这条消息将会在 30 分钟以后投递给消费者,消费者收到此消息后需要判断对应的订单是否已完成支付。 如⽀付未完成,则关闭订单。如已完成支付则忽略
如何作消息的重复消费处理 幂等性:⼀个请求,不管重复来多少次,结果是不会改变的。 RabbitMQ、RocketMQ、Kafka等任何队列不保证消息不重复,如果业务需要消息不重复消费,则需要消费端处理业务消息要保持幂等性 方式⼀:Redis的setNX() , 做消息id去重 java版本目前不支持设置过期时间 //Redis中操作,判断是否已经操作过 TODO boolean flag = jedis.setNX(key); if(flag){ //消费 }else{ //忽略,重复消费 } 方式⼆:redis的 Incr 原子操作:key自增,大于0 返回值大于0则说明消费过,(key可以是消息的md5取值, 或者如果消息id设计合理直接用id做key) int num = jedis.incr(key); if(num == 1){ //消费 }else{ //忽略,重复消费 } 方式三:数据库去重表 设计⼀个去重表,某个字段使⽤Message的key做唯⼀索引,因为存在唯⼀索引,所以重复消费会失败
消息队列如何保证消息的可靠性传输 消息可靠性传输,是非常重要,消息如果丢失,可能带来严重后果,⼀般从三个⻆度去分析