发布于 2020-03-09   513人围观   0条评论

摘要

我们设计和实现了谷歌文件系统,一个面向大规模分布式数据密集型应用的可伸缩文件系统。即使在普通廉价的商用机器上,它也提供了容灾和高性能服务。

GFS的设计目标和传统分布式文件系统类似,但是我们的设计和实现是由我们的应用负载和技术环境驱动的。不管是现在还是将来,GFS和早起的设想都有出入,我们重新审视了传统文件系统在设计上的折中选择,并衍生出完全不同的设计思路。

GFS完全满足我们对存储的需求。Google内部广泛使用GFS生成和处理大数据集。最大的集群使用数千台机器,提供了数百T的存储空间,服务于数百台客户机。

本文介绍GFS对于分布式应用的接口支持和扩展,讨论GFS的设计思路和细节,列出小规模测试和生产环境中的性能数据。

1. Introduction

GFS的设计和实现是为了满足谷歌快速增长的数据处理需求。GFS和传统的分布式文件系统具有许多相同的设计目标,如性能、可伸缩性、可靠性、可用性。但是,其设计由我们的技术环境驱动而来,因此和早期的文件系统又有着标志性的不同。我们考虑了传统文件系统的折衷选择,并给出了完全不同的设计思路。

首先,组件失败被认为是常态事件,而非意外事件。GFS包括数百台甚至数千台机器,支持可观数量的客户机访问。在任何时刻,机器组件都有可能发生故障,或者无法恢复有效服务。我们曾经遇到过程序bug、操作系统bug、人为失误、磁盘损坏、内存损坏、网络故障、电源损坏等各种各样的问题。所以,持续的监控、错误检测、容错和自动恢复等机制需要集成到GFS中。

其次,以传统的角度看,我们的文件庞大,数G大小的文件非常普遍。。每个文件通常包含许多应用程序对象,比如web文档。当处理数亿个对象构成的数以TB的数据集时,采用管理数亿个KB大小的小文件的方式是不明智的,尽管有些文件系统支持。因此,I/O操作、文件块尺寸等因素都需要重新考虑。

第三,绝大多数文件通过在文件尾部添加新数据的方式修改,而不是覆写已有数据。对文件的随机写入,在实际生产环境中几乎不存在。一旦文件写入完成,那么这些文件通常是只读,并且是按顺序读。比如,数据分析程序扫描超大数据集;正在运行的程序不断生成数据流;已归档的数据;一台机器上生成的中间结果,会被

查看更多
发布于 2020-03-08   548人围观   0条评论

6.824实验的基础设施:RPC和线程

Go中的线程和RPC,以及Go Tour中的一些练习

为什么使用Go作为lab的编程语言

线程

常用的结构化工具,但是使用起来会有各种各样的trick。在Go中,被称作goroutines。线程的存在,使得一个程序可以并发的处理多项任务。线程共享内存空间,线程不共享的有程序计数器、线程栈、寄存器。

在分布式系统中,我们需要线程的并行语义:
1. I/O并发。多个客户端发送请求并等待响应,服务端处理多个客户端请求。当在等待读取客户端X的数据时,可以利用等待的时间去处理客户端Y的请求。
2. 多核性能。代码可以并行地在多个cpu核里运行。
3. 便捷

线程有无替代品

事件驱动,就是线程的替代品。即,在一个线程中,活动状态交织,其实就是状态机。维护一个数据结构,保存每个活动的状态,比如,每个客户端请求。

开启一个事件循环,监听每个活动的输入(比如,服务端的响应到达),然后切换该活动到下一状态。

事件驱动,也可以实现I/O并发,并且避免线程切换的开销,但是浪费了多核编程环境。

多线程编程的难点

  • 数据共享
    • 比如,如果两个线程同时执行n = n + 1,或者,一个线程增加n时,另外一个线程读取n。这时候需要利用锁机制(Go里面有sync.Mutex),或者,避免共享可变对象数据。
  • 线程之间的条件竞争
    • 比如一个线程在生产数据,另外一个消耗数据。那么消费者怎么等待数据,生产者怎么唤醒消费者。Go中使用Go channel、sync.Cond、WaitGroup等数据结构解决该问题。
  • 死锁
    • RPC或者Go channels中可能产生死锁

Web Crawler

爬虫需要注意的两个问题:
1. I/O并发
多个线程,同时爬取多个网址
2. 每个URL只处理一次,避免重复处理
维护一个数据结构记录已经处理过的url,并且知道爬取程序的终止条件

crawler.go有两种解决方式

查看更多
周报    发布于 2020-03-02   52人围观   0条评论

摘要

MapReduce是一种用来处理和生成大数据集的编程模型以及相关实现。用户选定一个map函数,该map函数的输入是一个键值对,输出是一系列中间键值对。然后用户选定一个reduce函数,该reduce函数用于处理具有相同键的所有中间键值对,并得到结果。实际生产中,有大量应用可以用此模型描述。

这种编程模型可以在集群上并行工作。运行时系统会自动分割输入数据、分发任务到各个机器、处理任务失败或者机器故障、管理必要的机器间通信。因此,即使没有分布式系统经验的程序员,也可以方便地利用分布式系统的资源。

现在每天有大量MapReduce模型的工程运行于谷歌集群,其具有高度的扩展性,一个典型的MapReduce计算可以利用集群处理TB级别的数据集。

1.介绍

过去数年,大量特殊目的的计算程序被设计出来,用于处理大量的原始数据集,比如爬虫结果、网络请求日志,来得到需要的衍生数据,比如倒排索引、web文档的图结构、某日查询最多的关键词。虽然这类计算在概念上非常直观,但是由于输入数据集非常庞大,因此需要将这些输入数据集切割、分发到多个机器上处理。但是除了原来本有的计算模型外,还需要编写大量复杂的代码去处理并行化计算、数据分发、故障处理等问题。

因此我们干脆设计一种新的抽象,将并行计算、容错、数据分发、负载均衡这些复杂技术细节隐藏起来,交给库去完成,我们只需要定义计算模型即可。这种抽象的灵感来自于Lisp等函数式编程语言中的Map和Reduce原语。我们意识到许多计算都需要对输入的每个记录应用一个"map"操作来得到中间一系列键值对,之后再对所有拥有相同键的值应用"reduce"操作,得到衍生数据集。因此如果一个编程模型,允许我们通过定义map操作和reduce操作,那我们就可以方便设计大量并行计算,并且我们可以使用重新执行作为主要的容错机制。

这次工作的主要贡献是提供一个简单而强大的接口,可以使用这个接口完成自动并行化和大规模分布式计算,并且该接口的实现在大型商用集群上性能卓然。

本文第二章给出基本编程模型以及一些栗子。第三章介绍为集群计算环境量身定做的MapReduce接口。第四章介绍一些对于编程模型的改进。第五章测试了我们的实现在不同任务

查看更多
go    发布于 2019-11-04   301人围观   0条评论

终端挂代理

因为electron-ssr已经提供了http的代理。
如需要在终端中挂上代理,输入

  1. export http_proxy="http://127.0.0.1:12333"
  2. export https_proxy="http://127.0.0.1:12333"

Go官网教程(A tour of Go)

从官网下载一个tour教程包

  1. go get golang.org/x/tour

工作路径bin目录下会出现tour二进制,运行tour程序会打开一个本地站点

分三部分
1. 基本语法和数据结构
2. 方法和接口
3. 并发原语

学习过程中的一些笔记

第一部分

Go项目均由packages构成, 项目从main包开始运行
如果变量名以大写字母开头,则该变量对外可见,即导出。否则,外界不可见,且无法使用
为何go变量的类型声明与c系语言不同?go的类型声明在做复杂的函数签名时更易读
slice与array
map特性
make方法,既可以用来创建slice,也可以用来创建map

第二部分

方法:Go中没有类的概念,但是可以在函数的基础上得到方法。即,在func和函数名之间插入某个类型的调用者(receiver)。本质上,还是一个函数。等价于将receiver作为第一个参数传入函数。receiver的类型定义必须在同一个package中

接收器分为两种value receiver和point receiver。方法中对value receiver的修改不会影响到方法外,对point receiver的修改会影响到方法外

value receiver的调用可以被转换为对point receiver的调用
point receiver的调用可以被转化为对value receiver的调用

使用point receiver的两个优点:
1. 该方法需要修改receiver指向的值
2. 可以避免值拷贝

接口:一些方法签名的集合。也可以看作是一种类型。当某些类型实现了接口中的方法,那么这些类型可以赋值给接口类型定义的变量。

如果某些类型拥有相同的方法集合,那么可以定义一个

查看更多
linux    发布于 2019-07-31   324人围观   0条评论

epoll_create

  1. #include <sys/epoll.h>
  2. int epoll_create(int size);

epoll_create()创建一个新的epoll对象,并返回一个文件描述符指向该epoll对象。
size表示,该epoll对象可能要监听的文件描述符数量,内核会使用该建议值分配内部的数据结构,当然之后如果空间不够用,内核会分配更多的空间。
linux2.6.8之后,size参数被忽略(但是仍然必须大于0)。
参考epoll_create - Linux manual page - man7.org

epoll_ctl

  1. #include <sys/epoll.h>
  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

epfd即epoll_create返回的描述符,用于管理用户关心的文件描述符。epoll_ctl用于添加、修改、删除epoll对象中的fd及该fd关联的事件监听。

op的值:

  • EPOLL_CTL_ADD
  • EPOLL_CTL_MOD
  • EPOLL_CTL_DEL

event的定义

  1. typedef union epoll_data {
  2. void *ptr;
  3. int fd;
  4. uint32_t u32;
  5. uint64_t u64;
  6. } epoll_data_t;
  7. struct epoll_event {
  8. uint32_t events; // Epoll Events
  9. epoll_data_t data; // User Data Variable
  10. }

成员events的值

  • EPOLLIN 可读
  • EPOLLOUT 可写
  • EPOLLET 设置边缘触发。默认水平触发
  • ...其他

参考epoll_ctl - Linux manual page - man7.org

epoll_wait

  1. #include <sys/epoll.h>
  2. int epoll_wait(int epfd, struct epoll_event *events, int maxevents, i
查看更多