12.19 消息中间件

参考资料:https://thinkwon.blog.csdn.net/article/details/104588612

 

  1. 消息中间件是什么
    1. 消息中间件的定义
      1. 百度:消息中间件是基于队列与消息传递技术,在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统
      2. 技术:是利用高效可靠的消息传递机制进行异步的数据传输,并基于数据通信进行分布式系统的集成。通过提供消息队列模型和消息传递机制,可以在分布式环境下扩展进程间的通信。
    2. 消息中间件的俩种传递模式
      1. 点对点模式:消息生产者将消息发送到队列中,消息消费者从队列中接收消息。消息可以在队列中进行异步传输。
      2. 发布/订阅模式:发布订阅模式是通过一个内容节点来发布和订阅消息,这个内容节点称为主题(topic),消息发布者将消息发布到某个主题,消息订阅者订阅这个主题的消息,主题相当于一个中介。主题是的消息的发布与订阅相互独立,不需要进行基础即可保证消息的传递,发布/订阅模式在消息的一对多广播是采用。
        1. 消息分发和路由
          1. 若该队列至少有一个消费者订阅,消息将以循环(round-robin)的方式发送给消费者。每条消息只会分发给一个订阅的消费者(前提是消费者能够正常处理消息并进行确认)。通过路由可实现多消费的功能
          2. 消息提供方->路由->一至多个队列消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。通过队列路由键,可以把队列绑定到交换器上。消息到达交换器后,RabbitMQ 会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则);
  2. 这个技术的应用场景
    1. 应用程序之间不采取直接通信,而是使用消息中间作为中介,做到数据的异步通信。开发人员不需要考虑网络协议和远程调用的问题,只需要通过各消息中间件所提供的api,就可以简单的完成消息推送,和消息接收的业务功能。
    2. 消息的生产者将消息存储到队列中,消息的消费者不一定马上消费消息,可以等到自己想要用到这个消息的时候,再从相应的队列中去获取消息。这样的设计可以很好的解决,大数据量数据传递所占用的资源,使数据传递和平台分开,不再需要分资源用于数据传输,可以将这些资源用去其他想要做的事情上。
    3. rabbitmq 的使用场景
      1. 服务间异步通信
      2. 顺序消费
      3. 定时任务
      4. 请求削峰
  3. 这个技术的优缺点
    1. MQ的优点
      1. 异步处理 - 相比于传统的串行、并行方式,提高了系统吞吐量。
      2. 应用解耦 - 系统间通过消息通信,不用关心其他系统的处理。
      3. 流量削锋 - 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。
      4. 日志处理 - 解决大量日志传输。
      5. 消息通讯 - 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。
    2. 中间件的缺点
      1. 系统复杂度提高
      2. 可用性问题
      3. 一致性问题
  4. 这个技术的核心是什么
    1. 技术选型,为什么选这个技术
      1. ActiveMQ是老牌的消息中间件,国内很多公司过去运用的还是非常广泛的,功能很强大。但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。
        1. 队列模式,其实就是分食模式。 比如生产方发了 10条消息到 activeMQ 服务器, 而此时有多个 消费方,那么这些消费方就会瓜分这些10条消息,一条消息只会被一个消费方得到。
        2. 主题模式,就是订阅模式。 比如生产方发了10条消息,而此时有多个消费方,那么多个消费方都能得到这 10条消息,就如同订阅公众号那样。
      2. RabbitMQ(RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的消息中间件),他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。
        1. fanout:如果交换器收到消息,将会广播到所有绑定的队列上
        2. direct:如果路由键完全匹配,消息就被投递到相应的队列
        3. topic:可以使来自不同源头的消息能够到达同一个队列。 使用 topic 交换器时,可以使用通配符
      3. RocketMQ,是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。
      4. Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。Kafka的优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。因此Kafka在大数据领域中配合实时计算技术(比如Spark Streaming、Storm、Flink)使用的较多。
      5. 总结:中小型公司使用 RabbitMQ 是不错的选择,大型公司基础架构研发实力较强,用 RocketMQ 是很好的选择大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的。
    2. 设计MQ的思路
      1. 首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量
        1. 设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?
      2. mq 的数据要不要落地磁盘
        1. 肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路
      3. 考虑一下你的 mq 的可用性
        1. 具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务
  5. 这个技术的原理
    1. RabbitMQ工作模式
      1. SIMPLE模式(简单的收发模式)
        1. 消息产生消息,将消息放入队列
        2. 消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失,这里可以设置成手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出)。
      2. work工作模式(资源的竞争)
        1. 消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使用)。
      3. publish/subscribe发布订阅(共享资源)
        1. 每个消费者监听自己的队列;
        2. 生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收到消息。
  6. 这个技术的使用方式
    1. RabbitMQ 的集群
      1. 普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写操作。
      2. 镜像集群模式:这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。这样的话,好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整数据。
  7. 这个技术的常见问题
    1. 消息的顺序问题
      1. 保证生产者 - MQServer - 消费者是一对一对一的关系
      2. 拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
    2. 消息的重复问题
      1. 如果消费端收到两条一样的消息,应该怎样处理?消费端处理消息的业务逻辑保持幂等性。只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。
        1. 写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过
        2. 消费一条消息就往数据库里插入一条数据,要是你一个消息重复两次,你不就插入了两条,这数据不就错了?但是你要是消费到第二次的时候,自己判断一下是否已经消费过了,若是就直接扔了,这样不就保留了一条数据,从而保证了数据的正确性
posted @ 2020-09-16 08:19  Smileing  阅读(116)  评论(0编辑  收藏  举报