自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MQ的那些破事兒,你不好奇嗎?

開(kāi)發(fā) 開(kāi)發(fā)工具
最近mq越來(lái)越火,很多公司在用,很多人在用,其重要性不言而喻。本篇從三個(gè)方面講解關(guān)于mq的相關(guān)知識(shí)。

[[397434]]

前言

最近mq越來(lái)越火,很多公司在用,很多人在用,其重要性不言而喻。但是如果我讓你回答下面的這些問(wèn)題:

  1. 我們?yōu)槭裁匆胢q?
  2. 引入mq會(huì)多哪些問(wèn)題?
  3. 如何解決這些問(wèn)題?

你心中是否有答案了呢?本文將會(huì)一一為你解答,這些看似平常卻很有意義的問(wèn)題。

1 傳統(tǒng)模式有哪些痛點(diǎn)?

1.1 痛點(diǎn)1

有些復(fù)雜的業(yè)務(wù)系統(tǒng),一次用戶請(qǐng)求可能會(huì)同步調(diào)用N個(gè)系統(tǒng)的接口,需要等待所有的接口都返回了,才能真正的獲取執(zhí)行結(jié)果。

這種同步接口調(diào)用的方式總耗時(shí)比較長(zhǎng),非常影響用戶的體驗(yàn),特別是在網(wǎng)絡(luò)不穩(wěn)定的情況下,極容易出現(xiàn)接口超時(shí)問(wèn)題。

1.2 痛點(diǎn)2

很多復(fù)雜的業(yè)務(wù)系統(tǒng),一般都會(huì)拆分成多個(gè)子系統(tǒng)。我們?cè)谶@里以用戶下單為例,請(qǐng)求會(huì)先通過(guò)訂單系統(tǒng),然后分別調(diào)用:支付系統(tǒng)、庫(kù)存系統(tǒng)、積分系統(tǒng) 和 物流系統(tǒng)。

系統(tǒng)之間耦合性太高,如果調(diào)用的任何一個(gè)子系統(tǒng)出現(xiàn)異常,整個(gè)請(qǐng)求都會(huì)異常,對(duì)系統(tǒng)的穩(wěn)定性非常不利。

1.3 痛點(diǎn)3

有時(shí)候?yàn)榱宋脩?,我們?huì)搞一些活動(dòng),比如秒殺等。

如果用戶少還好,不會(huì)影響系統(tǒng)的穩(wěn)定性。但如果用戶突增,一時(shí)間所有的請(qǐng)求都到數(shù)據(jù)庫(kù),可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)無(wú)法承受這么大的壓力,響應(yīng)變慢或者直接掛掉。

對(duì)于這種突然出現(xiàn)的請(qǐng)求峰值,無(wú)法保證系統(tǒng)的穩(wěn)定性。

2 為什么要用mq?

對(duì)于上面?zhèn)鹘y(tǒng)模式的三類(lèi)問(wèn)題,我們使用mq就能輕松解決。

2.1 異步

對(duì)于痛點(diǎn)1:同步接口調(diào)用導(dǎo)致響應(yīng)時(shí)間長(zhǎng)的問(wèn)題,使用mq之后,將同步調(diào)用改成異步,能夠顯著減少系統(tǒng)響應(yīng)時(shí)間。

系統(tǒng)A作為消息的生產(chǎn)者,在完成本職工作后,就能直接返回結(jié)果了。而無(wú)需等待消息消費(fèi)者的返回,它們最終會(huì)獨(dú)立完成所有的業(yè)務(wù)功能。

這樣能避免總耗時(shí)比較長(zhǎng),從而影響用戶的體驗(yàn)的問(wèn)題。

2.2 解耦

對(duì)于痛點(diǎn)2:子系統(tǒng)間耦合性太大的問(wèn)題,使用mq之后,我們只需要依賴(lài)于mq,避免了各個(gè)子系統(tǒng)間的強(qiáng)依賴(lài)問(wèn)題。

訂單系統(tǒng)作為消息生產(chǎn)者,保證它自己沒(méi)有異常即可,不會(huì)受到支付系統(tǒng)等業(yè)務(wù)子系統(tǒng)的異常影響,并且各個(gè)消費(fèi)者業(yè)務(wù)子系統(tǒng)之間,也互不影響。

這樣就把之前復(fù)雜的業(yè)務(wù)子系統(tǒng)的依賴(lài)關(guān)系,轉(zhuǎn)換為只依賴(lài)于mq的簡(jiǎn)單依賴(lài),從而顯著的降低了系統(tǒng)間的耦合度。

2.3 消峰

對(duì)于痛點(diǎn)3:由于突然出現(xiàn)的請(qǐng)求峰值,導(dǎo)致系統(tǒng)不穩(wěn)定的問(wèn)題。使用mq后,能夠起到消峰的作用。

訂單系統(tǒng)接收到用戶請(qǐng)求之后,將請(qǐng)求直接發(fā)送到mq,然后訂單消費(fèi)者從mq中消費(fèi)消息,做寫(xiě)庫(kù)操作。如果出現(xiàn)請(qǐng)求峰值的情況,由于消費(fèi)者的消費(fèi)能力有限,會(huì)按照自己的節(jié)奏來(lái)消費(fèi)消息,多的請(qǐng)求不處理,保留在mq的隊(duì)列中,不會(huì)對(duì)系統(tǒng)的穩(wěn)定性造成影響。

3 引入mq會(huì)多哪些問(wèn)題?

引入mq后讓我們子系統(tǒng)間耦合性降低了,異步處理機(jī)制減少了系統(tǒng)的響應(yīng)時(shí)間,同時(shí)能夠有效的應(yīng)對(duì)請(qǐng)求峰值問(wèn)題,提升系統(tǒng)的穩(wěn)定性。

但是,引入mq同時(shí)也會(huì)帶來(lái)一些問(wèn)題。

3.1 重復(fù)消息

問(wèn)題重復(fù)消費(fèi)問(wèn)題可以說(shuō)是mq中普遍存在的問(wèn)題,不管你用哪種mq都無(wú)法避免。

有哪些場(chǎng)景會(huì)出現(xiàn)重復(fù)的消息呢?

  1. 消息生產(chǎn)者產(chǎn)生了重復(fù)的消息
  2. kafka和rocketmq的offset被回調(diào)了
  3. 消息消費(fèi)者確認(rèn)失敗
  4. 消息消費(fèi)者確認(rèn)時(shí)超時(shí)了
  5. 業(yè)務(wù)系統(tǒng)主動(dòng)發(fā)起重試

如果重復(fù)消息不做正確的處理,會(huì)對(duì)業(yè)務(wù)造成很大的影響,產(chǎn)生重復(fù)的數(shù)據(jù),或者導(dǎo)致數(shù)據(jù)異常,比如會(huì)員系統(tǒng)多開(kāi)通了一個(gè)月的會(huì)員。

3.2 數(shù)據(jù)一致性問(wèn)題

很多時(shí)候,如果mq的消費(fèi)者業(yè)務(wù)處理異常的話,就會(huì)出現(xiàn)數(shù)據(jù)一致性問(wèn)題。比如:一個(gè)完整的業(yè)務(wù)流程是,下單成功之后,送100個(gè)積分。下單寫(xiě)庫(kù)了,但是消息消費(fèi)者在送積分的時(shí)候失敗了,就會(huì)造成數(shù)據(jù)不一致的情況,即該業(yè)務(wù)流程的部分?jǐn)?shù)據(jù)寫(xiě)庫(kù)了,另外一部分沒(méi)有寫(xiě)庫(kù)。

 

如果下單和送積分在同一個(gè)事務(wù)中,要么同時(shí)成功,要么同時(shí)失敗,是不會(huì)出現(xiàn)數(shù)據(jù)一致性問(wèn)題的。

但由于跨系統(tǒng)調(diào)用,為了性能考慮,一般不會(huì)使用強(qiáng)一致性的方案,而改成達(dá)成最終一致性即可。

3.3 消息丟失問(wèn)題

同樣消息丟失問(wèn)題,也是mq中普遍存在的問(wèn)題,不管你用哪種mq都無(wú)法避免。

有哪些場(chǎng)景會(huì)出現(xiàn)消息丟失問(wèn)題呢?

  1. 消息生產(chǎn)者發(fā)生消息時(shí),由于網(wǎng)絡(luò)原因,發(fā)生到mq失敗了。
  2. mq服務(wù)器持久化時(shí),磁盤(pán)出現(xiàn)異常
  3. kafka和rocketmq的offset被回調(diào)時(shí),略過(guò)了很多消息。
  4. 消息消費(fèi)者剛讀取消息,已經(jīng)ack確認(rèn)了,但業(yè)務(wù)還沒(méi)處理完,服務(wù)就被重啟了。

導(dǎo)致消息丟失問(wèn)題的原因挺多的,生產(chǎn)者、mq服務(wù)器、消費(fèi)者 都有可能產(chǎn)生問(wèn)題,我在這里就不一一列舉了。最終的結(jié)果會(huì)導(dǎo)致消費(fèi)者無(wú)法正確的處理消息,而導(dǎo)致數(shù)據(jù)不一致的情況。

3.4 消息順序問(wèn)題

有些業(yè)務(wù)數(shù)據(jù)是有狀態(tài)的,比如訂單有:下單、支付、完成、退貨等狀態(tài),如果訂單數(shù)據(jù)作為消息體,就會(huì)涉及順序問(wèn)題了。如果消費(fèi)者收到同一個(gè)訂單的兩條消息,第一條消息的狀態(tài)是下單,第二條消息的狀態(tài)是支付,這是沒(méi)問(wèn)題的。但如果第一條消息的狀態(tài)是支付,第二條消息的狀態(tài)是下單就會(huì)有問(wèn)題了,沒(méi)有下單就先支付了?

消息順序問(wèn)題是一個(gè)非常棘手的問(wèn)題,比如:

  • kafka同一個(gè)partition中能保證順序,但是不同的partition無(wú)法保證順序。
  • rabbitmq的同一個(gè)queue能夠保證順序,但是如果多個(gè)消費(fèi)者同一個(gè)queue也會(huì)有順序問(wèn)題。

如果消費(fèi)者使用多線程消費(fèi)消息,也無(wú)法保證順序。

如果消費(fèi)消息時(shí)同一個(gè)訂單的多條消息中,中間的一條消息出現(xiàn)異常情況,順序?qū)?huì)被打亂。

還有如果生產(chǎn)者發(fā)送到mq中的路由規(guī)則,跟消費(fèi)者不一樣,也無(wú)法保證順序。

3.5 消息堆積

如果消息消費(fèi)者讀取消息的速度,能夠跟上消息生產(chǎn)者的節(jié)奏,那么整套mq機(jī)制就能發(fā)揮最大作用。但是很多時(shí)候,由于某些批處理,或者其他原因,導(dǎo)致消息消費(fèi)的速度小于生產(chǎn)的速度。這樣會(huì)直接導(dǎo)致消息堆積問(wèn)題,從而影響業(yè)務(wù)功能。

 

這里以下單開(kāi)通會(huì)員為例,如果消息出現(xiàn)堆積,會(huì)導(dǎo)致用戶下單之后,很久之后才能變成會(huì)員,這種情況肯定會(huì)引起大量用戶投訴。

3.6 系統(tǒng)復(fù)雜度提升

這里說(shuō)的系統(tǒng)復(fù)雜度和系統(tǒng)耦合性是不一樣的,比如以前只有:系統(tǒng)A、系統(tǒng)B和系統(tǒng)C 這三個(gè)系統(tǒng),現(xiàn)在引入mq之后,你除了需要關(guān)注前面三個(gè)系統(tǒng)之外,還需要關(guān)注mq服務(wù),需要關(guān)注的點(diǎn)越多,系統(tǒng)的復(fù)雜度越高。

mq的機(jī)制需要:生產(chǎn)者、mq服務(wù)器、消費(fèi)者。

有一定的學(xué)習(xí)成本,需要額外部署mq服務(wù)器,而且有些mq比如:rocketmq,功能非常強(qiáng)大,用法有點(diǎn)復(fù)雜,如果使用不好,會(huì)出現(xiàn)很多問(wèn)題。有些問(wèn)題,不像接口調(diào)用那么容易排查,從而導(dǎo)致系統(tǒng)的復(fù)雜度提升了。

4 如何解決這些問(wèn)題?

mq是一種趨勢(shì),總體來(lái)說(shuō)對(duì)我們的系統(tǒng)是利大于弊的,難道因?yàn)樗鼤?huì)出現(xiàn)一些問(wèn)題,我們就不用它了?

那么我們要如何解決這些問(wèn)題呢?

4.1 重復(fù)消息問(wèn)題

不管是由于生產(chǎn)者產(chǎn)生的重復(fù)消息,還是由于消費(fèi)者導(dǎo)致的重復(fù)消息,我們都可以在消費(fèi)者中這個(gè)問(wèn)題。

這就要求消費(fèi)者在做業(yè)務(wù)處理時(shí),要做冪等設(shè)計(jì),如果有不知道如何設(shè)計(jì)的朋友,可以參考《高并發(fā)下如何保證接口的冪等性?》,里面介紹得非常詳情。

在這里我推薦增加一張消費(fèi)消息表,來(lái)解決mq的這類(lèi)問(wèn)題。消費(fèi)消息表中,使用messageId做唯一索引,在處理業(yè)務(wù)邏輯之前,先根據(jù)messageId查詢(xún)一下該消息有沒(méi)有處理過(guò),如果已經(jīng)處理過(guò)了則直接返回成功,如果沒(méi)有處理過(guò),則繼續(xù)做業(yè)務(wù)處理。

4.2 數(shù)據(jù)一致性問(wèn)題

我們都知道數(shù)據(jù)一致性分為:

  • 強(qiáng)一致性
  • 弱一致性
  • 最終一致性

而mq為了性能考慮使用的是最終一致性,那么必定會(huì)出現(xiàn)數(shù)據(jù)不一致的問(wèn)題。這類(lèi)問(wèn)題大概率是因?yàn)橄M(fèi)者讀取消息后,業(yè)務(wù)邏輯處理失敗導(dǎo)致的,這時(shí)候可以增加重試機(jī)制。

重試分為:同步重試 和 異步重試。

有些消息量比較小的業(yè)務(wù)場(chǎng)景,可以采用同步重試,在消費(fèi)消息時(shí)如果處理失敗,立刻重試3-5次,如何還是失敗,則寫(xiě)入到記錄表中。但如果消息量比較大,則不建議使用這種方式,因?yàn)槿绻霈F(xiàn)網(wǎng)絡(luò)異常,可能會(huì)導(dǎo)致大量的消息不斷重試,影響消息讀取速度,造成消息堆積。

而消息量比較大的業(yè)務(wù)場(chǎng)景,建議采用異步重試,在消費(fèi)者處理失敗之后,立刻寫(xiě)入重試表,有個(gè)job專(zhuān)門(mén)定時(shí)重試。

還有一種做法是,如果消費(fèi)失敗,自己給同一個(gè)topic發(fā)一條消息,在后面的某個(gè)時(shí)間點(diǎn),自己又會(huì)消費(fèi)到那條消息,起到了重試的效果。如果對(duì)消息順序要求不高的場(chǎng)景,可以使用這種方式。

4.3 消息丟失問(wèn)題

不管你是否承認(rèn)有時(shí)候消息真的會(huì)丟,即使這種概率非常小,也會(huì)對(duì)業(yè)務(wù)有影響。生產(chǎn)者、mq服務(wù)器、消費(fèi)者都有可能會(huì)導(dǎo)致消息丟失的問(wèn)題。

為了解決這個(gè)問(wèn)題,我們可以增加一張消息發(fā)送表,當(dāng)生產(chǎn)者發(fā)完消息之后,會(huì)往該表中寫(xiě)入一條數(shù)據(jù),狀態(tài)status標(biāo)記為待確認(rèn)。如果消費(fèi)者讀取消息之后,調(diào)用生產(chǎn)者的api更新該消息的status為已確認(rèn)。有個(gè)job,每隔一段時(shí)間檢查一次消息發(fā)送表,如果5分鐘(這個(gè)時(shí)間可以根據(jù)實(shí)際情況來(lái)定)后還有狀態(tài)是待確認(rèn)的消息,則認(rèn)為該消息已經(jīng)丟失了,重新發(fā)條消息。

這樣不管是由于生產(chǎn)者、mq服務(wù)器、還是消費(fèi)者導(dǎo)致的消息丟失問(wèn)題,job都會(huì)重新發(fā)消息。

4.4 消息順序問(wèn)題

消息順序問(wèn)題是我們非常常見(jiàn)的問(wèn)題,我們以kafka消費(fèi)訂單消息為例。訂單有:下單、支付、完成、退貨等狀態(tài),這些狀態(tài)是有先后順序的,如果順序錯(cuò)了會(huì)導(dǎo)致業(yè)務(wù)異常。

解決這類(lèi)問(wèn)題之前,我們先確認(rèn)一下,消費(fèi)者是否真的需要知道中間狀態(tài),只知道最終狀態(tài)行不行?

其實(shí)很多時(shí)候,我真的需要知道的是最終狀態(tài),這時(shí)可以把流程優(yōu)化一下:

這種方式可以解決大部分的消息順序問(wèn)題。

但如果真的有需要保證消息順序的需求。訂單號(hào)路由到不同的partition,同一個(gè)訂單號(hào)的消息,每次到發(fā)到同一個(gè)partition。

 

4.5 消息堆積

如果消費(fèi)者消費(fèi)消息的速度小于生產(chǎn)者生產(chǎn)消息的速度,將會(huì)出現(xiàn)消息堆積問(wèn)題。其實(shí)這類(lèi)問(wèn)題產(chǎn)生的原因很多,如果你想進(jìn)一步了解,可以看看我的另一篇文章《我用kafka兩年踩過(guò)的一些非比尋常的坑》。

那么消息堆積問(wèn)題該如何解決呢?

這個(gè)要看消息是否需要保證順序。

如果不需要保證順序,可以讀取消息之后用多線程處理業(yè)務(wù)邏輯。

這樣就能增加業(yè)務(wù)邏輯處理速度,解決消息堆積問(wèn)題。但是線程池的核心線程數(shù)和最大線程數(shù)需要合理配置,不然可能會(huì)浪費(fèi)系統(tǒng)資源。

如果需要保證順序,可以讀取消息之后,將消息按照一定的規(guī)則分發(fā)到多個(gè)隊(duì)列中,然后在隊(duì)列中用單線程處理。

好了,今天先分享到這來(lái),下期再見(jiàn)。我在這里只是拋磚引玉,其實(shí)mq相關(guān)的內(nèi)容還有很多,比如:定時(shí)發(fā)送、延遲發(fā)送、私信隊(duì)列、事務(wù)問(wèn)題等等。

 

責(zé)任編輯:姜華 來(lái)源: 蘇三說(shuō)技術(shù)
相關(guān)推薦

2020-12-29 08:47:45

緩沖SQL磁盤(pán)

2014-05-30 10:23:15

樂(lè)跑手環(huán)智能手環(huán)運(yùn)動(dòng)手環(huán)

2022-05-27 08:55:15

工具自動(dòng)化軟件

2020-11-10 08:41:51

CPU執(zhí)行任務(wù)內(nèi)存

2020-12-22 10:48:22

Linux網(wǎng)絡(luò)包網(wǎng)絡(luò)模型

2015-01-06 14:39:41

云計(jì)算云存儲(chǔ)數(shù)據(jù)遷移

2022-05-10 09:16:50

MQ內(nèi)存消費(fèi)者

2014-03-12 09:23:06

DevOps團(tuán)隊(duì)合作

2018-11-25 10:08:44

阿里巴巴技術(shù)開(kāi)源

2021-08-16 05:39:33

云計(jì)算云計(jì)算環(huán)境信創(chuàng)云

2024-02-06 08:33:54

文件系統(tǒng)SSD

2023-04-11 07:34:40

分布式系統(tǒng)算法

2021-03-18 09:01:53

軟件開(kāi)發(fā)軟件選型

2014-10-20 10:23:37

2011-03-22 10:49:53

2011-02-25 14:35:00

2018-09-26 06:50:19

2021-06-02 08:33:31

TPCTPC-H系統(tǒng)

2022-02-08 17:39:04

MySQL服務(wù)器存儲(chǔ)

2020-12-22 07:36:02

顯示器校色色彩
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)