在工做中經常聽到某某大牛之間的交談會涉及到,xx消費者啊啥的,到底什麼大牛之間講的是什麼?
這篇文章主要解決三個問題:
1.到底什麼是生產者和消費者,以及它們之間的故事
2.它們之間靠什麼交流
3.應用場景php
在實際的程序開發中,會常常碰到這樣的狀況:小a模塊負責生產數據,這些數據由另一個模塊負責處理。產生數據的模塊,就形象地稱爲生產者;而處理數據的模塊,就稱爲消費者。redis
單單抽象出生產者和消費者,還夠不上是生產者/消費者模式。該模式還須要有一個緩衝區處於生產者和消費者之間,做爲一箇中介。生產者把數據放入緩衝區,而消費者從緩衝區取出數據。大概的結構以下圖。swoole
能夠這麼理解,你(生產者)須要寫信寄給基友,你先放到郵箱(緩衝區),郵遞員(消費者)從郵箱取信進行派送(數據處理)。併發
那麼有同窗問了,好好的生產者和消費者直接溝通不就行了,搞出一個緩衝區是作甚?
其實這是有內涵(優勢)的:異步
解耦函數
假設生產者和消費者都是兩個類,若是直接讓生產者調消費者的類的方法,勢必會使其依賴於消費者的類方法,萬一消費者的消費方式改變(函數改掉啦)那麼生產者也要改。好了,代碼耦合了。高併發
那麼若是有了緩衝區就不同了,兩個都依賴於緩衝區,緩衝區只起到緩衝數據做用,一邊存一邊取,互不關聯也不依賴。性能
ps:你寫信直接交給郵遞員,萬一郵遞員換了,那你不是還要從新認識一下,還要關心是否是真的郵遞員。那若是是放郵箱的話,郵遞員是誰和你半毛錢關係沒有。.net
支持併發設計
生產者直接調消費者某個方法有個弊端:因爲函數是同步的,也能夠說是阻塞的,消費者沒返回以前,生產者只能一直等着,萬一消費者處理的又很慢,那生產者空閒着就浪費了。
使用了生產者/消費者模式以後,生產者和消費者能夠是兩個獨立的併發主體。生產者把製造出來的數據往緩衝區一丟,就能夠再去生產下一個數據。基本上不用依賴消費者的處理速度。
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