COS 418/MIT6.824 MapReduce

关于map reduce

a.是一种编程框架,将任务分解成多份,交给不同的机器执行

b.MapReduce将任务分为两部分来执行
[map阶段]:处理原始任务,产生包含"中间结果"的键值对的中间文件
[reduce阶段]:处理中间文件,产生包含最后结果的文件
*需要注意的是,这里的map和reduce是用户自定义函数。

c.框架共包含一个master和多个worker master负责给每一个worker分配任务,也负责管理每一个任务的状态。worker负责执行具体的任务,包括map和reduce。

在这里插入图片描述
要实现的mapreduce框架分为两个版本,一个是sequentia顺序版本,“顺序”说的是一个map任务执行完之后才执行下一个map任务,当所有的map任务执行完之后,才开始按“顺序执行”reduce任务。第二个是distributed版本,这个版本中,map任务是并发执行的,但也是执行完所有的map任务之后才去执行reduce任务。

流程

说明:从wc.go中的main开始执行,接着执行master.go中的run,然后由run中的schedule来进行调度任务,在schedule中调用了框架的doMap和doReduce,其中又分别调用了用户定义的mapF和reduceF。其中顺序版本是顺序执行,并发版本是通过rpc来并发执行。

将分布式框架和application代码分隔开,相当于写接口;
split:input into chunks
Maps:take files as input,generate list of <key,value>
Reduce:MapReduce framework collect all <k,v> with same key, then hand them to reduce function

1.application部分只需写好wordCount功能

Map(k,v)
	split v into words
	for each word w:
		emit(w,"1")

Reduce(k,v)
	emit(len(v))

实际操作遇到的问题

1.调同在src的别的包时飘红:
在src下用go mod init src;

2.在同一个文件夹下的两个go文件func了一样的函数名:
让两个go文件不在同一个文件夹中(加一个文件夹),或让两个go文件中不存在相同的函数名(修改一个其中函数名);

3.go中到底什么是包:
一个包就是由一个或多个源文件组成,各个源文件都可以访问包内的内容(包括 变量、常量、类型、函数等)。包在源文件层面的组织就是文件夹,通常把一个包的所有源文件放在一个文件夹中。
main 包比较特殊,因为它必须包含一个 main 函数;而且它必须位于程序的根目录。
所以包究竟是什么:包在程序层面就是所有使用相同 package 的源文件组成的代码模块;在源文件层面就是一个文件夹。
一个包所有的文件,必须位于同一个目录下包名自然可以和文件夹名不一样,毕竟一个是导入路径,一个是包名。但不建议这么做,这样容易造成调用这个包的人,无法快速知道这个包的名称是什么。
至于为什么不用目录名作为包名,是为了避免目录中出现奇怪的字符,也为了调用者方便使用
在执行导入的时候,若不手动定义包名,则从导入路径的源码文件中的 package 行获取包名,也即目录名和包名没有直接的关系。

4.利用go module管理包时,发现如果工作目录未设置为gopath,则导入工作目录下的自定义包会报错“xx包不在GOROOT中”:
import后面的其实是GOPATH开始的相对目录路径,包括最后一段。但由于一个目录下只能有一个package,所以import一个路径就等于是import了这个路径下的包。配置环境变量将工作目录加入到GOPATH中,重启生效。接下来import自定义包时注意文件路径(e.g. src/mapreduce)

5.要把在自定义包外部使用的变量或者函数的首字母大写,外部才可以访问它们。

函数调用

strings.Split( , )

 s := strings.Split("", "")
fmt.Println(s, len(s))
s = strings.Split("abc,abc", "")
fmt.Println(s, len(s))
s = strings.Split("", ",")
fmt.Println(s, len(s))
s = strings.Split("abc,abc", ",")
fmt.Println(s, len(s))
s = strings.Split("abc,abc", "|")
fmt.Println(s, len(s))
fmt.Println(len(""))
fmt.Println(len([]string{""}))
str := ""
fmt.Println(str[0])

运行结果:
[] 0 //返回空数组
[a b c , a b c] 7 //返回7个数组元素
[] 1 //返回一个包含空字符元素的数组, 数组长度是1
[abc abc] 2
[abc,abc] 1
0
1
panic: runtime error: index out of range

打印变量类型

(导入reflect包)
fmt.Println(reflect.TypeOf(var))

strconv包的atoi和itoa

string转int和int转string

import (
    "strconv"
    "fmt"
    "reflect"
)
     
func main() {
    i, err := strconv.Atoi("12345")
    if err != nil {
        panic(err)
    }
    fmt.Println(i,reflect.TypeOf(i)) 
    i += 3
    fmt.Println(i)
     
    s := strconv.Itoa(12345)
    fmt.Println(s,reflect.TypeOf(s)) 
    s += "3"
    fmt.Println(s)
}

fmt.Sscanf()

Sscanf扫描参数字符串,将连续的以空格分隔的值存储到由格式确定的连续的参数中。 它返回成功解析的项目数。输入中的换行符必须与格式中的换行符匹配。

func Sscanf(str string, format string, a ...interface{}) (n int, err error) {
	return Fscanf((*stringReader)(&str), format, a...)
}

Fscanf扫描从r读取的文本,将连续的以空格分隔的值存储到由格式确定的连续的参数中。 它返回成功解析的项目数。输入中的换行符必须与格式中的换行符匹配。

func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error) {
	s, old := newScanState(r, false, false)
	n, err = s.doScanf(format, a)
	s.free(old)
	return
}

例子:

n, err := fmt.Sscanf(lines[i], "%d", &v1)   //读取lines[i],将其转换为int型的v1

encoding/json中的Encoder与Decoder

Abstract
介绍go语言中json的使用

json
json是一种传输格式,类似与XML,与XML相比可读性略差,但是传输效率高。

GO Json
go语言中提供了json的encoder,可以将数据结构转换为json格式。在使用之前,需要导入包

import "encoding/json"

Encode
使用

func NewEncoder(w io.Writer) *Encoder

创建一个json的encode。

file, _ := os.Create("json.txt")
enc := json.NewEncoder(file)
err := enc.Encode(&v)

数据结构v会以json格式写入json.txt文件。

Decode
使用

func NewDecoder(r io.Reader) *Decoder

创建一个json的decode。

fp, _ os.Open("json.txt")
dec := json.NewDecoder(fp)
for {
    var V v
    err := dec.Decode(&v)
    if err != nil {
        break
    }
    //use v
}

v是一个数据结构空间,decoder会将文件中的json格式按照v的定义转化,存在v中。

Example

type Person struct {
    name string
    age int
}

type Student struct {
    p *Person
    sno int
}

对于Student类型,虽然里面有一个指针,gojson一样可以处理。在encode与decode时,会自动的递归下降的进行格式转换。

Summary
encoder与decoder像是在writer外面封装了一层。会根据指定的数据结构的格式进行读写。如果文件中的json格式与指定的数据结构的格式不一致会出现error。
在decoder的过程中,用一个for{}不停的读文件,直到出现error,代表文件结束。在for{}中,每次都要申请一个新的空间,存放从文件中读取出来的数据。

os.Create(filename)

Create采用模式0666(任何人都可读写,不可执行)创建一个名为filename的文件,如果文件已存在会截断它(为空文件)。
如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。如果出错,错误底层类型是*PathError。
删除文件与截断文件的区别:
1)删除的话文件系统内对应这个文件的索引就没了,相应的块也全部回收,也就是说你无法再正常访问这个文件了,虽然文件内容可能还残留在盘上。
2)截断是把一个文件删一部分留一部分,体现在于这个文件变小了,占用的块可能也减少了。但是再超级快中或者根目录中还是能一层一层索引到这个文件,除非你把文件截断成0,那就直接删除了。没记错的话linux的文件删除操作的底层实现其实就是截断,把文件截断为0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值