分布式开发之消息队列

本文围绕如下几点进行阐述:

  1. 为什么使用消息队列?
  2. 使用消息队列有什么缺点?
  3. 消息队列如何选型?
  4. 如何保证消息队列是高可用的?
  5. 如何保证消息不被重复消费?
  6. 如何保证消费的可靠性传输?

1. 为什么使用消息队列?

解耦,异步,限流

2. 使用消息队列有什么缺点?

导致系统可用性降低,若MQ发生故障会影响系统可用性。系统复杂性增加,引入MQ会引入新的关注点,比如需要考虑消息可靠性投递,消息重复消费等问题。

3. 消息队列如何选型?

1. 看MQ更新频率

2. 看MQ性能

3. 比较MQ各自特点,比如Kafka适合大数据场景如日志采集

4. 如何保证消息队列是高可用的?

以RcoketMQ为例,他的集群就有多master 模式、多master多slave异步复制模式、多 master多slave同步双写模式。多master多slave模式部署架构图:

Rocket的高可用架构和kafka很像,只是NameServer集群,在kafka中是用zookeeper代替,都是用来保存和发现master和slave用的。通信过程如下:
Producer 与 NameServer集群中的其中一个节点(随机选择)建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Broker Master 建立长连接,且定时向 Broker 发送心跳。Producer 只能将消息发送到 Broker master,但是 Consumer 则不一样,它同时和提供 Topic 服务的 Master 和 Slave建立长连接,既可以从 Broker Master 订阅消息,也可以从 Broker Slave 订阅消息。

kafka:

如上图所示,一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer Group,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。

5. 如何保证消息不被重复消费?

其实无论是那种消息队列,造成重复消费原因其实都是类似的。正常情况下,消费者在消费消息时候,消费完毕后,会发送一个确认信息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息 队列中删除。只是不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念,简单说一下(如果还不懂,出门找一个kafka入门到精通教程),就是每一个消息都有一个offset,kafka消费过消息后,需要提交offset,让消息队列知道自己已经消费过了。那造成重复消费的原因?,就是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。

1. 利用数据库主键唯一性:全局唯一ID + 指纹码。当唯一ID插入数据库时会因为主键约束而失败,这样就能保障消息不会被重复消费。

2. 利用redis的原子性。但也有需要考虑的问题。如何消息落地。

6.如何保障消费的可靠性传输。

可靠性传输要从三个角度来分析:生产者弄丢数据、消息队列弄丢数据、消费者弄丢数据

  6.1  生产端的可靠性投递

保障消息的成功发出,保障MQ节点的成功接收,发送端收到MQ节点确认应答。完善的消息进行补偿机制。

6.1.1 解决方案

6.1.1.1  消息落库,对消息状态进行打标。

6.1.1.2  消息的延迟投递,做二次确认,回调检查。

     6.2 MQ消息队列丢数据
          处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。
    那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步
    1、将queue的持久化标识durable设置为true,则代表是一个持久的队列
    2、发送消息的时候将deliveryMode=2
  这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据

    6.3 消费者丢数据
          消费者丢数据一般是因为采用了自动确认消息模式。这种模式下,消费者会自动确认收到信息。这时RabbitMQ会立即将消息删除,这种情况下如果消费者出现异常而没能处理该消息,就会丢失该消息。
          至于解决方案,采用手动确认消息即可。

未完待续

原文地址:https://www.cnblogs.com/frank2015/p/9650981.html

时间: 2024-08-02 18:07:42

分布式开发之消息队列的相关文章

对分布式事务、消息队列的重新认识

本质上问题可以抽象为:当一个表数据更新后,怎么保证另一个表的数据也必须要更新成功.若两张表在同一个数据库实例中,则使用本地事务就好了.否则可以采用分布式事务,或者消息队列. 前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了. 上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品

redis分布式锁和消息队列

最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP等,不能在内存中使用锁,或者如Java这样的,需要一下更为简单的锁校验的时候,redis分布式锁的使用就足够满足了.redis的分布式锁其实就是基于setnx方法和redis对key可设置有效时间的功能来实现的.基本用法比较简单. public boolean tryLock(String lock

浅析腾讯云分布式高可靠消息队列服务CMQ架构

在分布式大行其道的今天,我们在系统内部.平台之间广泛运用消息中间件进行数据交换及解耦.CMQ是腾讯云内部自研基于的高可靠.强一致.可扩展分布式消息队列,在腾讯内部包括微信手机QQ业务红包.腾讯话费充值.广告订单等都有广泛使用.目前已上线腾讯云对外开放,本文对腾讯云CMQ核心技术原理进行分享介绍. CMQ消息队列主要适用于金融.交易.订单等对可靠性.可用性有较高要求的业务场景. 以腾讯充值系统为例,该充值系统通过CMQ 对交易模块.发货部分.结算系统进行异步解耦.削峰填谷,一方面大大降低了模块间耦

如何使用NODEJS+REDIS开发一个消息队列

作者: RobanLee 原创文章,转载请注明: 萝卜李 http://www.robanlee.com MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们>.消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术.排队指的是应用程序通过 队列来通信.队列的使用除去了接收和发送应用程序同时执行的要求.其

腾讯云分布式高可靠消息队列CMQ架构

版权声明:本文由张浩原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/126 来源:腾云阁 https://www.qcloud.com/community 在分布式大行其道的今天,我们在系统内部.平台之间广泛运用消息中间件进行数据交换及解耦.CMQ是腾讯云内部自研基于的高可靠.强一致.可扩展分布式消息队列,在腾讯内部包括微信手机QQ业务红包.腾讯话费充值.广告订单等都有广泛使用.目前已上线腾讯云对外开放,本文对腾讯云CM

分布式事务之消息队列一致性和幂等问题

原文链接:https://www.cnblogs.com/rjzheng/p/10115798.html 引言 这篇说说分布式事务的问题.企业现在的架构都由传统的架构转向了微服务架构,如下图所示:那么,都不可避免的会遇到跨数据库调用的,分布式事务问题!目前,业内解决分布式事务问题,都基本不用JTA这种强一致性的解决方案,基本是采用如下两套方案 基于TCC的事务框架 消息队列 OK,你们先记住两点(1)图中的服务A和服务B,如果是同步调用,要求一起成功,或者一起失败,那么此时应选用TCC的事务框架

分布式通信技术之消息队列

消息队列的基本原理 消息队列是基于队列实现的,存储具有特定格式的消息数据.消息队列包括生产者,消息队列以及消费者. RocketMQ的原理与工作机制 架构图 NameServer Cluster:名字服务器集群,类似于kafka中的zookeeper,提供分布式协调与管理的功能 Producer Cluster:生产者集群,负责接收用户数据,将数据发布到消息队列中心Broker cluster Consumer Cluster:消费者集群,负责从Broker获取消息进行消费 Broker Clu

2017.12.18 Android开发之消息队列(实现子线程修改UI组件)

1.界面布局,以及组件初始化: 组件初始化: private Button button; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button=(Button)findViewById(R.id.button)

使用NODEJS+REDIS开发一个消息队列以及定时任务处理

作者:RobanLee 原创文章,转载请注明: 萝卜李 http://www.robanlee.com 源码在这里: https://github.com/robanlee123/RobCron 时间有限,就不详细注释,有问题或者意见欢迎@我,也欢迎大家批评指正. 本文所必须的一些资料如下: 1. NODEJS ==> 可以去NODEJS.ORG下载最新的源码.2. Redis ==> Redis.io3. KUE ==> Nodejs的一个开源队列系统4. NODE-SCHEDULE