陈硕的Blog

muduo多机协作网络编程示例一:单词计数及排序

去年我写了《Muduo 网络编程示例》系列文章,这些文章已经收入《Linux 多线程服务端编程:使用 muduo C++ 网络库》一书。这些文章讲的基本都是运行在单机上的网络程序,每个例子都只有一个程序(第7.13节例外)。我接下来打算继续写几篇文章,谈一谈分布在多台机器上、协作发挥作用的网络编程例子。

今天先讲第一个,单词计数及排序。单词计数(word count),顾名思义就是统计一个文本文件里边每个词出现了多少次。排序指的是按出现次数从多到少排序,也可以把问题改为“找出出现次数最多的1000个单词”。

这个问题有三个层次,第一是输入文件比较小,能完全放入内存;第二是输入文件比较大,不能一次性都放入内存;第三是输入文件分布在多台机器上,这需要用到网络编程。

第一个层次很好解决,几十行代码就搞定了。https://gist.github.com/4519962

第二个层次不难解决,基本思路是分而治之,先hash分块统计单词出现次数,将每一块按出现次数排序,最后归并。代码见 https://github.com/chenshuo/recipes/blob/master/puzzle/query_freq.cc ,分析见 http://www.cnblogs.com/baiyanhuang/archive/2012/11/11/2764914.html

第三个层次也不难,可以当做网络编程的练习来做。如果有合适的框架,可以轻松解决,因为单词计数是map reduce的经典范例,对出现次数排序也可以再用一步map reduce搞定(估计需要一个好的 shuffle 函数,简单hash是不行的)。

如果用普通网络编程,一种设计思路如下图,其中方框代表机器,椭圆代表输入输出文件,圆角矩形代表进程。思路跟第二个层次一样,先hash到多个shard文件(由hasher和receiver负责),再对每个shard文件排序(由sender负责),最后归并(merger)。

topk

注意这种思路适合求top K元素,不适合按出现次数排序全部单词,因为最终结果收集在一台机器上。目前这个sender实现的一个限制是,每个shard必须能全部放入内存,因为sender对shard排序是在内存中进行的。如果数据更大,还需要实现单机外部排序。

图中hasher和receiver的代码见muduo示例中的 muduo/examples/wordcount ;sender和merger的代码见 https://github.com/chenshuo/recipes/tree/master/topk 。注意merger没有使用muduo,而是采用阻塞网络编程。有兴趣的读者可以思考其背后的原因。要想发挥 merger 正常的性能,需要修改 /usr/include/boost/asio/basic_socket_streambuf.hpp ,增大缓冲区,即 enum { buffer_size = 8192 };

这可以看作是map reduce的原始实现,或者说用map reduce的思想手写了一些原始工具。如果把map reduce比作C语言,这里的几个程序相当于汇编写的函数。

以后我再写一个按出现次数全排序的例子吧,需要替换这里的sender和merger。

(.完.)

posted on 2013-01-13 04:01 陈硕 阅读(3572) 评论(2)  编辑 收藏 引用 所属分类: muduo

评论

# re: muduo多机协作网络编程示例一:单词计数及排序[未登录] 2013-01-14 10:58 春秋十二月

不错,看了代码,虽没直接实现Hash、堆和归并算法,但这没关系,使用现成的boost和stl库也好,你对库运用的很到位  回复  更多评论   

# re: muduo多机协作网络编程示例一:单词计数及排序 2013-01-16 11:38 UCoding

学习了!  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

随笔分类

随笔档案

相册

搜索

最新评论

阅读排行榜

评论排行榜