当前位置: 首页 > news >正文

go-zero(十三)使用MapReduce并发

go zero 使用MapReduce并发

一、MapReduce 介绍

MapReduce 是一种用于并行计算的编程模型,特别适合在大规模数据处理场景中简化逻辑代码。

官方文档:

https://go-zero.dev/docs/components/mr

1. MapReduce 的核心概念

在 MapReduce 中,主要有以下三个核心步骤:
a. Generate (生成数据)

  • 数据的初始输入阶段。可以是一个简单的循环,也可以是从数据库、文件或其他来源加载数据。
    b. Mapper (映射)
  • 将输入数据映射为中间结果。通常用来过滤、转换、查询或处理数据。
    c. Reducer (归约)
  • 对映射后的数据进行汇总处理,生成最终的结果。

在 go zero 中,mr.MapReduce 的具体代码如下:


func MapReduce[T, U, V any](generate GenerateFunc[T], mapper MapperFunc[T, U], reducer ReducerFunc[U, V],opts ...Option) (V, error) {panicChan := &onceChan{channel: make(chan any)}source := buildSource(generate, panicChan)return mapReduceWithPanicChan(source, panicChan, mapper, reducer, opts...)
}

2. 为什么需要 MapReduce

在实际的业务场景中我们常常需要从不同的 rpc 服务中获取相应属性来组装成复杂对象。

比如要查询商品详情:

  • 商品服务-查询商品属性
  • 库存服务-查询库存属性
  • 价格服务-查询价格属性
  • 营销服务-查询营销属性

如果是串行调用的话响应时间会随着 rpc 调用次数呈线性增长,所以我们要优化性能一般会将串行改并行。

简单的场景下使用 WaitGroup 也能够满足需求,但是如果我们需要对 rpc 调用返回的数据进行校验、数据加工转换、数据汇总呢?继续使用 WaitGroup 就有点力不从心了.。

二、项目构建

接下来我们使用一个文章列表功能简单的演示下

1. article数据表

这是存储文章信息的表,包含标题、内容、作者、评论数等字段。

CREATE TABLE `article` (`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',`title` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '标题' COLLATE 'utf8mb4_bin',`content` TEXT NOT NULL COMMENT '内容' COLLATE 'utf8_unicode_ci',`cover` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '封面' COLLATE 'utf8mb4_bin',`description` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '描述' COLLATE 'utf8mb4_bin',PRIMARY KEY (`id`)
);

2.article.api

在实际开发中,应该传入作者ID、游标、页码、排序方法等信息,这里为了方便演示就不传入参数了,API 定义如下:

syntax = "v1"type (ArticleInfo {ArticleId   int64  `json:"article_id"`Title       string `json:"title"`Content     string `json:"content"`Description string `json:"description"`Cover       string `json:"cover"`}ArticleListResponse {Articles []ArticleInfo `json:"articles"`}
)@server (prefix: /v1/article
)
service article-api {@handler Articlelisthandlerpost /list returns (ArticleListResponse)
}

三、使用 MapReduce

拉取库

go get github.com/zeromicro/go-zero/core/mr

1.实现文章列表

我们使用 MapReduce 来并行处理文章数据,

func (l *ArticlelistLogic) Articlelist() (resp *types.ArticleListResponse, err error) {// Step 1: Generate 数据//这里为了方便我使用了简单for循环产生文档IDgenerateFunc := func(source chan<- int) {for id := 1; id < 50; id++ { // 模拟文章 ID 数据source <- id}}articleModel := l.svcCtx.ArticleModel// Step 2: Mapper 映射处理mapperFunc := func(id int, writer mr.Writer[*types.ArticleInfo], cancel func(error)) {//使用产生id,查询文章详情one, err := articleModel.FindOne(l.ctx, uint64(id)) // 查找单篇文章if err != nil {return // 跳过错误}//FindOne返回的是 *model.Article类型,Mapper映射的类型为*types.ArticleInfo//所以需要转换一下articleInfo := &types.ArticleInfo{ArticleId:   int64(one.Id),Title:       one.Title,Content:     one.Content,Description: one.Description,Cover:       one.Cover,}writer.Write(articleInfo) // 写入中间结果}// Step 3: Reducer 汇总处理reduceFunc := func(pipe <-chan *types.ArticleInfo, writer mr.Writer[[]types.ArticleInfo], cancel func(error)) {var articleList []types.ArticleInfofor article := range pipe {articleList = append(articleList, *article) }writer.Write(articleList) // 写入最终结果}// 调用 MapReduce//mr.WithWorkers(5)  允许调用者自定义并发工作线程数。//如果不传入mr.WithWorkers ,默认Workers为16个reduce, err := mr.MapReduce(generateFunc, mapperFunc, reduceFunc, mr.WithWorkers(5))   if err != nil {return nil, err // 处理错误}// 返回结果return &types.ArticleListResponse{Articles: reduce,}, nil
}

在这里插入图片描述

2. 详细讲解

Step 1: Generate 数据
generateFunc 的作用是提供初始数据。在本例中,我们通过一个循环生成了文章的 ID:

generateFunc := func(source chan<- int) {for id := 1; id < 50; id++ {source <- id}
}

Step 2: Mapper 映射处理
mapperFunc 用于处理每一个文章 ID,并将其转换为 ArticleInfo

  • 使用 articleModel.FindOne 从数据库中获取文章数据。
  • 如果获取失败,跳过该 ID。
  • 将结果通过 writer.Write 写入到下一步。
mapperFunc := func(id int, writer mr.Writer[*types.ArticleInfo], cancel func(error)) {one, err := articleModel.FindOne(l.ctx, uint64(id))if err != nil {return}articleInfo := &types.ArticleInfo{ArticleId:   int64(one.Id),Title:       one.Title,Content:     one.Content,Description: one.Description,Cover:       one.Cover,}writer.Write(articleInfo)
}

Step 3: Reducer 汇总处理
reduceFuncmapperFunc 的结果汇总为最终的 []types.ArticleInfo

  • 遍历管道中的每个 *types.ArticleInfo
  • 将解引用后的 ArticleInfo 添加到结果列表。
reduceFunc := func(pipe <-chan *types.ArticleInfo, writer mr.Writer[[]types.ArticleInfo], cancel func(error)) {var articleList []types.ArticleInfofor article := range pipe {articleList = append(articleList, *article)}writer.Write(articleList)
}

3. 测试运行

/v1/article/list 发送 POST 请求:

curl -X POST http://localhost:8888/v1/article/list

运行结果如下:

{"articles": [{"article_id": 1,"title": "标题1","content": "这是内容1","description": "描述1","cover": "封面1.jpg"},...]
}

4.效率对比

普通循环

为了更直观的对比效率,我们使用普通循环再次实现下文章列表:

func (l *ArticlelistLogic) Articlelist() (resp *types.ArticleListResponse, err error) {// todo: add your logic here and delete this linetime1 := time.Now()var articleList []types.ArticleInfoarticleModel := l.svcCtx.ArticleModelfor id := 1; id < 50; id++ {article, _ := articleModel.FindOne(l.ctx, uint64(id))articleInfo := types.ArticleInfo{ArticleId:   int64(article.Id),Title:       article.Title,Content:     article.Content,Description: article.Description,Cover:       article.Cover,}articleList = append(articleList, articleInfo)}time2 := time.Now()logx.Info("执行时间为:", time2.Sub(time1))return &types.ArticleListResponse{Articles: articleList,}, nil}

效率对比

这个执行时间可能每次都不一样,但是进过多次对比, 使用mapreduce 效率是高于普通方法的

使用串行调用时间:
在这里插入图片描述

使用MapReduce消耗时间:

在这里插入图片描述

相关文章:

go-zero(十三)使用MapReduce并发

go zero 使用MapReduce并发 一、MapReduce 介绍 MapReduce 是一种用于并行计算的编程模型&#xff0c;特别适合在大规模数据处理场景中简化逻辑代码。 官方文档&#xff1a; https://go-zero.dev/docs/components/mr 1. MapReduce 的核心概念 在 MapReduce 中&#xff0c;主…...

【实操之 图像处理与百度api-python版本】

1 cgg带你建个工程 如图 不然你的pip baidu-aip 用不了 先对图片进行一点处理 $ 灰度处理 $ 滤波处理 参考 import cv2 import os def preprocess_images(input_folder, output_folder):# 确保输出文件夹存在if not os.path.exists(output_folder):os.makedirs(output_fol…...

java 导出word锁定且部分内容解锁可编辑

使用 Apache POI 创建带编辑限制的 Word 文档 在日常工作中&#xff0c;我们可能需要生成一些带有编辑限制的 Word 文档&#xff0c;例如某些段落只能被查看&#xff0c;而其他段落可以自由编辑。本文介绍如何使用 Apache POI 创建这样的文档&#xff0c;并通过代码实现相应的…...

SQL 在线格式化 - 加菲工具

SQL 在线格式化 打开网站 加菲工具 选择“SQL 在线格式化” 或者直接访问 https://www.orcc.online/tools/sql 输入sql&#xff0c;点击上方的格式化按钮即可 输入框得到格式化后的sql结果...

大数据法律法规——《关键信息基础设施安全保护条例》(山东省大数据职称考试)

大数据分析应用-初级 第一部分 基础知识 一、大数据法律法规、政策文件、相关标准 二、计算机基础知识 三、信息化基础知识 四、密码学 五、大数据安全 六、数据库系统 七、数据仓库. 第二部分 专业知识 一、大数据技术与应用 二、大数据分析模型 三、数据科学 大数据法律法规…...

【CVE-2024-5660】ARM CPU漏洞:硬件页面聚合(HPA)安全通告

安全之安全(security)博客目录导读 目录 一、概述 二、修改历史 三、什么是硬件页面聚合? 四、修复解决 一、概述 在一些基于arm的cpu中发现了一个问题,该问题可能允许修改的、不受信任的客户机操作系统...

数智读书笔记系列008 智人之上:从石器时代到AI时代的信息网络简史

书名:智人之上&#xff1a;从石器时代到AI时代的信息网络简史 作者:&#xff3b;以&#xff3d;尤瓦尔赫拉利 译者:林俊宏 出版时间:2024-09-01 ISBN:9787521768527 中信出版集团制作发行 作者信息 尤瓦尔・赫拉利 1976 年出生于以色列海法&#xff0c;是牛津大学历史学…...

将 Ubuntu 22.04 LTS 升级到 24.04 LTS

Ubuntu 24.04 LTS 将支持 Ubuntu 桌面、Ubuntu 服务器和 Ubuntu Core 5 年&#xff0c;直到 2029 年 4 月。 本文将介绍如何将当前 Ubuntu 22.04 系统升级到最新 Ubuntu 24.04 LTS版本。 备份个人数据 以防万一&#xff0c;把系统中的重要数据自己备份一下~ 安装配置SSH访问…...

【自动驾驶】Ubuntu20.04安装ROS1 Noetic

【自动驾驶】Ubuntu20.04安装ROS1 Noetic 方式一&#xff1a;官方教程方式二&#xff1a;鱼香ROS脚本安装ROS配置rosdep配置ROS环境 测试ROS1 Noetic是否安装成功 方式一&#xff1a;官方教程 https://wiki.ros.org/noetic/Installation/Ubuntu 方式二&#xff1a;鱼香ROS脚本 …...

(转,自阅,侵删)【LaTeX学习笔记】一文入门LaTeX(超详细)

【LaTeX学习笔记】一文入门LaTeX&#xff08;超详细&#xff09;-阿里云开发者社区LaTeX中主要分为导言区和正文区导言区通常用于定义文档的格式、语言等&#xff08;全局设置&#xff09;。常用的LaTex命令主要有\documentclass&#xff0c;\usepackage等。下面分别对几个常用…...

css的选择器有哪些?权重由大到小是怎么排序的?

CSS选择器有很多种&#xff0c;下面是常见的选择器类型&#xff0c;并按照其权重&#xff08;即优先级&#xff09;从高到低进行排序。 CSS选择器类型 通用选择器 (*) &#xff08;通配符选择器&#xff09; 选择所有元素&#xff0c;权重最低。 例如&#xff1a;* { color:…...

CTF知识集-PHP特性

title: CTF知识集-PHP特性 写在开头可能会用到的提示 call_user_func 调用的函数可以不区分大小写preg_match过滤存在长度溢出&#xff0c;长度超过100w检测失效。str_repeat(‘show’,250000); 生成100w个字符preg_match是无法处理数组的&#xff0c;例如:preg_match( n u m…...

比特币是否会取代美元(以及其他主权货币)

上图是 Olivier Blanchard 宏观经济学第八版的英文版内容。这里用中文解释。 1. 背景与现状&#xff1a; 比特币的规模与美元相比仍然很小&#xff1a; 截至 2018 年 12 月&#xff0c;比特币的总流通量为 1730 万枚&#xff0c;每枚价值 $3,900&#xff0c;总市值约 $670 亿…...

WPF+MVVM案例实战与特效(三十七)- 实现带有水印和圆角的自定义 TextBox 控件

文章目录 1、概述2、案例实现1、基本功能2、代码实现3、控件应用4、案例效果4、总结1、概述 在开发用户界面时,TextBox 是最常见的输入控件之一。为了提升用户体验,我们经常需要为 TextBox 添加一些额外的功能,例如显示提示文本(水印)和设置圆角边框。本文将详细介绍如何…...

深度学习训练参数之学习率介绍

学习率 1. 什么是学习率 学习率是训练神经网络的重要超参数之一&#xff0c;它代表在每一次迭代中梯度向损失函数最优解移动的步长&#xff0c;通常用 η \eta η 表示。它的大小决定网络学习速度的快慢。在网络训练过程中&#xff0c;模型通过样本数据给出预测值&#xff0…...

导游现场面试需要注意的问题

今天给大家带来一些导游现场面试需要注意的问题&#xff0c;大部分的城市导游考试已经考完了&#xff0c;但是还有一些城市的十二月份才考&#xff0c;有需要的朋友们赶紧来看&#xff0c;有备无患。 01、做好充足准备 认真准备做好每个景点的讲解介绍&#xff0c;不要抱有侥幸…...

Burp suite 3 (泷羽sec)

声明 学习视频来自B站UP主 泷羽sec,如涉及侵泷羽sec权马上删除文章。 笔记只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 这节课旨在扩大自己在网络安全方面的知识面&#xff0c;了解网络安全领域的见闻&#xff0c;了…...

LabVIEW前面板无法显示的常见原因

当 LabVIEW 前面板显示为白色或黑色时&#xff0c;可能由于控件可视性设置、显卡驱动问题、程序错误或 LabVIEW 设置不当引起。通过检查面板设置、更新驱动、重启程序等方式可有效解决此问题。 遇到前面板无法显示或显示为白色/黑色的情况&#xff0c;可能有以下几种原因。可以…...

【Syncfusion系列】Diagram 杂谈 第三篇 序列化和反序列化

目录 序列化保存C# 代码示例&#xff0c; 方式1 &#xff1a;C# 代码示例&#xff0c; 方式2 &#xff1a; 反序列化加载C# 代码示例, 方式1&#xff1a;C# 代码示例, 方式2&#xff1a; **如何序列化自定义属性**序列化和反序列化都存在的一个问题解决方式 图表是否已修改&…...

Apache APISIX快速入门

本文将介绍Apache APISIX&#xff0c;这是一个开源API网关&#xff0c;可以处理速率限制选项&#xff0c;并且可以轻松地完全控制外部流量对内部后端API服务的访问。我们将看看是什么使它从其他网关服务中脱颖而出。我们还将详细讨论如何开始使用Apache APISIX网关。 在深入讨…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...