AppEngine-MapReduce简介
2010 10 18 10:53 PM 2412次查看
分类:Google App Engine 标签:Google App Engine, Python
提起MapReduce,熟悉函数式编程的应该很容易明白它的思想。用Python来举例,它就是map函数和reduce函数,就这么简单!
考虑到有人对Python不太了解,所以再介绍下map和reduce吧:
- map接受一个序列参数和一个函数参数,遍历这个序列,将其中所有的元素代入函数中执行。例如将一个列表里的元素全部加2,那么列表就是序列参数,加2就是函数参数。
- reduce同样接受一个序列参数和一个函数参数,遍历这个序列,依次将所有的元素和上一次的执行结果代入函数中执行。例如统计一个列表的积,那么列表就是序列参数,乘法就是函数参数。
了解了这些后,就不难明白AppEngine-MapReduce也需要2个最重要的参数:操作和所操作的实体集。
于是来看一个mapreduce.yaml的例子:
mapreduce:
- name: fix Article
mapper:
input_reader: google.appengine.ext.mapreduce.input_readers.DatastoreInputReader
handler: fix_uploaded_data.fix_article
params:
- name: entity_kind
default: model.Article
在这个文件里就定义了操作(fix_uploaded_data.fix_article)和所操作的实体集(model.Article)。因此它会遍历所有的model.Article实体,进行fix_uploaded_data.fix_article操作。遗憾的是目前只能指定一个类型的所有实体,还不能指定某一部分为参数(例如指定a属性小于10的实体)。接下来再来看看fix_uploaded_data.fix_article做了什么:
from model import Comment
from google.appengine.ext.mapreduce import operation
def empty(list):
return list is None or list == ['']
def fix_article(article):
if empty(article.keywords):
article.keywords = []
if empty(article.tags):
article.tags = []
article.replies = Comment.all().ancestor(article).filter('approved =', True).count(100000)
yield operation.db.Put(article)
其实就是一个很简单的map操作,处理一下空值,并计算replies属性,最后用yield operation.db.Put(article)返回即可。注意这里用的不是db.put,此外除了Put操作,还能执行Delete操作,其他就基本都一样了。
定义完操作后,还得定义一个handler来处理。由于现在的SDK已经内置了AppEngine-MapReduce,因此只要在app.yaml的handlers里加上这段即可:
- url: /mapreduce(/.*)?
script: $PYTHON_LIB/google/appengine/ext/mapreduce/main.py
login: admin
然后访问一下/mapreduce,就可以看到其界面了。最后我这个操作是每秒处理了22.39个实体,显得有点慢,不过考虑到这个实体很大,而且每次都有一个count查询,也还是可以接受的。只不过从性能上来考虑的话,自己写个task,用游标来记录位置,每次操作多处理一些实体估计会更快。
我顺便还在执行结果里发现了google.appengine.ext.key_range这个模块,而且知道它是依靠猜测,将key分成几段,并利用end游标来分成多个task并行执行的。
此外还有一些高级的参数和用法,这里就不再介绍了,毕竟这个库还没正式并入GAE SDK里,以后说不定还有很大改动。
0条评论 你不来一发么↓