大规模数据处理实战
蔡元楠
Google Brain资深工程师
立即订阅
8443 人已学习
课程目录
已完结 46 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 从这里开始,带你走上硅谷一线系统架构师之路
免费
模块一 | 直通硅谷大规模数据处理技术 (3讲)
01 | 为什么MapReduce会被硅谷一线公司淘汰?
02 | MapReduce后谁主沉浮:怎样设计下一代数据处理技术?
03 | 大规模数据处理初体验:怎样实现大型电商热销榜?
模块二 | 实战学习大规模数据处理基本功 (8讲)
04 | 分布式系统(上):学会用服务等级协议SLA来评估你的系统
05 | 分布式系统(下):架构师不得不知的三大指标
06 | 如何区分批处理还是流处理?
07 | Workflow设计模式:让你在大规模数据世界中君临天下
08 | 发布/订阅模式:流处理架构中的瑞士军刀
09 | CAP定理:三选二,架构师必须学会的取舍
10 | Lambda架构:Twitter亿级实时数据分析架构背后的倚天剑
11 | Kappa架构:利用Kafka锻造的屠龙刀
模块三 | 抽丝剥茧剖析Apache Spark设计精髓 (10讲)
12 | 我们为什么需要Spark?
13 | 弹性分布式数据集:Spark大厦的地基(上)
14 | 弹性分布式数据集:Spark大厦的地基(下)
15 | Spark SQL:Spark数据查询的利器
16 | Spark Streaming:Spark的实时流计算API
17 | Structured Streaming:如何用DataFrame API进行实时数据分析?
18 | Word Count:从零开始运行你的第一个Spark应用
19 | 综合案例实战:处理加州房屋信息,构建线性回归模型
20 | 流处理案例实战:分析纽约市出租车载客信息
21 | 深入对比Spark与Flink:帮你系统设计两开花
模块四 | Apache Beam为何能一统江湖 (8讲)
22 | Apache Beam的前世今生
23 | 站在Google的肩膀上学习Beam编程模型
24 | PCollection:为什么Beam要如此抽象封装数据?
25 | Transform:Beam数据转换操作的抽象方法
26 | Pipeline:Beam如何抽象多步骤的数据流水线?
27 | Pipeline I/O: Beam数据中转的设计模式
28 | 如何设计创建好一个Beam Pipeline?
29 | 如何测试Beam Pipeline?
模块五 | 决战 Apache Beam 真实硅谷案例 (7讲)
30 | Apache Beam实战冲刺:Beam如何run everywhere?
31 | WordCount Beam Pipeline实战
32 | Beam Window:打通流处理的任督二脉
33 | 横看成岭侧成峰:再战Streaming WordCount
34 | Amazon热销榜Beam Pipeline实战
35 | Facebook游戏实时流处理Beam Pipeline实战(上)
36 | Facebook游戏实时流处理Beam Pipeline实战(下)
模块六 | 大规模数据处理的挑战与未来 (4讲)
37 | 5G时代,如何处理超大规模物联网数据
38 | 大规模数据处理在深度学习中如何应用?
39 | 从SQL到Streaming SQL:突破静态数据查询的次元
40 | 大规模数据处理未来之路
专栏加餐 | 特别福利 (4讲)
FAQ第一期 | 学习大规模数据处理需要什么基础?
加油站 | Practice makes perfect!
FAQ第二期 | Spark案例实战答疑
FAQ第三期 | Apache Beam基础答疑
结束语 (1讲)
结束语 | 世间所有的相遇,都是久别重逢
大规模数据处理实战
登录|注册

08 | 发布/订阅模式:流处理架构中的瑞士军刀

蔡元楠 2019-05-03
你好,我是蔡元楠。
今天我想要与你分享的是在处理大规模数据中十分流行的一种设计模式:发布 / 订阅模式(Publish/Subscribe Pattern),有些地方也称它为 Pub/Sub。
在了解发布 / 订阅模式之前,我想先简单介绍几个基础概念——消息(Message)和消息队列(Message Queue)。

消息

消息是什么呢?
在分布式架构里,架构中的各个组件(Component)需要相互联系沟通。组件可以是后台的数据库,可以是前端的浏览器,也可以是公司内部不同的服务终端(Service Endpoint)。
而各个组件间就是依靠通过发送消息互相通讯的。如下图所示。
消息可以是任意格式的。例如,我们可以利用 JSON 格式来传输一个消息,也能利用 XML 格式来传输一个消息,甚至可以使用一种自己定义的格式。

消息队列

知道了消息的含义后,你知道消息队列有什么作用吗?
消息队列在发布 / 订阅模式中起的是一个持久化缓冲(Durable Buffer)的作用。
消息的发送方可以发送任意消息至这个消息队列中,消息队列在接收到消息之后会将消息保存好,直到消息的接收方确认已经从这个队列拿到了这个消息,才会将这条消息从消息队列中删除。
有的消息系统平台如 Apache Kafka,它能够让用户自己定义消息队列对消息的保留时间,我将会在介绍 Apache Kafka 的时候讲到。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《大规模数据处理实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(46)

  • 利利
    盆友圈适合使用pub/sub模式
    原因1:消息发送方需要向多个接收方(n个可以看自己盆友圈的好友)广播消息
    原因2:多消费者组(微信朋友圈数据应该不仅仅只是用于社交,可能还有其他作用吧,所以可能会有多个模块需要用到这份数据)
    原因3:发送方发送消息之后是不需要接收方立即进行响应的(异步),所以用消息队列可以有效起到解耦的作用
    原因4:微信朋友圈对于数据而言,满足最终一致性的

    作者回复: 谢谢你的答案,观点基本我都是赞同的!

    2019-05-03
    1
    17
  • NEVER SETTLE
    老师,当今有许多很好的开源MQ,响Kafka,RabbitMQ等等,但是在看许多技术分享大会,为什么许多公司还会自己开发MQ呢?

    作者回复: 谢谢你的留言提问!个人觉得即便公司会开发自己的MQ,很多都是建立在这些开源项目之上的。一方面可能因为开源项目的一些属性并不能满足到自身的应用场景,所以加以改进。另一方面如果是大厂的话,可以打造出自己的一套生态圈,开发接口更加适合内部使用。

    2019-05-03
    9
  • J Zhang
    感觉没啥内容啊

    作者回复: 哈哈哈,感觉你的基本功很扎实啊,那这一讲你可以当作是复习章节,当然也可以留言和我讨论更高级的内容。我的专栏也希望能对初学者友好一点,对于初学者来说,这一讲是全新的内容呢。

    2019-05-05
    8
  • 大牛凯
    老师好,有一点模糊的地方,请问观察者模式和发布/订阅模式的区别从消息的传递上来看就是是否通过消息队列传递数据么?另外消息队列是对接收者push消息还是接收者主动从消息队列中pull消息出来呢?谢谢老师

    作者回复: 你好呀,感谢你的提问!

    其实在观察者模式下,你也可以通过消息队列去传递消息。但是更本质的区别是在观察者模式下,观察者必须知道被监听者的存在。就像例子所示,观察者必须调用被监听者的接口。而发布/订阅模式下,两者是解耦的,互相都不用知道对方的存在。

    消息队列中既可以使用push模式也可以使用pull模式,关键在于应用场景的考虑。例如如果消息跟新发布频繁,而下游的接收者能够处理的qps不高,那可能会更加倾向于采取pull模式。

    2019-05-03
    1
    8
  • paradox
    1. 微博粉丝订阅机制
    由于存在流量明星,针对不同情况的用户,系统可以区别对待,在线用户采用“推”模式,尽量及时更新订阅者的timeline;不在线的用户采用“拉”模式,在该用户上线后更新timeline。

    2. 微信朋友圈机制
    由于不太可能存在微博这种超级发布者,因此可仅采用“推”模式。

    3. 两款产品的共同点
    a) 发布者必须实时同步处理,因为发布成功后需要直接看到自己生产的消息。
    b) 订阅者可以异步处理,只要保证系统满足最终一致性即可。

    作者回复: 谢谢你的留言!总结得很到位啊!

    2019-05-05
    6
  • Chn.K
    log offset类似tcp的滑动窗口机制,有个问题:如例子讲的10003,在第一次由于某种原因未被消费者消费,生产者又发了一次10003,然后第一次发送的10003又到了消费者,那么10003会被消费者消费两次,这种情况kafka会有什么处理机制吗?

    作者回复: 谢谢你的留言提问!一般来说,这种发送机制叫做at least once delivery,这种情况需要消费者自身具备Idempotency,也就是幂等性。消费者需要自己知道哪些消息是duplicate的,从而知道怎么处理这些重复消息。

    2019-05-06
    1
    4
  • 每天晒白牙
    微信朋友圈适合用消息发布-订阅模式
    1.系统的发送方需要向大量的接收方广播消息。一个人打朋友圈,需要向有好友关系的多方发消息

    2.朋友圈的数据会被多个独立的业务方使用,比如做数据分析用于投放朋友圈广告,进行用户行为分析,构建用户画像

    3.系统的发送方在向接收方发送消息之后无需接收方进行实时响应。因为朋友圈这种业务应该使用pull模式,当A发朋友圈时,A的好友B C D,只有当B C D进行刷新朋友圈时,会去pull数据

    4.朋友圈对数据一致性只会要求最终一致性

    所以朋友圈很适合消息发布-订阅模式

    作者回复: 谢谢你的答案!分析得很详细,基本上我都是赞同的!

    2019-05-03
    4
  • 潘腾
    如果微信朋友圈使用发布订阅模式的话,那么是不是意味着每一个用户对应一个消息队列呢,那这样的话是不是就得有好几亿消息队列?

    作者回复: 谢谢你的提问!这个看你的设计了,即便真的使用发布订阅模式的话,同一个队列的消费者可以通过设置filter来只接收自己感兴趣的内容。

    2019-07-27
    1
    2
  • John
    請問老師 如果想把Oracle的數據實時同步到其他的地方比如MongoDB 要求幾秒鐘以內的latency 有沒有辦法使用pubsub的概念做到呢 又該如何做呢 謝謝

    作者回复: 谢谢你的提问!这个问题挺常见的,PubSub肯定是可以做到的。具体的做法还是看你的架构吧。如果你是own整一套系统的话,一种做法是你的service直接对这两个数据库进行dual write。如果你只是own这两个database的话,我相信Oracle应该是有一些database change notification的机制,这个时候你可以将这个data change publish到一个service中,然后再做同步。

    2019-07-05
    2
  • cl
    如果接收方读取数据之后回应消息队列它接收的 Log offset 是 10000、10001 和 10003,那么消息队列就会认为接收方最多只接收了消息 10000 和 10001,剩下的消息 10002、10003 和 10004 则会继续发送给接收方,直到接收方回应接收了消息 10002、10003 和 10004。
    第一句接收的log offset有10003吗?

    作者回复: 谢谢你的提问!如果我没理解错你的问题的话,你是想问接收方是否回复了10000、10001和10003这三个Log offset对吧?是的,接收的log offset有10003。因为消息队列需要接收到连续的log offset才会判定接收方接收到消息,这里因为log offset从10002断开了,所以消息队列会认为接收方从10002开始往后的消息都没有接收到。

    2019-05-09
    1
    2
  • 老师好,对于消息队列中的消息存储有一个问题。在一个发布订阅模式下的消息队列中消息会被保存多久呢?具体情景是如果有五个接收方订阅了一个队列的消息,其中四个成功接收了,第五个总也无法接收,这条消息会一直保存在队列中,并且不断尝试发给第五个订阅者吗?还是会设置最多重复次数?另一个情景,在发布者发送消息至队列后,新增加了一个订阅者,这时新的订阅者可以收到队列里已放入的消息吗?谢谢。

    作者回复: 涵你好,谢谢你的留言与提问!

    第一个问题,一般不同的系统有不同的机制去确定消息队列中消息会被保存多久。像Apache Kafka中可以通过设定Retention Period来确定消息被保存多久,甚至可以设置Retention Period为Forever来永久保存。

    第二个问题,只要没有超过保留期,消息会一直保存在队列并且一直尝试发送给第五个订阅者。当然订阅者也可以自己设定retry times,如果第五个订阅者告诉消息队列只需要重试一次,那这条消息就不会再发送给第五个订阅者了。如果你要保证操作一定成功,就要考虑用RPC来调用了。

    第三个问题还是要看系统设计了,设计上收到与不收到都可以做到,像Apache Kafka可以通过重设Log Offset的位置去实现新的订阅者收取队列里面旧的消息。如果你使用开源项目的话,文档里应该会有说明的。

    2019-05-04
    2
  • 川杰
    老师您好,个人理解,观察者模式本质上是消息推出,订阅该消息的对象获取消息并进行处理;所以我认为,发布/订阅模式其实是一种特殊的观察者模式,或者是观察者模式的实现方式。

    作者回复: 谢谢你的留言!我觉得本质上还是有所不同的,毕竟在观察者模式中观察者需要知道被监听的对象,而发布/订阅模式通过消息队列解耦了这一层关系。

    2019-05-03
    2
  • JohnT3e
    适合,1. 场景对实时性要求不高;2. 用户自己可以刷新拉取;

    作者回复: 谢谢你的答案!

    2019-05-03
    1
  • wong ka seng
    老师好!
    "发布 / 订阅模式指的是消息的发送方可以将消息异步地发送给一个系统中不同组件,而无需知道接收方是谁。" => 那麽BROWSER探访网站伺服器这个情况, 算不算发布 / 订阅模式?
    2019-08-04
  • Geek_fengchen
    有顺序的
    2019-07-05
  • 小乙哥
    文中提到kafka的log offset的例子,应该是争对某个topic下的partition吧?不是说整个topic吧?一个topic下会有多个partition,每个partition都有各自的log offset
    2019-07-02
  • 滩涂曳尾
    学习心得:

    消息队列有2个重点:
    1. 解耦合——vs. 观察者模式实现相同效果,而且每次都要和观察者协商消息格式)
    2. 高伸缩性——消息队列可以作为一个“独立”的“分布式存储”,专业团队维护。

    apache kafka: Producer -> topics -> Consumer

    发布/订阅模式限制:
    1. 发送之后,无法做到接收方实时响应;
    2. 只能满足“最终一致性,不能满足强一致性” (知乎有篇文章很好:https://zhuanlan.zhihu.com/p/67949045)

    作者回复: 谢谢你的留言和分享!总结得不错啊!

    2019-06-29
  • funnycrab
    我上交学长就是厉害 课程形象生动 易于理解!

    指出一个小typo,
    “在了解了消息和消息队列后,现在我想和你正式地向你介绍...”
    应为
    “在了解了消息和消息队列后,现在我想和你正式地介绍...”
    或者
    “在了解了消息和消息队列后,现在我想正式地向你介绍...”

    作者回复: 啊哈哈,谢谢你的支持啊,同时也谢谢你的建议!

    2019-06-23
  • 西北偏北
    消息队列用于解耦多个系统之间的通信。特别是一对多的通信。假设a系统要发消息给b和c 如果没有消息队列,a系统需要实现对b和c发送的机制,考虑消息丢失的问题,考虑消息过大时的并发和容错问题。


    引入消息队列后,a只需跟消息队列大交道,消息队列一般实现了消息的可靠性送达,高并发下的数据集群服务。

    作者回复: 谢谢留言!总结得不错啊!不过消息队列也不一定是可靠性送达的,在一些极端的情况下也是有可能出现丢包。

    2019-06-22
  • 夷,这也可以
    蔡老师好!朋友圈消息从重要功能来说
    1、消息需要发送给多个可见用户
    2、消息不需要实时响应,接收用户需要时再拉去(消费)
    3、只需最晚一致性即可
    至于其他地方使用这个可能会有。所以可以使用消息队列。
    可能老师就这个例子是为了说明什么时候应该用消息队列,让大家理解和思考。
    我这有疑问就是实际开发中,
    1可能是有个一个topic用来交互朋友圈的消息。
    2消息内容是这条消息的发送者和消息的接受者有哪些人及其他时间和空间附加信息。
    3整个朋友圈的信息只有一个topic 。
    这种情况在消息发送和消息处理不在一个模块时是可以的,而如果是在同一个模块,多线程异步处理就可以了。实际生产中不可能说为每个用户建立一个topic,然后一个人的消息发送给朋友圈的每个用户的topic。这是不合理的!
    所以我感觉消息队列更多的还是模块和模块之间有1对多或者多对多关系而又不关心实时响应时使用。可能说的比较乱啊
    2019-06-16
收起评论
46
返回
顶部