在工做中经常听到某某大牛之间的交谈会涉及到,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