知识卡片
MapReduce查询介于声明式与命令式之间用纯函数换取容错重跑
内容
MapReduce既不是完全的声明式查询语言,也不是完全命令式的查询API,而是处于两者之间: 查询逻辑用map和reduce两个代码片段表示,由处理框架反复调用这两个函数来完成计算—— 比如统计每月观测到多少鲨鱼,map函数从每条观测记录里提取”年-月”作为key、动物数量 作为value,框架按key把结果分组,reduce函数把同一个key下的所有value加总。这种模型 的关键约束是map和reduce函数必须是纯函数:只使用传入的数据作为输入,不能执行额外的 数据库查询,也不能有任何副作用。这个约束看起来是限制,但它换来了一个重要能力—— 既然函数是纯的、没有副作用,处理框架就可以以任意顺序运行这些函数,并且在某次执行 失败时安全地重新运行它们而不用担心产生重复或不一致的结果,这正是分布式批处理系统 需要的容错基础。不过MapReduce作为查询接口本身有可用性问题:必须编写两个互相配合 的函数,通常比写一条声明式查询更难;而且声明式查询语言能给查询优化器更多自动优化 的机会,这也是为什么后来出现了在MapReduce之上再包一层声明式接口的趋势(如MongoDB 后来增加的聚合管道),本质上是NoSQL系统在无意中重新发明了SQL式的声明式查询能力。
参考来源
- 位置:《数据密集型应用系统设计》第二章《数据模型与查询语言》"MapReduce查询"
(源文件:_epub-src/ch2_split_002.html)
- 结论依据:原文说明MapReduce处于声明式和命令式之间,map和reduce函数必须是纯函数
不能有副作用,这一限制允许数据库以任意顺序运行并在失败时重新运行这些函数,并指出
MapReduce的可用性问题促使MongoDB后来增加声明式的聚合管道,直接支撑本卡片结论。
- 原始内容:MapReduce既不是一个声明式的查询语言,也不是一个完全命令式的查询API,
而是处于两者之间……map和reduce函数在功能上有所限制:它们必须是纯函数……这些限制
允许数据库以任何顺序运行任何功能,并在失败时重新运行它们……MongoDB 2.2添加了一种
叫做聚合管道的声明式查询语言的支持。