聊聊Java消息

消息在开发过程中多次用到,在分布式系统中也是高频使用的一项技术,特写该片文章以作总结。

一、消息使用场景

1.1 常见的使用场景

系统解耦

在单机系统中解耦可能无关痛痒,但是在分布式环境下,系统间的相互依赖,最终会会导致整个依赖关系混乱,对后期的拆分和优化都带来负担。
异步处理

在逻辑请求链路里,为了提高接口RT,都会对逻辑进行优化,对于非主链路上的分支逻辑,都会选择异步处理。其中比较经典的当属日志的记录,一般会选择发送消息日志,然后由日志系统异步消费并进行存储等后续处理。

数据最终一致性,通过消息来实现最终的数据同步。

异步处理也可以引来 并行处理 的使用姿势。在工作中,我们基于消息开发了一个简单的分布式任务处理组件。该组件简单分为三块分别是 切分、加载、执行三个阶段


每个阶段都是以作为消费者,然后处理完毕后再作为生产者发送消息。消息消费无状态,可以按需无限拓容。

流量削峰

由于使用消息,我们的链路变成了生产者发送消息,消息中间件存储消息,最后消费者从消息中间件拉取消息的一个过程。而消息中间件的存储能力能够有效的帮助消费者进行缓冲。试想下,正常流量下消费者能够愉快的进行消费,瞬时高峰流量来的时候,消费者消费能力跟不上,刚好阻塞在消息中间件,等峰值过后,消费者又能很快的将阻塞的消息进行消费。

1.2 消息使用的先决条件

根据上面的三个常见场景,我们可以发现,消息的介入,一般都是在非核心链路较多或者核心链路但是能容忍延迟的情况下(比如数据的最终一致性)较为合适。

二、消息相关的概念

在JMS标准中,有两种消息模型P2P(Point toPoint)和Publish/Sub(Pub/Sub)。

P2P

点对点,一个发,一个消费。涉及到的角色 发布者(Publisher)、消费者(Consumer)、消息队列(Queue)

特点:

  1. 一个消息只能被一个消费者消费,消费后会从队列里移除
  2. 发布者和消费者无关系,发布者发送消息的行为不会随消费者而改变
  3. 消费者消费完成消息,需要向队列Ack,消息队列发现消息消费成功即做消息移除

Pub/Sub


发布订阅模式,一个发布,多方订阅。涉及到的角色有 发布者(Publisher)、主题(Topic)、订阅者(Subscriber)。

特点

  1. 每个消息可以有多个消费者
  2. 针对某个主题(Topic)的订阅者,必须创建一个订阅者之后,才能消费发布者的消息
  3. 为了消费消息,订阅者必须保持运行的状态

Kafka 就是该模式的典型代表。

三、常规消息问题及解决方案

2.1 消息延迟

一般要么是大流量进入,要么是消费者延迟,基本思路就是排除业务逻辑,然后考虑是否可拓容。

案例
工作中有这样一个场景 商品根据商品变更消息来进行ES数据的新增或修改,另外一个商品分组的消息对ES的数据进行修改,由于业务上先有商品后有分组,所以分组消息的消费者只做ES更新。
不巧的时当时一个哥们在刷全网商品数据,也没做限速导致有大量的商品变更消息产生,商品消息阻塞导致ES对应的商品文档没有创建,然后分组消息消费者更新失败。当时用的还是顺序消息,所以拓容无望。

由于每次更新ES都是从db获取最新的数据并更新到ES,并不依赖消息的数据。另外更新商品最多是数据同步延迟问题,而新增的商品直接会导致ES查不到,阻塞的消息大部分都是修改的消息,所以当时我们新建消息实例,把阻塞的那批消息转移到新的实例。然后原实例消息清空继续处理新的消息。保证新消息能够不阻塞。相当于变相进行了消费者和消息 Patition两个拓容
当然用户也是有感知的,只是我们尽可能的将故障降到最低。

2.2 消息阻塞

消息阻塞一般就是突然消息增多,超过了消费者消费的能力。或者消费者出现逻辑问题,导致不断的重试或长时间等待。

该类问题一般首先要看下业务日志,缺消费是否正常。如果是消息峰值,可考虑是否拓容。当然消费逻辑问题,只能紧急修补并发布了,在修补后为了快速消费阻塞的消息队列,可考虑临时对消费者进行拓容。

2.3 重复消费

重复消费一般发生下消费端,比如消费者处理完毕,在准备进行ack的时候出现了问题,应用重启后,消息中间件以为该消息还未处理又推给了消费者,或者消费者拉取的时候重复。

一般的做法就是消费端做幂等,业务上设置一个幂等表或者用redis等用来存储消费记录,每次消费消息都先去幂等存储进行验证,如果没有消费则存入幂等记录,幂等一般会根据一个业务唯一键进行确认。

2.4 消息丢失

消息丢失一般分为生产者发送失败、消息中间件丢失、消费丢失。

生产者丢失
生产者发送消息,可能以为网络问题或者消息中间处理失败导致,消息遗漏。针对生产者如果发送是同步的自然可以进行异常捕捉并重试。如果是异步请求,一般通过发送消息的异步回调方法来实现。kafka里这两种case都能满足。

消息中间的丢失
消息中间对我们来说一般都是相对可信的,但是有时候消息中间可能为了吞吐量啥的不能保证某些特性,所以这只能根据中间的文档进行相应的配置。

案例
kafka某个broker宕机,然后重新选举partiton的leader时,要是此时其他的follower刚好还有些数据没有同步,结果此时leader挂了,然后选举某个follower成leader之后,待同步的数据就彻底丢了。

给这个topic设置replication.factor参数:这个值必须大于1,要求每个partition必须有至少2个副本
在producer端设置acks=all:这个是要求每条数据,必须是写入所有replica之后,才能认为是写成功了

消费丢失
有的消息中间件支持自动ack,当消费者消费到消息,消息中间件也不管是否消费成功自动ack。这时候一般选择消费者主动ack比较合适。

2.5 消息顺序性

消息顺序性保证,一般来通过消息中间实现。消息中间件的顺序消息其实根本上就是局部有序,一般会对消息的主体,比如用户id、商品id这些进行分区,每个partition保证自己的队列有序,两个Partition之间无顺序限制。

然后在消费的过程中,一个Partition同一时刻只能被一个消费者消费变相的同步。所以可以看出需要注意的是,为了保证业务响应需要提取估好Partition的数量,保证系统最够的并发数量。
image.png

顺序消息的消费特性,导致一旦某个消息消费阻塞或者异常会导致它所在的Partition的阻塞。

三、常见消息中间对比

RocketMQ与kafka对比

Kafka、RabbitMQ、RocketMQ消息中间件的对比 —— 消息发送性能


推荐文章
从1-7,都建议看下
https://www.cnblogs.com/daiwei1981/p/9394587.html

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

推荐阅读更多精彩内容

  • 概念:微服务就是一些可独立运行、可协同工作的小的服务。微服务是现在特别流行的服务,微服务的字面意思是大家都很好理解...
    程序员技术圈阅读 3,292评论 2 47
  • 消息中间件选型分析 有很多网友留言:公司要做消息中间件选型,该如何选?你觉得哪个比较好?消息选型的确是一个大论题,...
    消失er阅读 1,956评论 0 24
  • 1、TCP为什么需要3次握手,4次断开? “三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端...
    杰伦哎呦哎呦阅读 3,439评论 0 6
  • “ 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列...
    落羽成霜丶阅读 3,931评论 1 41
  • 成长这个词其实挺奇怪的,小的时候我们根本不清楚这个词的含义,天天盼望着快点儿长大。 长大后我们开始逃避这个词,希望...
    箱子小北阅读 251评论 0 1