1. 程式人生 > >生產者消費者模式 php 【轉】

生產者消費者模式 php 【轉】

情況 快的 問題: 坑爹 解耦 負責 對象 關系 產生

在工作中常常聽到某某大牛之間的交談會涉及到,xx消費者啊啥的,到底什麽大牛之間講的是什麽?
這篇文章主要解決三個問題:
1.到底什麽是生產者和消費者,以及它們之間的故事
2.它們之間靠什麽交流
3.應用場景

正文

一、什麽是生產者和消費者,以及它們之間的故事

在實際的程序開發中,會經常碰到這樣的情況:小a模塊負責生產數據,這些數據由另外一個模塊負責處理。產生數據的模塊,就形象地稱為生產者;而處理數據的模塊,就稱為消費者。

單單抽象出生產者和消費者,還夠不上是生產者/消費者模式。該模式還需要有一個緩沖區處於生產者和消費者之間,作為一個中介。生產者把數據放入緩沖區,而消費者從緩沖區取出數據。大概的結構如下圖。

技術分享圖片

可以這麽理解,你(生產者)需要寫信寄給基友,你先放到郵箱(緩沖區),郵遞員(消費者)從郵箱取信進行派送(數據處理)。

那麽有同學問了,好好的生產者和消費者直接溝通不就好了,搞出一個緩沖區是做甚?
其實這是有內涵(優點)的:

解耦

假設生產者和消費者都是兩個類,如果直接讓生產者調消費者的類的方法,勢必會使其依賴於消費者的類方法,萬一消費者的消費方式改變(函數改掉啦)那麽生產者也要改。好了,代碼耦合了。

那麽如果有了緩沖區就不一樣了,兩個都依賴於緩沖區,緩沖區只起到緩沖數據作用,一邊存一邊取,互不關聯也不依賴。

ps:你寫信直接交給郵遞員,萬一郵遞員換了,那你不是還要重新認識一下,還要關心是不是真的郵遞員。那如果是放郵箱的話,郵遞員是誰和你半毛錢關系沒有。

支持並發

生產者直接調消費者某個方法有個弊端:由於函數是同步的,也可以說是阻塞的,消費者沒返回之前,生產者只能一直等著,萬一消費者處理的又很慢,那生產者空閑著就浪費了。
使用了生產者/消費者模式之後,生產者和消費者可以是兩個獨立的並發主體。生產者把制造出來的數據往緩沖區一丟,就可以再去生產下一個數據。基本上不用依賴消費者的處理速度。

ps:如果沒郵箱,你就要站在等郵遞員來,想必這是坑爹的一件事。

支持生產消費者忙閑不均

緩沖區還有另一個好處。如果制造數據的速度時快時慢,緩沖區的好處就體現出來了。當數據制造快的時候,消費者來不及處理,未處理的數據可以暫時存在緩沖區中。等生產者的制造速度慢下來,消費者再慢慢處理掉。

ps:萬一今天是情人節啥的,寄信的人特別多,郵遞員一回只能帶100封,那麽多余100封的部分就可以放在郵箱,等處理好100封後再回頭取,繼續處理。

它們之間靠什麽交流

那麽生產者和消費者之間怎麽交流呢?當然是通過數據單元交流的。何謂數據單元捏?簡單地說,每次生產者放到緩沖區的,就是一個數據單元;每次消費者從緩沖區取出的,也是一個數據單元。

ps:寄信,信就是數據單元

那麽數據單元涉及到一個很關鍵的問題,就是數據粒度的問題。
有時出於性能等因素的考慮,也可能會把N個業務對象打包成一個數據單元。那麽,這個N該如何取值就是顆粒度的考慮了。顆粒度的大小是有講究的。太大 的顆粒度可能會造成某種浪費;太小的顆粒度可能會造成性能問題。顆粒度的權衡要基於多方面的因素,以及一些經驗值的考量。

ps:還是拿寄信的例子。如果顆粒度過小(比如設定為1),那郵遞員每次只取出1封信。如果信件多了,那就得來回跑好多趟,浪費了時間。
如果顆粒度太大(比如設定為100),那寄信的人得等到湊滿100封信才拿去放入郵筒。假如平時很少寫信,就得等上很久,會很不爽滴~

應用場景

那麽在php中哪些地方會用到呢,或者說哪些地方會看到別人用到生產者和消費者模式?這裏簡單講幾個:

swoole

對,你沒看錯,就是swoole。那麽swoole其實是有使用了這個設計的模式,業務邏輯(生產者)將數據單元通過swoole的send函數弄到swoole的一個緩沖區之間,通過work進程進行分發,task進程(消費者)進行消費。

耗時操作的異步處理

當“耗時操作“遇到了”高並發“,如果不采取一點措施,卡慢崩會慢慢到來,此時可以將要處理的耗時操作的相關信息(數據單元)通過業務邏輯[生產者]push到redis隊列中(redis只是舉例),在通過跑一個腳本的進程[消費者]進行pop出數據單元進行處理。

轉載自

http://blog.csdn.net/u011957758/article/details/51138707

生產者消費者模式 php 【轉】