中间件之消息队列篇

写在前面

这是中间件之消息队列篇,涉及知识包括,可用于八股文复习宝典,也可用于加深知识,建议大家以闯关的模式进行阅读,然后根据内容查漏补缺,欢迎提问相互学习交流

之前已经完成了

  1. 新版javase必备核心知识篇,点击即可学习
  2. 并发编程必备核心知识篇,点击即可学习

接下来还将更新

  1. Mysql核心知识点
  2. http协议核心知识点
  3. Spring-Mybatis核心知识点
  4. 分布式缓存核心知识点

中间件之消息队列篇概览
常用消息队列有哪些,引入队列的优缺点
消息队列的发送方式有哪几种,使用场景分别是怎样的?
延迟消息使用场景
如何作消息的重复消费处理
消息队列如何保证消息的可靠性传输

常用消息队列有哪些,引入队列的优缺点

优点:解耦系统、异步化、削峰
缺点: 系统可⽤性降低、复杂度增高、维护成本增高

主流消息队列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做唯⼀索引,因为存在唯⼀索引,所以重复消费会失败

消息队列如何保证消息的可靠性传输

消息可靠性传输,是非常重要,消息如果丢失,可能带来严重后果,⼀般从三个⻆度去分析

  1. producer端:
    不采用oneway发送,使用同步或者异步方式发送,做好重试,但是重试的Message key必须唯⼀
    投递的日志需要保存,关键字段,投递时间、投递状态、重试次数、请求体、响应体
  2. broker端:
    多主多从架构,需要多机房
    同步双写、异步刷盘 (同步刷盘则可靠性更高,但是性能差点,根据业务选择)
    机器断电重启:异步刷盘,消息丢失;同步刷盘消息不丢失
    硬件故障:可能存在丢失
  3. consumer端
    消息队列⼀般都提供的ack机制,发送者为了保证消息肯定消费成功,只有 消费者明确表示消费成功,队列才会认为消息消费成功,中途断电、抛出异常等都不会认为成功——即都会重新投递,每次在确保处理完这个消息之后,在代码里调用ack,告诉消息队列消费成功
    消费端务必做好幂等性处理
    消息消费务必保留日志,即消息的元数据和消息体,完善的消息补偿机制,发送失败的消息可以再感知并⼆次处理
    在rabbitMQ中保证消息可靠性:
    生产者到交换机
    通过confirmCallback
    交换机到队列
    通过returnCallback
    最后
    开启消息确认机制以后,保证了消息的准确送达,但由于频繁的确认交互, rabbitmq 整体效率变低,吞吐量下降严重,不是非常重要的消息不建议用消息确认机制

你可能感兴趣的:(笔记,中间件,kafka,java)