您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“為什么要使用消息隊(duì)列”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
說到Java中的隊(duì)列應(yīng)該都不會(huì)陌生。其具有通過先進(jìn)先出,或者雙端進(jìn)出的方式進(jìn)行數(shù)據(jù)管理;通過阻塞以達(dá)到自動(dòng)平衡負(fù)載的功能。
消息隊(duì)列之所以以隊(duì)列命名,起初也是因?yàn)槠涔δ芎筒僮鳎蚸ava的本地隊(duì)列有相似之處。所以,我們可以簡(jiǎn)單的認(rèn)為消息隊(duì)列就是為了滿足分布式下各服務(wù)之間的數(shù)據(jù)傳輸、管理和消費(fèi)的一種中間服務(wù)。
問:你們的系統(tǒng)中為什么要引入消息隊(duì)列?
我們總歸需要知曉消息隊(duì)列的使用價(jià)值,以及自己的業(yè)務(wù)場(chǎng)景下的實(shí)際痛點(diǎn)才能回答為什么要用消息隊(duì)列這個(gè)問題,才能回答系統(tǒng)引入消息隊(duì)列的價(jià)值所在。
系統(tǒng)間解耦
以前幾天在后臺(tái)和關(guān)注公號(hào)的一個(gè)大佬討論的廣告流水更新的操作為例:
廣告檢索系統(tǒng),需要感知廣告貼的信息變動(dòng)來更新自己的索引,但實(shí)際上檢索系統(tǒng)和投放、物料、資產(chǎn)等系統(tǒng)間沒有必要依靠接口對(duì)感知行為進(jìn)行強(qiáng)關(guān)聯(lián),且接口的方式在維護(hù)和系統(tǒng)的壓力方面不友好,那么,消息隊(duì)列的作用就顯的很重要了,各系統(tǒng)發(fā)布各自的消息,誰需要誰訂閱,達(dá)到目的同時(shí)不會(huì)增加額外的系統(tǒng)調(diào)用壓力。(注:builder的接口調(diào)用是為了獲取最新的信息,此處可以通過壓縮等方式進(jìn)行優(yōu)化)
因此,當(dāng)系統(tǒng)間無實(shí)時(shí)數(shù)據(jù)交互要求,但還需要其業(yè)務(wù)信息時(shí),可以用消息隊(duì)列來達(dá)到系統(tǒng)間解耦的作用,只要發(fā)布方定義好消息隊(duì)列格式,消費(fèi)方的任何操作均可和發(fā)布方無關(guān),減少了不必要的聯(lián)調(diào)和發(fā)布沖突等影響。
服務(wù)異步化
最典型的一個(gè)例子,就是支付場(chǎng)景下的結(jié)果通知功能。
我們知道,一般情況下不管是app push 還是短信通知,都是比較耗時(shí)的操作。所以,沒有必要因?yàn)檫@些非核心功能的耗時(shí)操作而影響了支付的核心操作,只要我們?cè)谥Ц恫僮魍瓿芍?,將支付結(jié)果發(fā)到短信中心指定的消息topic下,短信中心自然會(huì)接收到此消息并保證通知給用戶。
圖片來源于知乎回答
因此使用消息隊(duì)列,讓非核心的操作異步化,提高整個(gè)業(yè)務(wù)鏈路的高效和穩(wěn)定,是很有效的。
削峰填谷
這個(gè)功能使我們本篇關(guān)注的重點(diǎn),面對(duì)特殊場(chǎng)景如秒殺、春晚紅包等萬億級(jí)流量的脈沖式壓力下,一種保護(hù)我們系統(tǒng)的服務(wù)免于崩潰的有效手段就是消息隊(duì)列。
通過消息中心高性能的存儲(chǔ)和處理能力,將超過系統(tǒng)處理能力的多余流量暫時(shí)存儲(chǔ)起來,并在系統(tǒng)處理能力內(nèi)平緩釋放出來,達(dá)到削峰的效果。
比如我們的廣告計(jì)費(fèi)系統(tǒng),面對(duì)上萬并發(fā)的商業(yè)貼檢索量,數(shù)千并發(fā)的點(diǎn)擊操作,實(shí)時(shí)接口的方式一定是不合適的,畢竟廣告行為和支付行為不一樣,支付失敗用戶還可以重試,但用戶的商業(yè)貼點(diǎn)擊行為是不可回放的,本次流量過去就過去了,因此,需要利用消息隊(duì)列將扣費(fèi)請(qǐng)求緩存下來,來保證計(jì)費(fèi)系統(tǒng)的穩(wěn)定。
其他
還如廣播、事務(wù)型、最終一致性等特性,也是消息隊(duì)列經(jīng)常用到的功能。
業(yè)務(wù)上增加響應(yīng)延遲
前面提到,消息隊(duì)列使得業(yè)務(wù)非核心流程異步化,可以提高整個(gè)業(yè)務(wù)操作的時(shí)效性和流暢度,提升用戶操作體驗(yàn)。但,也是因?yàn)閿?shù)據(jù)進(jìn)入隊(duì)列的原因,不可避免的會(huì)耽擱消費(fèi)速度。導(dǎo)致業(yè)務(wù)生效不及時(shí)。
比如,之前遇到的商品推薦,產(chǎn)品要求推薦列表中不能出現(xiàn)滿減秒殺的商品,以消除特殊商品對(duì)推薦效果產(chǎn)生影響。除了秒殺,我們還需要感知商品的上下架、黑名單、庫存等等,因次,用redis中的bit多個(gè)偏移量來維護(hù)一個(gè)商品的多個(gè)狀態(tài)。然后接收促銷組的消息來變更推薦緩存集群中的商品狀態(tài),但由于消息的延遲,就有可能導(dǎo)致商品狀態(tài)變更不及時(shí)的情況發(fā)生。不過只要權(quán)衡之下業(yè)務(wù)和技術(shù)上是可接受的就OK了。
架構(gòu)上引入不穩(wěn)定因素
消息隊(duì)列的引入,相當(dāng)于在原有的分布式服務(wù)鏈路中新增了一個(gè)系統(tǒng),系統(tǒng)復(fù)雜度也隨之變大了。同時(shí),消息隊(duì)列的作用要求其具有高性能和高可用。
所以,面對(duì)怎樣部署高可用穩(wěn)定集群、消息發(fā)送不成功怎么重試、broker數(shù)據(jù)同步策略怎么設(shè)置、broker異常導(dǎo)致消息重發(fā)怎么冪等、消費(fèi)不成功怎么重試等等問題,需要中間件團(tuán)隊(duì)和業(yè)務(wù)系統(tǒng)一起努力應(yīng)對(duì)。
2020 年雙十一交易峰值達(dá)到 58.3W 筆/秒。RocketMQ為了阿里的交易生態(tài)有很多深度定制,這里我們只介紹其中針對(duì)高可用的優(yōu)化。
個(gè)人理解,push消費(fèi)模式只適合于消費(fèi)速度遠(yuǎn)大于生產(chǎn)速度的場(chǎng)景,如果是大流量并發(fā)場(chǎng)景,基本還是以Pull消費(fèi)為主。
而pull前broker和client間會(huì)進(jìn)行負(fù)載均衡建立連接,那么,一旦Client被Hang住,(沒有宕就不會(huì)rebalance,即時(shí)宕機(jī)也是默認(rèn)20s才會(huì)rebalance),就會(huì)讓broker與該client關(guān)聯(lián)的隊(duì)列消息無法及時(shí)被消費(fèi),導(dǎo)致積壓。怎么辦:POP,新的消費(fèi)模式
POP 消費(fèi)中并不需要rebalance去分配消費(fèi)隊(duì)列,取而代之的是請(qǐng)求所有的 broker 獲取消息進(jìn)行消費(fèi)。broker 內(nèi)部會(huì)把自身的三個(gè)隊(duì)列的消息根據(jù)一定的算法分配給等待的 POPClient。即使 PopClient 2 出現(xiàn) hang,但內(nèi)部隊(duì)列的消息也會(huì)讓 Pop Client1 和 Pop Client2 進(jìn)行消費(fèi)。這樣避免了消費(fèi)堆積。[1]
要實(shí)現(xiàn)平滑,則需要讓producer無感的實(shí)現(xiàn)partition遷移。
大致原理是將待遷移partition的數(shù)據(jù)和新的partition數(shù)據(jù)進(jìn)行同步并持續(xù)一段時(shí)間,直到消費(fèi)者全部趕上同步的開始節(jié)點(diǎn),然后再變更路由,刪除原partition,完成遷移。
相同的數(shù)據(jù)同步思路,在facebook的分布式隊(duì)列災(zāi)備方案上也有應(yīng)用。
kafka的高性能,來源于順序文件讀寫和操作系統(tǒng)緩存pagecache的支持,在單partition,單consumer的場(chǎng)景下,kafka表現(xiàn)的非常優(yōu)秀。但是,如果同一機(jī)器上,存在不同的partition,甚至,消費(fèi)模式有實(shí)時(shí)和延遲消費(fèi)的混合場(chǎng)景,將會(huì)出現(xiàn)PageCache資源競(jìng)爭(zhēng),導(dǎo)致緩存污染,影響broker的服務(wù)的處理效率。
美團(tuán)應(yīng)對(duì)實(shí)時(shí)/延遲消費(fèi)緩存污染
將數(shù)據(jù)按照時(shí)間維度分布在不同的設(shè)備中,近實(shí)時(shí)部分的數(shù)據(jù)緩存在 SSD 中,這樣當(dāng)出現(xiàn) PageCache 競(jìng)爭(zhēng)時(shí),實(shí)時(shí)消費(fèi)作業(yè)從 SSD 中讀取數(shù)據(jù),保證實(shí)時(shí)作業(yè)不會(huì)受到延遲消費(fèi)作業(yè)影響
當(dāng)消費(fèi)請(qǐng)求到達(dá) Broker 時(shí),Broker 直接根據(jù)其維護(hù)的消息偏移量和設(shè)備的關(guān)系從對(duì)應(yīng)的設(shè)備中獲取數(shù)據(jù)并返回,并且在讀請(qǐng)求中并不會(huì)將 HDD 中讀取的數(shù)據(jù)回刷到 SSD,防止出現(xiàn)緩存污染。同時(shí)訪問路徑明確,不會(huì)由于 Cache Miss 而產(chǎn)生的額外訪問開銷。
快手應(yīng)對(duì)follower數(shù)據(jù)同步引起的緩存污染
broker 中引入了兩個(gè)對(duì)象:一個(gè)是 block cache;另一個(gè)是 flush queue。
Producer 的寫入請(qǐng)求在 broker 端首先會(huì)被以原 message 的形式寫入 flush queue 中,之后再將數(shù)據(jù)寫入到 block cache 的一個(gè) block 中,之后整個(gè)請(qǐng)求就結(jié)束了。在 flush queue 中的數(shù)據(jù)會(huì)由其他線程異步地寫入到磁盤中(會(huì)經(jīng)歷 page cache 過程)。保證queue不受follower的影響
consumer 首先會(huì)從 block cache 中檢索數(shù)據(jù),如果命中,則直接返回。否則,則從磁盤讀取數(shù)據(jù)。這樣的讀取模式保障了 consumer 的 cache miss 讀并不會(huì)填充 block cache,從而避免了產(chǎn)生污染。
總結(jié)
我們可以看出,解決緩存污染的基本出發(fā)點(diǎn),還是要拆解不同消費(fèi)速度的任務(wù)、或不同的數(shù)據(jù)生產(chǎn)來源,分而治之的思路避免相互間緩存的影響。
紅包操作的背后流程簡(jiǎn)化為:從 A 帳號(hào)中把余額讀出來,然后做減法操作,再把結(jié)果寫回 A 帳號(hào)中;然后拆紅包對(duì) B 帳號(hào)做加法操作,把結(jié)果寫到 B 帳號(hào)中。
而由于賬務(wù)系統(tǒng)能承載的壓力有限(和賬務(wù)相關(guān)的系統(tǒng)一般都會(huì)由于鎖、事務(wù)等原因影響處理效率),可能導(dǎo)致入賬失敗,如果按實(shí)時(shí)業(yè)務(wù)邏輯,則需要對(duì)拆紅包進(jìn)行實(shí)時(shí)回滾(回滾需要對(duì)A的賬戶再進(jìn)行一次加法),而引入CMQ后,業(yè)務(wù)鏈路變成將失敗的請(qǐng)求寫入CMQ,由CMQ的高可用來保證數(shù)據(jù)一致,直到賬務(wù)系統(tǒng)最終入賬成功。簡(jiǎn)化了賬務(wù)系統(tǒng)由于系統(tǒng)壓力而導(dǎo)致的入賬失敗而導(dǎo)致紅包賬務(wù)回滾帶來的額外系統(tǒng)操作。
“為什么要使用消息隊(duì)列”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。