关于生产者-消费者问题的一些思考

关于生产者-消费者问题的一些思考

写过一些多线程程序之后,回过头来重新翻开《APUE》和《UNP:IPC》,感觉特别有收获。这里小小总结一下。

1. 定义
Producer-Consumer Problem: also known as the bounded buffer problem.
One or more producers (threads or processes) are creating data times that are then processed by one or moree consumers (threads or processes). The data items are passed between the producers and consumers using some type of IPC.

2. 参与者
Producers:生产者,负责往bounded buffer(一般是队列)里插入数据(一般是任务job)。
Consumers:消费者,负责从bounded buffer中取出数据(一般是job),进行处理。

3. 数据共享或消息传递
有些数据需要各个进程都看得到和操作的到。比如队列和里面的数据。
数据共享方式一般有:共享内存(用户级别,多线程天生共享内存),文件系统
消息传递机制有:Pipe和FIFO(内核级别的数据共享),Socket(内核级别,本地用Unix Domain Socket),文件系统。
 
4. 协作点
1. 并发控制——因为有多个生产者和消费者,他们会对同一个队列同时进行操作,这必然需要并发控制。
并发控制一般使用各种锁机制(Lock),如mutex,reader-writer lock, 还有信号量(带通知机制的计数锁)。

2. 通知机制——生产者需要知道队列什么时候有空间可以放数据;消费者需要知道队列什么时候有数据可以消费。另外,在现实世界,任务一般是有限的,消费者需要知道什么时候自己可以停止了(队列不可能有数据了),这一般要求生产者告诉消费者他已经不再创建任务了。一种简单的做法是直到生产者将所有任务创建完成才启动消费者,这样就只需要同步消费者,但是如果创建任务是一件很耗时的操作,那么显然边创建边消费是一件更快速的做法。如果没有通知机制的引入,那么各个线程可能需要轮询(polling),这是对CPU资源的一种浪费。
线程/进程间的通知机制一般有条件变量(Condition Variables)或者信号量(Semaphone)。

其中第三点和第四点其实是有点互斥的。数据越不共享,越不需要并发控制,但是进程间通讯就越困难。

实战——数据迁移
目标:将Oracle的PRODUCT_DETAIL表给定范围数据迁移到MySQL集群中。

方案1:Map-Reduce思想,尽量减少并发控制。
将任务划分为N个不相干的子集,分配给每个进程/线程处理,各个进程和线程自己使用自己的数据结构,这样就不需要与其他进程/线程同步。父进程/线程等所有的子进程/线程处理完任务之后,将他们的结果进行汇总(不一定需要)。比如我们这个例子,可以这么做:
将迁移到数据区间[minId, maxId]划分成N个小区间,比如[minId, maxId_1],[maxId_1+1, maxId_2],... ,[maxId_n+1, maxId],对每个区间进行独立迁移。由于每个区间变小了,所以该区间的操作就可以单进程/线程执行,减少复杂性。
这种方案中,子进程/线程既是生产者也是消费者,只是每个人都工作量减少了。所有子线程走的是同样的程序。

方案2:传统的Producer-Consumer思想。
一个或者多个生产者进程/线程,负责从Oracle数据库中取出给定区间需要迁移到记录id,放在一个队列里。
一个或者多个消费者进程/线程,每次从队列中取出一个产品id,对该id对应的记录进行迁移。直到任务完成。
不同与方案1,方案2有明确的生产者消费者分工,生产者和消费者走到是完全不同的程序。这种协作其实类似与工厂里面的流水线操作,每个进程只是负责迁移工作的一部分(生产或者消费)。
如果消费者在生产者结束生产之前启动,需要生产者告诉消费者它已经创建完所有任务了,以让消费者知道什么时候可以停止。

数据迁移其实最困难的部分在于迁移到算法,如何保证迁移过程不产生脏数据和数据丢失。另外,对数据库连接数的控制也是要考虑的。由于迁移过程比较耗时,打印迁移进度和统计迁移信息也是必要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值