MQ消息队列使用进阶大全

使用Mq有哪些优点?

  • 解耦:A系统依赖B,C,D系统,A只需要发送topic,B,C,D后期不需要消息自行取消消费即可,类似消息总线
  • 异步:异步执行消息发送,通知等
  • 消峰:应对突发的流量高峰时段(错峰与流控)
  • 复用:一次发送多次消费

使用Mq有哪些缺点?

  • 系统复杂度提高
  • 系统可用性降低

Mq怎么选型,各个Mq中间件的优缺点?

  • 开源产品,市场任何度
  • 消息可靠性
  • 跨语言支持
  • 性能
  • 功能
image

使用Mq会带来哪些问题?

一致性问题

使用可靠消息最终一致性的分布式事务方案来保障

消息顺序问题

一笔订单产生了3条消息,分别是订单创建、订单付款、订单完成。消费时,要按照顺序依次消费才有意义

出现原因:

  • 一个queue,有多个consumer去消费。因为每个consumer的执行时间是不固定的,先读到消息的consumer不一定先完成操作
  • 一个queue对应一个consumer,但是consumer里面进行了多线程消费,这样也会造成消息消费顺序错误

解决:

  • 有关联的同一组消息1、2、3发到queue1中,然后消费者1消费,因为消息队列本来就是有序的,所以这样就有序。为了提高性能,搞多个queue,有关联的同一组消息发到同一队列,每个队列都有唯一的消费者
  • 一个queue但是对应一个consumer,然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理。原理和上面一样,都是保证同一组消息发给同一队列,然后被同一消费者消费
  • 既然要求“同一组消息发给同一队列,然后被同一消费者消费”,那最好的办法是把同一组消息合并成一条。这样性能更好,无论多线程、还是多消费者都ok。
    有人可能说合并后会不会数据量太大?
    大多数场景都不要求顺序执行。比如电商支付完后需要:App推送、短信推送、加积分、给仓库发发货的消息、修改购物推荐;比如支付宝抢红包,先抢到的不要求先到账。

总结:涉及到发送方集群,mq集群,接收方集群

  • 保证发送方是顺序发送
  • 保证同一个唯一标识(订单号)只发送到指定Mq Server上
  • 保证同一个唯一标识(订单号)只在一个接收方节点上消费

消息堆积问题

  • 临时扩容,以更快的速度去消费数据了,先修复consumer的问题,确保其恢复消费速度,然后将现有consumer都停掉。临时建立好原先10倍或者20倍的queue数量(新建一个topic,partition是原来的10倍)。然后写一个临时分发消息的consumer程序,这个程序部署上去消费积压的消息,消费之后不做耗时处理,直接均匀轮询写入临时建好分10数量的queue里面。紧接着征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的消息。
    这种做法相当于临时将queue资源和consumer资源扩大10倍,以正常速度的10倍来消费消
    等快速消费完了之后,恢复原来的部署架构,重新用原来的consumer机器来消费消息


    image
  • 临时写个程序,连接到mq里面消费数据,收到消息之后直接存redis,后续重发
  • mq完全放不下,快挂了,写个程序,连接到mq里面消费数据,收到消息之后直接将其丢弃,快速消费掉积压的消息,降低MQ的压力,然后走第二种方案
  • 堆积引起的丢失,高峰期过后手动去查询丢失的那部分数据,然后将消息重新发送到mq里面,把丢失的数据重新补回来

消息重复发送问题(消息幂等性)

uuid-redis,唯一索引,状态机判断

消息丢失问题

  • rabbitMq
生产者:
开启confirm模式(异步),写的消息都会分配一个唯一的id,rabbitmq会给你回传一个ack消息

mq server:
queue持久化,可以保证rabbitmq持久化queue的元数据,但是不会持久化queue里面的数据
deliveryMode设置为2,这样消息就会被设为持久化方式,此时rabbitmq就会将消息持久化到磁盘上。
就算是在持久化之前rabbitmq挂了,数据丢了,生产者收不到ack回调也会进行消息重发

消费者:
使用rabbitmq提供的ack机制,首先关闭rabbitmq的自动ack,然后每次在确保处理完这个消息之后,
在代码里手动调用ack。这样就可以避免消息还没有处理完就ack
  • kafka
消费者:
关闭自动提交offset,在自己处理完毕之后手动提交offset,这样就不会丢失数据。

mq server:
一般要求设置4个参数来保证消息不丢失:
给topic设置 replication.factor参数:这个值必须大于1,要求每个partition必须至少有2个副本。
在kafka服务端设置min.isync.replicas参数:这个值必须大于1, 要求一个leader至少感知到有至少一个follower
在跟自己保持联系正常同步数据,这样才能保证leader挂了之后还有一个follower。
在生产者端设置acks=all:表示要求每条每条数据,必须是写入所有replica副本之后,才能认为是写入成功了
在生产者端设置retries=MAX(很大的一个值,表示无限重试):表示 这个是要求一旦写入事变,就无限重试

生产者:
如果按照上面设置了ack=all,则一定不会丢失数据,要求是,你的leader接收到消息,
所有的follower都同步到了消息之后,才认为本次写成功了。如果没满足这个条件,
生产者会自动不断的重试,重试无限次

Mq集群方式

  • rabbitMq
  1. 单机模式
  2. 普通集群 每次写消息到queue的时候,都会自动把消息到多个queue里进行消息同步,每个节点都有queue队列的元数据,还需要去对应节点拉数据再返回
  3. 镜像集群模式 每次写消息到queue的时候,都会自动把消息到多个queue里进行消息同步,每个节点都有queue队列的完整数据
  • kafka
  1. 多个broker组成,一个broker是一个节点;你创建一个topic,这个topic可以划分成多个partition,每个partition可以存在于不同的broker上面,每个partition存放一部分数据。这是天然的分布式消息队列

Mq知识点

数据交互模式:

Push(推模式)、Pull(拉模式)

push更关注实时性,pull更关注消费者消费能力

推模式指的是客户端与服务端建立好网络长连接,服务方有相关数据,直接通过长连接通道推送到客户端。其优点是及时,一旦有数据变更,客户端立马能感知到;另外对客户端来说逻辑简单,不需要关心有无数据这些逻辑处理。缺点是不知道客户端的数据消费能力,可能导致数据积压在客户端,来不及处理。

拉模式指的是客户端主动向服务端发出请求,拉取相关数据。其优点是此过程由客户端发起请求,故不存在推模式中数据积压的问题。缺点是可能不够及时,对客户端来说需要考虑数据拉取相关逻辑,何时去拉,拉的频率怎么控制等等。

拉模式中,为了保证消息消费的实时性,采取了长轮询消息服务器拉取消息的方式。每隔一定时间,客户端想服务端发起一次请求,服务端有数据就返回数据,服务端如果此时没有数据,保持连接。等到有数据返回(相当于一种push),或者超时返回。长轮询Pull的好处就是可以减少无效请求,保证消息的实时性,又不会造成客户端积压。

推模式是最常用的,但是有些情况下推模式并不适用的,比如说:
由于某些限制,消费者在某个条件成立时才能消费消息
需要批量拉取消息进行处理

rabbitMq推模式实现SimpleMessageListenerContainer 拉模式:basicGet

消费关系处理

  • 单播,就是点到点
  • 广播,是一点对多点,一个生产者,对应对个消费者消费-发布订阅Publish\Subscribe

为了实现广播功能,我们必须要维护消费关系,通常消息队列本身不维护消费订阅关系,可以利用zookeeper等成熟的系统维护消费关系,在消费关系发生变化时下发通知

rabbitMq

image
工作模式
Exchange有常见以下3种类型:
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:组播,定向,把消息交给符合指定routing key 的队列
Topic:规则播,通配符,把消息交给符合routing pattern(路由模式) 的队列
Header

1、简单模式 HelloWorld
一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)

2、工作队列模式 Work Queue
一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)

3、发布订阅模式 Publish/subscribe--对应广播-消息总线
需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列

4、路由模式 Routing
需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

5、通配符模式 Topic
需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式的routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列

优点:

  • 消费方可以选择消费方式为pull或者是broker主动push
  • 支持的消费模式也有多种,点对点,广播,正则匹配,订阅发布
  • 消息需要通过复杂的路由到消费者
  • 性能20k/sec

缺点:

  • 吞吐量不高,分布式弱

Kafka

image

image

image
Kafka是一种高吞吐量的分布式发布订阅消息系统,使用Scala编写。默认端口9092
依赖zk,每个topic里面都有一个leader,topic,leader信息存zk。
每个分区是有顺序性,可以将一类,比如某个人的订单hash到同一分区(就可以保证顺序性,可以制定某个key来hash)
Topic一种逻辑分类的概念到不同的分区(类似queue),消息不会删除,默认8天自动删除
一个分区对应一个消费者,单播
可以用消费组来实现多播,1个分区对应多个消费组
备份因子:必须小于等于节点数
kafka选举原理:就是利用zk临时节点,断开即删除,
然后flower监听watcher的副节点有变化就重新创建一个临时节点,谁建成功谁就是leader

优点:

  • 从A系统到B系统的消息没有复杂的传递规则,并且具有较高的吞吐量要求。性能100k/sec
  • 需要访问消息的历史记录的场景,因为kafak是持久化消息的,所以可以通过偏移量访问到那些已经被消费的消息
  • 流处理的场景。处理源源不断的流式消息
  • 高性能原因:集群。消息是顺序存磁盘(比随机内存性能高)。消息消费不需要ack删除消息。全异步

缺点:

  • 客户端发送一条消息的时候,Kafka并不会立即发送出去,先攒一波再一起处理,Kafka 不太适合在线业务场景

自己设计一个Mq需要考虑哪些东西?

  • 优先级队列,延迟队列,死性队列,重试队列
  • 消息回踪,消息丢失
  • 跨语言,安全机制,多协议支持
  • 消费模式
  • 消费关系处理
  • 可以参考Pulsar,存储和计算分离的设计

参考:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 夜莺2517阅读 127,709评论 1 9
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,520评论 28 53
  • 兔子虽然是枚小硕 但学校的硕士四人寝不够 就被分到了博士楼里 两人一间 在学校的最西边 靠山 兔子的室友身体不好 ...
    待业的兔子阅读 2,583评论 2 9
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,178评论 4 8