什么是隊列系統(tǒng)棵癣?
可以把隊列和棧還有堆想象成一個容器辕翰,
隊列其實就是我們通常說的排隊,可以想象成一個兩端開口的容器狈谊,先來后到喜命,先進(jìn)來的就先出去后進(jìn)來的就后出去。
棧就不一樣了河劝,棧大家可以想象成一端開口的容器 壁榕,比如說杯子,先進(jìn)去的反而后出來赎瞎。
而堆就是沒有口的一個盆牌里,隨便進(jìn)出。
含義:
消息隊列系統(tǒng)就是利用隊列的原理务甥,把一個個的消息放到像隊列一樣的容器里牡辽。
特點:
1喳篇、消息隊列是有順序的
2、消息隊列系統(tǒng)是可以存放數(shù)據(jù)的
場景:
1.用戶點擊按鈕發(fā)送短信态辛,有沒有收到短信系統(tǒng)其實并不知道
? ? 答疑: 用戶點擊了獲取短信的按鈕麸澜,主線程收到指令以后,fork 一個新的線程來去處理發(fā)送短信因妙,然后主線程繼續(xù)執(zhí)行后續(xù)的操作痰憎。
2.大家在使用各大第三方系統(tǒng)的時候是不是個回調(diào),如果回調(diào)沒有調(diào)通怎么辦
3.秒殺的時候商品只有100個的時候怎么處理
4.需要和第三方數(shù)據(jù)通訊的時候 對方掉線了怎么辦
5.如果我需要給別人發(fā)回調(diào) 別人沒有收到咋辦
6.我系統(tǒng)需要大量的記錄日志的時候怎么記
考慮:
1.我接下來的操作是不是必須成功
2.我接下來的操作用戶有沒有必要參與
3.接下來的操作是不是費時
如果是命中這三項其中一項攀涵,那么我們就可以把這個操作進(jìn)行異步處理(PS:注意這里不是多線程铣耘,而是多進(jìn)程。PHP支持多進(jìn)程也支持多線程)以故。
其實 php 在這里是可以用多線程來處理異步的問題蜗细,為啥不用呢?
1.從語言的角度來說 php的多線程需要依賴第三方庫怒详,而且比較弱炉媒,會出現(xiàn)子線程阻塞的問題,還有線程回收與釋放的問題 不像其它語言那么靈活
2.多線程來處理這類的問題只解決了費時的場景昆烁,和用戶無需參與的場景吊骤,并沒有解決保證成功的場景
以上都是 php 基于 sapi 運(yùn)行的情況,也就是基于 web 服務(wù)運(yùn)行 php 的場景静尼,也就是大家用 apache 或者 nginx 的時候白粉,cli 模式下運(yùn)行 php是另外的模型了。
為什么多線程不能解決保證成功的場景鼠渺?
答:如果我用多線程處理這個問題鸭巴,我請求網(wǎng)絡(luò)還是失敗,這個時候怎么辦拦盹?
? ? 1.子線程繼續(xù)等待鹃祖,循環(huán)直到成功
? ? 2.子線程銷毀,繼續(xù) fork 新線程直到成功
? ? 那么就很容易出現(xiàn)有線程一直阻塞在這里不會被釋放的現(xiàn)象吧普舆?
? ? 如果這種異常情況多了 大家想一下 你的電腦的內(nèi)存和 cpu 是不是瞬間就被撐爆了恬口?
? ? 那么需要解決剛剛說的那三個場景,就需要一個有存儲能力的異步工具沼侣,起碼失敗了你能幫我把失敗的東西存起來楷兽。
? ? 失敗了, 我首先做的事情是重試? 我不能無限重試华临,我更需要的是把失敗的東西存下來我能找到他,只要消息存下來了端考,準(zhǔn)確的說雅潭,消息低成本的存下來了揭厚,我就可以重新再嘗試,
回到場景一:
用戶點擊發(fā)生短信請求—>系統(tǒng)講請求放到消息隊列系統(tǒng)—>返回給用戶成功
另外一個進(jìn)程去消息隊列系統(tǒng)里消息—>拿到消息之后處理—>處理成功把消息刪掉—>處理失敗把消息放回系統(tǒng)
總結(jié):
隊列系統(tǒng) 并不是一個系統(tǒng) 而是一個概念扶供,只要你能滿足我說的兩個條件的筛圆,都可以廣義的說是隊列系統(tǒng)了。
比如 mysql 可以設(shè)計成隊列系統(tǒng)椿浓,redis 同理太援。