脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Golang编程并发工具库MapReduce使用实践

Golang编程并发工具库MapReduce使用实践

2022-09-29 15:34EvaCcino Golang

这篇文章主要为大家介绍了Golang并发工具库MapReduce的使用实践,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

环境

?
1
2
go version go1.16.4 windows/amd64
Intel(R) Core(TM) i7-7820HK CPU @ 2.90GHz 4核心8线程

项目需求

处理数个约5MB的小文件

从源目录读取文件并拷贝到目标目录

计算源文件MD5和目标文件MD5进行对比,如不相同则报错并终止程序执行

mapReduce使用说明

?
1
go get -u github.com/tal-tech/go-zero

需求实现

判断上下文是否中止 → 读取数据 → 写入数据 → 校验MD5

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func fnBuilder(name string) func() error {
  return func() error {
       // 判断上下文是否终止
       select {
       case <-ctx.Done():
         return ctx.Err()
       default:
       }
       // 读取源数据
       data, _err := os.ReadFile(filepath.Join(sourcePath, fileName))
       // 计算源数据MD5
       sourceMD5 := hash.Md5(data)
       // 获取名称
       fields := strings.Split(d.Name(), "-")
       // 目标文件路径
       distFilePath := filepath.Join(distPath, fileName)
       // 拷贝数据
       os.WriteFile(distFilePath, data, 0600)
       // 校验数据
       distData, _err := os.ReadFile(distFilePath)
       distMD5 := hash.Md5(distData)
       if !bytes.EqualFold(sourceMD5, distMD5) {
         return errors.New("md5校验失败")
       }
       return nil
     }
}

业务逻辑

创建任务队列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
type SourceMap = map[string]fs.DirEntry
func CopyFileToDist(ctx context.Context, source SourceMap) (err error) {
  // 创建工作队列
  work := make([]func() error, 0, len(source))
  for _name := range source {
    // 创建任务
    work = append(work, fnBuilder(_name))
  }
  switch concurrency {
  default:
    // mapReduce
  case 1:
    // sync.waitGroup
  case 2:
    // 串行
  }
}

执行方式1:MapReduce

?
1
2
3
4
5
func() {
   if err = mr.Finish(work...); err != nil {
     return err
   }
}

执行方式2:sync.WaitGroup

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func() {
    var wg sync.WaitGroup
    wg.Add(len(work))
    for k := range work {
      go func(index int) {
        defer wg.Done()
        if err = work[index](); err != nil {
          log.Errorln(err)
          return
        }
      }(k)
    }
    wg.Wait()
}

执行方式3:串行

?
1
2
3
4
5
6
7
func() {
    for _, fn := range work {
      if err = fn(); err != nil {
        return err
      }
    }
}

运行结果

MapReduce

耗时 109220900 ns

?
1
2
{"file":"D:/go/src/filenamesSorter/main.go:44","func":"main.init.0","level":"info","msg":"并发处理(0-mapReduce 1-Sync.WaitGroup 2-不并发) 0","time":"2021-06-02T13:32:05+08:00"}
{"file":"D:/go/src/filenamesSorter/main.go:69","func":"main.main","level":"info","msg":"文件分类完毕","time":"2021-06-02T13:32:05+08:00","文件数":17,"耗时(ns)":109220900}

sync.WaitGroup

耗时 109798000 ns

?
1
2
{"file":"D:/go/src/filenamesSorter/main.go:44","func":"main.init.0","level":"info","msg":"并发处理(0-mapReduce 1-Sync.WaitGroup 2-不并发) 1","time":"2021-06-02T13:31:28+08:00"}
{"file":"D:/go/src/filenamesSorter/main.go:69","func":"main.main","level":"info","msg":"文件分类完毕","time":"2021-06-02T13:31:28+08:00","文件数":17,"耗时(ns)":109798000}

串行

耗时 359307700 ns

?
1
2
{"file":"D:/go/src/filenamesSorter/main.go:44","func":"main.init.0","level":"info","msg":"并发处理(0-mapReduce 1-Sync.WaitGroup 2-不并发) 2","time":"2021-06-02T13:33:02+08:00"}
{"file":"D:/go/src/filenamesSorter/main.go:69","func":"main.main","level":"info","msg":"文件分类完毕","time":"2021-06-02T13:33:02+08:00","文件数":17,"耗时(ns)":359307700}

结论

  • 在不严格的情况下,执行效率方面可以认为 mapReduce ≈ sync.WaitGroup
  • 易用性(包括并发和错误处理),mapReduce 完胜 sync.WaitGroup
  • mapReduce好用

引申阅读

通过MapReduce降低服务响应时间

以上就是Golang编程并发工具库MapReduce使用实践的详细内容,更多关于Golang并发工具库MapReduce的资料请关注服务器之家其它相关文章!

原文链接:https://blog.csdn.net/yes169yes123/article/details/117467920

延伸 · 阅读

精彩推荐
  • Golang详解Go 创建命令行工具的方法

    详解Go 创建命令行工具的方法

    这篇文章主要介绍了详解Go 创建命令行工具,需要的朋友可以参考下...

    crossoverJie9372021-02-23
  • Golanggo如何利用orm简单实现接口分布式锁

    go如何利用orm简单实现接口分布式锁

    本篇文章主要介绍了go如何利用orm简单实现接口分布式锁,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...

    zx2792020-05-17
  • GolangGolang实现AES对称加密的过程详解

    Golang实现AES对称加密的过程详解

    AES是一个对称密码,旨在取代DES成为广泛使用的标准,本文给大家分享Golang实现AES对称加密的过程,本文附有Golang实现AES加密ECB模式的源码,感兴趣的朋友...

    写Golang的小张9052021-06-27
  • GolangGolang使用lua脚本实现redis原子操作

    Golang使用lua脚本实现redis原子操作

    这篇文章主要介绍了Golang使用lua脚本实现redis原子操作,本文通过实例代码给大家介绍的非常详细,对大家的工作或学习具有一定的参考借鉴价值,需要的朋...

    GrassInWind201910242020-06-06
  • Golang详解Go 语言中的比较操作符

    详解Go 语言中的比较操作符

    这篇文章专注于 6 个操作符,==,!=,<,<=,> 和 >=。我们将深入探讨它们的语法和用法的细微差别,感兴趣的朋友跟随脚本之家小编一起看看吧 ...

    themoonbear6192020-05-17
  • Golang项目实战:使用 Fiber + Gorm 构建 Rest API

    项目实战:使用 Fiber + Gorm 构建 Rest API

    Fiber 作为一个新的 Go 框架,似乎受追捧程度很高,Star 数飙升很快。不知道这是不是表明,不少 JS/Node 爱好者开始尝试学习 Go 了,对 Go 是好事。...

    幽鬼13372022-01-07
  • Golanggolang爬虫colly 发送post请求

    golang爬虫colly 发送post请求

    本文主要介绍了golang爬虫colly 发送post请求实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随...

    liuyuncd8902022-07-11
  • GolangGolang通过小程序获取微信openid的方法示例

    Golang通过小程序获取微信openid的方法示例

    这篇文章主要介绍了Golang通过小程序获取微信openid的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    Rollover7442020-06-07