过度设计

来源:互联网 发布:淘宝电子面单充值 编辑:程序博客网 时间:2024/06/11 17:56

这几天在设计应用的原型,一直想的是如何解耦和应付后面的多进程应用,所以设计的时候用了很多的接口编程。这个还算是不错。难点在reader/writer之间的同步:writer需要在reader空闲的时候通知他可以读,reader则需要在没有任务的时候等待;两者交换数据用named pipe;reader包括一个IB(mysql)的“load”语句,使用named pipe。一开始很容易想到使用信号量,但是如何利用起来费了些思量。

Writer:

     while(1){

            tell_reader_have_work_to_do;            ---------->           if(reader_is_not_loading){

                                                                                                          tell_reader_have_work_to_do;

                                                                                                   }

            write_FIFO;

    }

 

Reader:

     while(1){

            wait_for_work;

            ;

            mysql_load_data_in_file;

            ;

    }

load语句是利用Connector_C完成的。最初的目的是要保证几点:

1. reader不死等,也就是说writer退出的时候,自己能知道;

2. load语句不能挂死,必须在有限时间内读到EOF;

3. writer必须在reader没有执行load语句的时候才告诉reader有data需要处理,否则直接写FIFO

第一条比较容易做到,因为两者共享同一个semid,那么在writer退出的时候可以删除此semid,那么等待的reader将会得到ERMID错误;第二条也不是问题;关键是第三条,设定它的目的是应为当前版本的IB只有table lock,如果一直执行load,则query无法返回,所以如果reader被唤醒,而对端并没有数据的话,load将被挂住。这样就要求writer知道reader的状态:在执行load还是在等待。如果在执行load,那么执行tell_reader_have_work_to_do操作,因为load将会把此次写入的数据一并load进去;否则唤醒。这样避免多次唤醒,导致load挂住。这样一来就需要增加tell_my_status和update_my_status操作,并且writer还得再write之前获知状态。这样一来在reader和writer都需要操作两个sem,所以加锁就成了必须的动作,而是又增加了一个信号量。并且两者间的锁的争用在多线程的时候也是问题。

实际上我并没有实验三个信号量的方案,只是试了下两个信号量的方案。才发现必须得加另外一个锁,因为在mysql_load_data_in_file和tell_my_status之间,writer可能被执行,而是得到reader正在loading,而是不进行tell_reader_have_work_to_do。那么后果就是两者都被挂起(为了保证writer不丢数据,所以对FIFO的写是BLOCK的)。当时我的改动就是把写FIFO改成NON-BLOCK,如果发现open失败,重复检查reader的状态。这种方法是可以的,但是这样的话writer就会占用很多的cpu时间(TOP命令的观察)。导致load的速率很慢。这让我很苦恼,因为我一直坚持第3条目的,当时觉得只有这样,reader进程才能安全。现在想来有些钻牛角尖了,有时候你的否定自己,多方面来看,难道必须要加上这个我自以为是的第3条“原则”吗?不加的话如何能保证reader进程安全呢?

仔细想想,其实只要能了解对端的某些信息,比如是否退出,即使表示work的sem不准确,reader也能工作。比如说如果writer退出的时候,在信号处理函数里面reader发现自己挂在load上面,可以自己写一个EOF,然后退出就是;或者直接close掉mysql的链接就是。虽然这样看,用的sem并不是那么的优雅,但却是很简单的,看起来也非常的清楚,一个就搞定。并且在管理进程里面很容易就能得到子进程的退出等等的消息。利用信号量加上sem就可以搞定。

原创粉丝点击