生产者—消费者模型问题又被称为“有限缓冲区”问题,即至少一个生产者与至少一个消费者针对一个公用的初始大小固定的缓冲区进行操作。首先,缓冲区是公用的或者说是共享的。Producer进程将消息放入缓冲区,Consumer进程从缓冲区获得消息。这个缓冲区一般被实现为队列结构,比如基于共享内存队列结构。有了缓冲区后,大家来看看Producer进程和Consumer进程的配合使用情景。
1)通过进程间的互斥锁来对缓冲区进行互斥访问,以解决多个Producer进程和Con⁃sumer进程之间的配合问题。这种解决方案使得Consumer进程大多数时间在忙等待,空耗计算资源。
2)采用条件变量,Consumer进程在条件变量上等待,Producer进程生产出数据后,可采用特定逻辑去唤醒某个Consumer或者全部Consumer进程(Broadcast)。这种方案使得Consumer进程多数情况下都在挂起状态,在缓冲区没有数据的情况下也无法去做别的事情。
3)基于条件变量,不同的是在Consumer进程中创建了一个工作线程,并由该工作线程来做条件变量的等待。同时每个Consumer进程中工作线程和主线程通过Pipe的方式配合。Producer进程主线程生成一条数据后,就会发起一个唤醒操作。被唤醒的Consumer进程的工作线程则通过Pipe告知主线程,主线程一般通过多路复用(select or poll)监听Pipe并及时获得通知去获取缓冲数据。这种解决方案的缺陷是,常出现工作线程无法退出的问题:当Consumer进程退出前,工作线程因无法从条件变量的阻塞状态下唤醒并退出,导致主线程在Join该工作线程时挂起而无法退出。(www.daowen.com)
4)用可靠信号机制+进程内Pipe机制。Producer进程在生产后数据发送UNIX可靠信号(>SIGRTMIN)给所有注册的Consumer进程。Consumer进程设置的可靠信号处理函数的逻辑较为简单,就是向Pipe写入一个字节数据,这样当信号中断处理完毕后,Consumer进程就可以收到Pipe的POLL_IN事件了。
5)通过UNIX FIFO做Producer、Consumer进程间通知的机制。FIFO机制简单、数据可靠,且在一定数据长度下的数据写入都是原子操作。FIFO与缓冲区一道做初始化创建,要操作缓冲区的Producer、Consumer进程,都要事先打开FIFO以写入或读出数据。Producer进程输出数据后,向FIFO写入数据以表示通知。某个Consumer进程从FIFO中读取通知并开始处理缓冲区数据,每个进程一般只从FIFO读取一个字节表示收到信号。
Kafka的设计思想之一是高吞吐量、高扩展性,因而Kafka在Producer与Consumer模型之间的数据传送采用了独特的Pull与push机制。即Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。