Map-Reduce是个什么东东?

MapReduce是一种用于使用并行分布式算法在集群计算机上处理大型数据集的编程模型及其相关实现。这一概念首先由Google普及,并随后作为Apache Hadoop项目的一部分开源发布。

MapReduce的基本工作流程:

  1. 映射(Mapping):这是第一阶段,在此阶段中,输入数据被划分为多个分块,并在整个集群的多个节点之间分散。每个节点独立地对其所拥有的数据分块应用“映射(map)”函数。映射函数接受一对键值(key-value)作为输入,并产出一组中间键值对。

    例如,如果你正在分析网站日志,映射函数可能将每个日志条目作为输入,并输出(IP地址,访问次数)这样的中间键值对。

  2. 洗牌与排序(Shuffling and Sorting):映射阶段之后,所有中间键值对都会按其键进行排序和分组。这确保了具有相同键的所有值在进入减少(reduce)步骤之前会被集中到同一个节点上。

  3. Reducing:在这一最后阶段,将对每组中间键值应用“reduce”函数。reduce函数以某种方式组合这些值,从而生成最终输出。例如,它可以计算每个IP地址的所有访问次数总和。

MapReduce的优势:

  • 可扩展性:通过在众多机器之间分布数据,能够处理非常大的数据集。
  • 故障容忍性:如果在处理过程中某个节点发生故障,系统可以自动将任务重新分配给另一个节点,确保计算仍然能够完成。
  • 简单性:它通过抽象并隐藏并行化、故障容忍以及数据分布的具体细节,简化了编写并行算法的过程。

示例应用场景:

  • 网络搜索索引构建
    在MongoDB中,虽然MapReduce可用于构建复杂的聚合逻辑,但实际构建搜索引擎索引时,MongoDB的mapReduce功能并不常用,因为MongoDB从版本3.4开始引入了更强大的聚合框架(Aggregation Pipeline),并且对于索引的构建,MongoDB本身提供了内建的索引机制。

不过,为了演示如何在MongoDB中使用MapReduce进行类似于索引构建的处理,假设我们有一个包含网页数据的集合web_pages,每个文档包含url(网页地址)和content(网页内容)等字段,我们可以编写一个简单的MapReduce作业来收集每个唯一URL及其出现次数,这可以看作是构建索引的一个简单模拟。

// 定义Map函数,它会为每个文档发出一个键值对,键是URL,值是1
var mapFunction = function() {
  emit(this.url, 1);
};

// 定义Reduce函数,它会将所有相同的URL对应的值加起来
var reduceFunction = function(key, values) {
  return Array.sum(values);
};

// 运行MapReduce作业
db.web_pages.mapReduce(
  mapFunction,
  reduceFunction,
  { 
    out: "url_index", // 输出结果到新的集合
    finalize: function(key, reducedValue) { 
      // finalize函数可以对reduce的输出进行进一步处理(此处不必要,仅作示例)
      return reducedValue;
    }
  }
);

// 查询结果集合
db.url_index.find();

上述MapReduce作业创建了一个新集合url_index,其中记录了每个网址及其在原始集合中出现的次数。然而,这并不是传统意义上的搜索引擎索引,因为它没有对内容进行解析、提取关键词或建立倒排索引。

实际构建搜索索引通常涉及更复杂的数据预处理和索引结构设计,MongoDB的内置索引和全文索引(text indexes)更适合这类场景。对于大规模的全文搜索需求,通常会选择专门的搜索引擎解决方案,如Elasticsearch或Solr。

  • 日志文件分析
    在MongoDB中,尽管MapReduce适用于批处理和聚合大量数据,但随着MongoDB Aggregation Framework的发展,现在更推荐使用聚合管道来处理日志分析等场景。然而,如果您希望了解如何在早期版本或者特定场景下使用MapReduce来分析MongoDB中的日志数据,以下是一个简化的日志文件分析的MapReduce示例。假设您有一个名为log_entries的集合,其中每个文档代表一条日志记录,含有timestamp(时间戳)和event_type(事件类型)等字段,想要统计每种事件类型的日志数量:
// 定义Map函数,它会为每条日志发出键值对,键是事件类型,值是1
var mapFunction = function() {
  emit(this.event_type, 1);
};

// 定义Reduce函数,它会把同一事件类型的所有计数加在一起
var reduceFunction = function(eventType, values) {
  return Array.sum(values);
};

// 运行MapReduce作业
db.log_entries.mapReduce(
  mapFunction,
  reduceFunction,
  {
    out: "log_stats", // 输出结果到新的集合
  }
);

// 查询结果集合
db.log_stats.find().sort({ "_id": 1 });

这个MapReduce作业会统计log_entries集合中每种event_type的数量,并将结果保存到名为log_stats的新集合中。每个文档的_id将是事件类型,值是该事件类型的日志条目总数。

请注意,实际的日志分析可能会更复杂,需要处理更多字段、日期范围和其他条件。在现代MongoDB应用中,同样的任务可能更倾向于使用聚合管道(Aggregation Pipeline)来实现,因为它通常更快,更易于理解和维护。

  • 数据聚合任务(如统计点击次数、浏览量或购买量)
    假设你有一个MongoDB集合user_activity,其中包含了用户活动数据,每个文档格式如下:
{
    "_id": ObjectId("..."),
    "userId": "user1",
    "activityType": "click",
    "item": "product1",
    "timestamp": ISODate("...")
}

要统计每个用户的点击次数、浏览量或其他购买行为,你可以使用MongoDB的MapReduce功能。以下是一个统计每个用户点击产品次数的MapReduce示例:

// Map函数
var mapFunction = function() {
  emit(this.userId, { activityType: this.activityType, count: 1 });
};

// Reduce函数
var reduceFunction = function(userId, activities) {
  var result = { clickCount: 0, viewCount: 0, purchaseCount: 0 };
  
  activities.forEach(function(activity) {
    switch (activity.activityType) {
      case 'click':
        result.clickCount += activity.count;
        break;
      case 'view':
        result.viewCount += activity.count;
        break;
      case 'purchase':
        result.purchaseCount += activity.count;
        break;
    }
  });

  return result;
};

// 运行MapReduce操作
db.user_activity.mapReduce(
  mapFunction,
  reduceFunction,
  {
    out: "user_activity_summary",
    verbose: true
  }
);

// 查看结果集合
db.user_activity_summary.find();

在这个例子中,Map函数会根据用户ID和活动类型发出键值对,而Reduce函数则负责汇总每个用户的各项活动计数。最终结果将存储在一个名为user_activity_summary的新集合中。

然而,请注意,在大多数情况下,特别是对于这类相对简单的聚合任务,MongoDB的Aggregation Pipeline提供了更为便捷和高效的解决方案,例如:

db.user_activity.aggregate([
  { $group: {
    _id: "$userId",
    clickCount: { $sum: { $cond: [{ $eq: ["$activityType", "click"] }, 1, 0] } },
    viewCount: { $sum: { $cond: [{ $eq: ["$activityType", "view"] }, 1, 0] } },
    purchaseCount: { $sum: { $cond: [{ $eq: ["$activityType", "purchase"] }, 1, 0] } }
  } }
]);

以上聚合管道操作同样会统计每个用户的点击、浏览和购买次数,并不需要创建额外的集合来存储结果。

  • 大数据集上的机器学习算法
    MongoDB MapReduce在处理机器学习任务方面并不是最直接的选择,因为它主要用于数据聚合和批处理,而不是构建或训练机器学习模型。然而,在一些场合,MapReduce可以作为一个初步的工具来进行数据预处理或特征工程,为后续机器学习任务准备数据。

假设我们想在一个大型MongoDB集合中使用MapReduce做简单的协同过滤算法的第一步,即计算物品之间的相似度(基于用户对物品的评分记录)。这里我们有一个集合ratings,其结构如下:

{
  "_id": ObjectId(...),
  "userId": "user1",
  "itemId": "item1",
  "rating": 4.5
}

为了计算每对物品间的共同用户数量和平均评分差值(Pearson相似度的一种简化形式),我们可以编写如下MapReduce脚本:

// Map函数
var mapFunction = function() {
  // 对于每一个评分记录,发出<itemId1, itemId2>键和带有共同用户及评分差值信息的对象
  emit([this.itemId, this.userId], { otherItemId: this.userId, rating: this.rating });
};

// Reduce函数
var reduceFunction = function(itemIdPair, userRatings) {
  var totalUsers = {};
  var ratingsSum = {};
  var ratingsCount = {};

  userRatings.forEach(function(ratingInfo) {
    var userId = ratingInfo.otherItemId;
    var rating = ratingInfo.rating;

    if (!totalUsers[userId]) {
      totalUsers[userId] = true;
      ratingsSum[userId] = rating;
      ratingsCount[userId] = 1;
    } else {
      ratingsSum[userId] += rating;
      ratingsCount[userId]++;
    }
  });

  // 返回共同用户数量和评分之和,实际的相似度计算通常会在外部完成
  return { commonUsers: Object.keys(totalUsers).length, ratingsSum: ratingsSum, ratingsCount: ratingsCount };
};

// 运行MapReduce操作
db.ratings.mapReduce(
  mapFunction,
  reduceFunction,
  {
    out: { reduce: "item_similarity" },
    scope: { Math: Math } // 如果需要数学运算,可以注入Math对象
  }
);

上面的示例仅仅是用MapReduce对物品间的共同用户进行了计数,实际的相似度计算需要在此基础上进一步完成,通常是在外部处理Reducer的输出结果,因为MapReduce本身的限制并不适合复杂的数学运算和迭代过程。

对于大规模机器学习任务,更加推荐的方法是将数据导出至更适合进行机器学习处理的环境,如Spark、Hadoop或Python的数据科学库中,再利用Scikit-Learn、TensorFlow、PyTorch等成熟机器学习库进行建模。

总之,MapReduce通过将复杂的计算分解为可在大量普通服务器上并行执行的更简单的任务,为处理大数据提供了一种强大且可扩展的工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/600017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

弹性云服务器是什么,为何如此受欢迎

云计算作为当下炙手可热的技术领域&#xff0c;已然成为现代企业不可或缺的核心能力。云服务器作为云计算的基石之一&#xff0c;在这个数字化时代发挥着至关重要的作用。而弹性云服务器&#xff0c;作为云服务器的一种演进形式&#xff0c;更是备受瞩目。 弹性云服务器&#…

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】

&#x1f496; Brief&#xff1a;大家好&#xff0c;我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 个人说明书&#xff1a;Zeeland&…

自动化运维管理工具 Ansible-----【inventory 主机清单和playbook剧本】

目录 一、inventory 主机清单 1.1inventory 中的变量 1.1.1主机变量 1.1.2组变量 1.1.3组嵌套 二、Ansible 的脚本 ------ playbook&#xff08;剧本&#xff09; 2.1 playbook介绍 2.2playbook格式 2.3playbooks 的组成 2.4playbook编写 2.5运行playbook 2.5.1ans…

学习笔记:【QC】Android Q qmi扩展nvReadItem/nvWriteItem

一、qmi初始化 流程图 初始化流程: 1、主入口&#xff1a; vendor/qcom/proprietary/qcril-hal/qcrild/qcrild/rild.c int main(int argc, char **argv) { const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); rilInit RIL_Init; funcs rilInit…

【Linux】Linux线程

一、Linux线程的概念 1.什么是线程 1.一个进程的一个执行线路叫做线程&#xff0c;线程的一个进程内部的控制序列。 2.一个进程至少有一个执行线程 3.线程在进程内部&#xff0c;本质是在进程地址空间内运行 4.操作系统将进程虚拟地址空间的资源分配给每个执行流&#xff0…

基于51单片机的闭环反馈直流电机PWM控制电机转速测量( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机的闭环反馈直流电机PWM控制转速测量( proteus仿真程序设计报告原理图讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;S0086 1. 主要功能&#xff1a; 基于51单片机的闭环…

js宏任务微任务输出解析

第一种情况 setTimeout(function () {console.log(setTimeout 1) //11 宏任务new Promise(function (resolve) {console.log(promise 1) //12 同步函数resolve()}).then(function () {console.log(promise then) //13 微任务})})async function async1() {console.log(async1 s…

语音识别--使用YAMNet识别环境音

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

2024.5.7

//头文件#ifndef MYWIDGET_H #define MYWIDGET_H#include <QWidget> #include <QPushButton> #include <QLineEdit> #include <QLabel> #include <QTextToSpeech> #include <QString> #include <QtDebug> #include <QIcon> #i…

js浏览器请求,post请求中的参数形式和form-data提交数据时数据格式问题(2024-05-06)

浏览器几种常见的post请求方式 Content-Type 属性规定在发送到服务器之前应该如何对表单数据进行编码。 默认表单数据会编码为 "application/x-www-form-urlencoded" post请求的参数一般放在Body里。 Content-Type&#xff08;内容类型&#xff09;&#xff0c;一般…

截图工具Snipaste:不仅仅是截图,更是效率的提升

在数字时代&#xff0c;截图工具已成为我们日常工作和生活中不可或缺的一部分。无论是用于工作汇报、学习笔记&#xff0c;还是日常沟通&#xff0c;一款好用的截图工具都能大大提升我们的效率。今天&#xff0c;我要向大家推荐一款功能强大且易于使用的截图软件——Snipaste。…

CRC校验原理及步骤

文章目录 CRC定义&#xff1a;CRC校验原理&#xff1a;CRC校验步骤&#xff1a; CRC定义&#xff1a; CRC即循环冗余校验码&#xff0c;是数据通信领域中最常用的一种查错校验码&#xff0c;其特征是信息字段和校验字段的长度可以任意选定。循环冗余检查&#xff08;CRC&#…

JUC-synchronized练习-交替打印ABC

今天来练习一下synchronized 简单来利用synchronized实现一个字符串的交替打印 主要的实现设置一个全局的变量state&#xff0c;线程执行通过不断累加state&#xff0c;根据state对三取余的结果来判断该线程是否继续执行还是进入等待。并通过synchronized锁住一个共享变量loc…

设计模式之模板模式TemplatePattern(五)

一、模板模式介绍 模板方法模式&#xff08;Template Method Pattern&#xff09;&#xff0c;又叫模板模式&#xff08;Template Pattern&#xff09;&#xff0c; 在一个抽象类公开定义了执行它的方法的模板。它的子类可以更需要重写方法实现&#xff0c;但可以成为典型类中…

学习R语言第五天

文章目录 语法学习创建数据的方式绘制图形的方式图形添加颜色如何操作数据的方式数据进行验算的判断加付值的方式修改变量名称的方式判断是否存在缺失值在计算的方式忽略缺失值通过函数的方式忽略缺失值日期处理的方式字符串转化成日期的方式格式化数据框中数据返回当前的日期的…

保研面试408复习 1——操作系统、计网、计组

文章目录 1、操作系统一、操作系统的特点和功能二、中断和系统调用的区别 2、计算机组成原理一、冯诺依曼的三个要点二、MIPS&#xff08;每秒百万条指令&#xff09;三、CPU执行时间和CPI 3、计算机网络一、各个层常用协议二、网络协议实验——数据链路层a.网络速率表示b.数据…

《十八》QThread多线程组件

本章将重点介绍如何运用QThread组件实现多线程功能。 多线程技术在程序开发中尤为常用&#xff0c;Qt框架中提供了QThread库来实现多线程功能。当你需要使用QThread时&#xff0c;需包含QThread模块&#xff0c;以下是QThread类的一些主要成员函数和槽函数。 成员函数/槽函数 …

Linux内核之获取文件系统超级块:sget用法实例(六十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

EMAIL-PHP功能齐全的发送邮件类可以发送HTML和附件

EMAIL-PHP功能齐全的发送邮件类可以发送HTML和附件 <?php class Email { //---设置全局变量 var $mailTo ""; // 收件人 var $mailCC ""; // 抄送 var $mailBCC ""; // 秘密抄送 var $mailFrom ""; // 发件人 var $mailSubje…

如何查看慢查询

4.2 如何查看慢查询 知道了以上内容之后&#xff0c;那么咱们如何去查看慢查询日志列表呢&#xff1a; slowlog len&#xff1a;查询慢查询日志长度slowlog get [n]&#xff1a;读取n条慢查询日志slowlog reset&#xff1a;清空慢查询列表 5、服务器端优化-命令及安全配置 安…
最新文章