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

news2024/12/16 3:33:45

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 Articlelisthandler
    post /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循环产生文档ID
  generateFunc := 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.ArticleInfo
		
        for 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.ArticleInfo
    for 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 line
	time1 := time.Now()
	var articleList []types.ArticleInfo

	articleModel := l.svcCtx.ArticleModel
	for 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消耗时间:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索React与Microi吾码的完美结合:快速搭建项目,低代码便捷开发教程

一、摘要 在当今的数字化时代&#xff0c;软件开发就像是一场探险&#xff0c;每个开发者都是探险家&#xff0c;探索着代码的奥秘。React作为前端开发的领军框架&#xff0c;其组件化和高效的渲染机制为开发者提供了强大的工具。而Microi吾码低代码平台的出现&#xff0c;则为…

SAP FICO物料分类账实操

物料分类账所涉及到的差异从采购入库的时候就可能已经产生&#xff0c;接下来从创建物料主数据开始对可能产生差异地方进行分析。其中有些操作步骤在标准价格估算这一篇博文中已经有过演示&#xff0c;可以先做了解。 其中的某些创建在有直接可用的情况下是非必须的&#xff0…

WordPress酱茄主题 开源版 博客资讯自媒体网站模板

一款免费开源的WordPress主题&#xff0c;主题专为WordPress博客、资讯、自媒体网站而设计 运行环境 支持WordPress版本&#xff1a;5.6 兼容Chrome、Firefox、Safari等主流浏览器 支持设备&#xff1a;响应式布局&#xff0c;不同设备不同展示效果 服务器环境建议&#x…

【HF设计模式】03-装饰者模式

声明&#xff1a;仅为个人学习总结&#xff0c;还请批判性查看&#xff0c;如有不同观点&#xff0c;欢迎交流。 摘要 《Head First设计模式》第3章笔记&#xff1a;结合示例应用和代码&#xff0c;介绍装饰者模式&#xff0c;包括遇到的问题、遵循的 OO 原则、达到的效果。 …

Linux查看是否有www-data用户,如果没有添加一个

在 Linux 系统中&#xff0c;www-data 用户通常是用来运行 Web 服务&#xff08;如 Nginx 或 Apache&#xff09;的。如果你想检查系统中是否已经存在 www-data 用户&#xff0c;并在没有的情况下添加一个&#xff0c;可以按照以下步骤操作&#xff1a; ### 1. 检查 www-data …

23.模块和包

模块 模块Module,是一个python文件&#xff0c;以.py结尾。 模块能定义函数、类和变量。 模块导入 模块在使用前需要先导入 [from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名] import 模块 import time print("start...") time.sleep(5) print(&…

IDEA报错:无效的源发行版、无效的目标发行版

1. 无效的源发行版 创建项目的时候&#xff0c;会遇见这个报错&#xff0c;原因就是编译的JDK版本与发布版本不一致。 解决方法&#xff1a; 1.1. 找到问题所在地 英文&#xff1a;File -> Project Structure ->Project Settings 中文&#xff1a;文件->项目结构 …

2025年,客服知识库与人工智能的结合

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;传统客服模式正在经历前所未有的变革。特别是在2025年&#xff0c;客服知识库与AI的深度融合&#xff0c;不仅极大地提升了客服处理的效率与准确性&#xff0c;还为用户带来了更加个性化、高效的服务体验。 …

JVM 双亲委派模型以及垃圾回收机制

目录 1. JVM 内存区域划分 2. JVM 中类加载的过程 1) 类加载的基本流程 2) 双亲委派模型 3. JVM 中垃圾回收机制 1) 找到垃圾 a) 引用计数 b) 可达性分析 2) 释放垃圾 1. JVM 内存区域划分 一个运行起来的 Java 进程&#xff0c;其实就是一个 JVM 虚拟机。 而进程是…

微信小程序跳转其他小程序以及跳转网站

一、跳转其他小程序 1.1 知道appid和页面路径 wx.navigateToMiniProgram({appId: appid, // 替换为目标小程序 AppIDpath: pathWithParams, // 小程序路径envVersion: release, // 开发版、体验版或正式版success(res) {console.log("跳转到其他小程序成功&#xff01;&q…

学习笔记:从ncsi/nc-si协议和代码了解网络协议的设计范式

学习笔记&#xff1a;从ncsi/nc-si协议和代码了解网络协议的设计范式 参考文档&#xff1a; https://www.dmtf.org/standards/published_documents https://www.dmtf.org/dsp/DSP0222 https://www.dmtf.org/sites/default/files/standards/documents/DSP0222_1.2.0.pdf参考代…

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

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

【数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;编写一个程序实现单链表的基本运算。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;初始化线性表、销毁线性表、判定是否为空表、求线性…

利用ROS的Camera Calibration工具进行D435相机标定

一、安装ROS Camera Calibration sudo apt-get install ros-melodic-camera-calibration 二、安装realsense-ros 安装ROS Wrapper for Intel RealSense&#xff08;realsense-ros&#xff09; 三、启动数据读取节点 ctrlaltt打开终端 cd catkin_ws_ur source devel/setu…

让文案生成更具灵活性/chatGPT新功能canvas画布编辑

​ ​ OpenAI最近在2024年12月发布了canvas画布编辑功能&#xff0c;这是一项用途广泛的创新工具&#xff0c;专为需要高效创作文案的用户设计。 无论是职场人士、学生还是创作者&#xff0c;这项功能都能帮助快速生成、优化和编辑文案&#xff0c;提升效率的同时提高内容质量…

C# 网络编程--关于UDP 通信(二)

UDP (User Datagram Protocol) 是一种无连接的传输层协议&#xff0c;主要用于支持数据报文的传输。它的主要特点包括简单、高效、不保证可靠性和顺序。 1.UDP协议基本概念 1.udp基于IP的简单的协议&#xff0c;不可靠的协议 2.优点&#xff1a;简单、 轻量化、 传输速度高、…

Spring Boot 集成 MyBatis 全面讲解

Spring Boot 集成 MyBatis 全面讲解 MyBatis 是一款优秀的持久层框架&#xff0c;与 Spring Boot 集成后可以大大简化开发流程。本文将全面讲解如何在 Spring Boot 中集成 MyBatis&#xff0c;包括环境配置、基础操作、高级功能和最佳实践。 一、MyBatis 简介 1. SqlSession …

解决Jmeter HTTP Cookie管理器cookie不生效

解决Jmeter HTTP Cookie管理器cookie不生效问题 解决Jmeter HTTP Cookie管理器cookie不生效问题1、设置Jmeter HTTP Cookie管理器cookie后&#xff0c;发起的请求显示[no cookies]jmeter问题复现&#xff1a;这里同样使用postman进行重试&#xff0c;发现是可以正常获取数据的&…

freeswitch(开启支持MCU视频会议,使用mod_av模块)

亲测版本centos 7.9系统–》 freeswitch1.10.9 本人freeswitch安装路径(根据自己的路径进入) /usr/local/freeswitch/etc/freeswitch场景说明: 有些场景想使用视频会议MCU融合画面进行开会使用方法: 第一步:下载插件 yum install -y epel-release yum install

IntelliJ IDEA 使用技巧与插件推荐

目录 常用使用技巧 1. 使用快捷键提升开发效率 2. 多光标编辑 3. 代码自动补全 4. 使用 Find Action 快速执行操作 5. 集成版本控制系统&#xff08;VCS&#xff09; 6. 快速查看代码文档 推荐插件 1. Lombok Plugin 2. Rainbow Brackets 3. Key Promoter X 4. Chec…