在Scala中case class

 1、初始化的时候可以不用new,当然你也可以加上,普通类一定需要加new;

 2、toString的实现更漂亮;

 3、默认实现了equals 和hashCode;

 4、默认是可以序列化的,也就是实现了Serializable ;

 5、自动从scala.Product中继承一些函数;

 6、case class构造函数的参数是public级别的,我们可以直接访问;

 7、支持模式匹配;
  其实感觉case class最重要的特性应该就是支持模式匹配。这也是我们定义case class的唯一理由,难怪Scala官方也说:It makes only sense to define case classes if pattern matching is used to decompose data structures.。

How do I find all files containing specific text on Linux?

Do the following:

grep -rnw '/path/to/somewhere/' -e 'pattern'
  • -r or -R is recursive,
  • -n is line number, and
  • -w stands for match the whole word.
  • -l (lower-case L) can be added to just give the file name of matching files.

Along with these, --exclude, --include, --exclude-dir flags could be used for efficient searching:

  • This will only search through those files which have .c or .h extensions:
    grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
    
  • This will exclude searching all the files ending with .o extension:
    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
  • For directories it’s possible to exclude a particular directory(ies) through --exclude-dirparameter. For example, this will exclude the dirs dir1/, dir2/ and all of them matching *.dst/:
    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

This works very well for me, to achieve almost the same purpose like yours.

For more options check man grep.

Generate 16-digit unique code (like product serial)

static final private String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
final private Random rng = new SecureRandom();    

char randomChar(){
    return ALPHABET.charAt(rng.nextInt(ALPHABET.length()));
}

String randomUUID(int length, int spacing, char spacerChar){
    StringBuilder sb = new StringBuilder();
    int spacer = 0;
    while(length > 0){
        if(spacer == spacing){
            sb.append(spacerChar);
            spacer = 0;
        }
        length--;
        spacer++;
        sb.append(randomChar());
    }
    return sb;
}

使用webmagic构建一个分布式的爬虫

public class RedisScheduler implements Scheduler{

    private JedisPool pool;

    private static final String QUEUE_PREFIX = "queue_";

    private static final String SET_PREFIX = "set_";

    public RedisScheduler(String host){
        pool = new JedisPool(new JedisPoolConfig(), host);
    }

    @Override
    public void push(Request request, Task task) {
        Jedis jedis = pool.getResource();
          //使用SortedSet进行url去重
        if (jedis.zrank(SET_PREFIX+task.getUUID(),request.getUrl())==null){
            //使用List保存队列
            jedis.rpush(QUEUE_PREFIX+task.getUUID(),request.getUrl());
            jedis.zadd(SET_PREFIX+task.getUUID(),System.currentTimeMillis(),request.getUrl());
        }
    }

    @Override
    public Request poll(Task task) {
        Jedis jedis = pool.getResource();
        String url = jedis.lpop(QUEUE_PREFIX+task.getUUID());
            if (url==null) {
                return null;
            }
        return new Request(url);
    }
}

Hadoop YARN介绍

原文

YARN是Hadoop集群的资源管理系统。Hadoop2.0对MapReduce框架做了彻底的设计重构。YARN的基本设计思想是将MRv1中的JobTracker拆分成了两个独立的服务:一个全局的资源管理器ResourceManager每个应用程序特有的ApplicationMaster。其中ResourceManager负责整个系统的资源管理和分配,而ApplicationMaster负责单个应用程序的管理

YARN产生背景

MRv1的局限

YARN是在MRv1基础上演化而来的,它克服了MRv1中的各种局限性。在正式介绍YARN之前,先了解下MRv1的一些局限性,主要有以下几个方面:

  • 扩展性差。在MRv1中,JobTracker同时兼备了资源管理作业控制两个功能,这成为系统的一个最大瓶颈,严重制约了Hadoop集群扩展性。
  • 可靠性差。MRv1采用了master/slave结构,其中,master存在单点故障问题,一旦它出现故障将导致整个集群不可用。
  • 资源利用率低。MRv1采用了基于槽位的资源分配模型,槽位是一种粗粒度的资源划分单位,通常一个任务不会用完槽位对应的资源,且其他任务也无法使用这些空闲资源。此外,Hadoop将槽位分为Map Slot和Reduce Slot两种,且不允许它们之间共享,常常会导致一种槽位资源紧张而另外一种闲置(比如一个作业刚刚提交时,只会运行Map Task,此时Reduce Slot闲置)。
  • 无法支持多种计算框架。随着互联网高速发展,MapReduce这种基于磁盘的离线计算框架已经不能满足应用要求,从而出现了一些新的计算框架,包括内存计算框架、流式计算框架和迭代式计算框架等,而MRv1不能支持多种计算框架并存。

为了克服以上几个缺点,Apache开始尝试对Hadoop进行升级改造,进而诞生了更加先进的下一代MapReduce计算框架MRv2。正是由于MRv2将资源管理功能抽象成了一个独立的通用系统YARN,直接导致下一代MapReduce的核心从单一的计算框架MapReduce转移为通用的资源管理系统YARN。

集群资源统一管理

随着互联网的高速发展,新的计算框架不断出现,从支持离线处理的MapReduce,到支持在线处理的Storm,从迭代式计算框架Spark到流式处理框架S4,各种框架各有所长,各自解决了某一类应用问题。这时候就需要一个组件对同一个集群上的不同计算框架进行资源的统一管理。

YARN

相比于“一种计算框架一个集群”的模式,共享集群的模式存在多种好处:

  • 资源利用率高。如果每个框架一个集群,可能在某段时间内,有些计算框架的集群资源紧张,而另外一些集群资源空闲。共享集群模式则通过多种框架共享资源,使得集群中的资源得到更加充分的利用。
  • 运维成本低。如果采用“一个框架一个集群”的模式,则可能需要多个管理员管理这些集群,进而增加运维成本,而共享模式通常需要少数管理员即可完成多个框架的统一管理。
  • 数据共享。随着数据量的暴增,跨集群间的数据移动不仅需花费更长的时间,且硬件成本也会大大增加,而共享集群模式可让多种框架共享数据和硬件资源,将大大减小数据移动带来的成本。

YARN基本设计思想

MRv1主要由编程模型、数据处理引擎(由Map Task和Reduce Task组成)和运行时环境三部分组成。为了保证编程模型的向后兼容性,MRv2重用了MRv1中的编程模型和数据处理引擎,但运行时环境被完全重写。

MRv1的运行时环境主要由两类服务组成,分别是JobTracker和TaskTracker。其中,JobTracker负责资源管理作业控制。TaskTracker负责单个节点资源管理和任务执行

MRv1将资源管理和应用程序管理两部分混杂在一起,使得它在扩展性、容错性和多框架支持等方面存在明显缺陷。

而MRv2则通过将资源管理和应用程序管理两部分剥离开,分别由ResourceManager和ApplicationMaster负责,其中ResourceManager专管资源管理和调度,而ApplicationMaster则负责与具体应用程序相关的任务切分、任务调度和容错等,具体如下图所示。

Paste_Image.png

YARN基本架构

YARN是Hadoop 2.0中的资源管理系统,它的基本设计思想是将MRv1中的JobTracker拆分成了两个独立的服务:一个全局的资源管理器ResourceManager每个应用程序特有的ApplicationMaster。其中ResourceManager负责整个系统的资源管理和分配,而ApplicationMaster负责单个应用程序的管理

YARN总体上仍然是Master/Slave结构,在整个资源管理框架中,ResourceManager为Master,NodeManager为Slave,ResourceManager负责对各个NodeManager上的资源进行统一管理和调度。当用户提交一个应用程序时,需要提供一个用以跟踪和管理这个程序的ApplicationMaster,它负责向ResourceManager申请资源,并要求NodeManger启动可以占用一定资源的任务。由于不同的ApplicationMaster被分布到不同的节点上,因此它们之间不会相互影响。

下图描述了YARN的基本组成结构,YARN主要由ResourceManager、NodeManager、ApplicationMaster(图中给出了MapReduce和MPI两种计算框架的ApplicationMaster,分别为MR AppMstr和MPI AppMstr)和Container等几个组件构成。

YARN基本架构

接下来对YARN里几个重要的组件一一介绍。

1. ResourceManager(RM)

RM是一个全局的资源管理器,负责整个系统的资源管理和分配。它主要由两个组件构成:调度器(Scheduler)和应用程序管理器(Applications Manager,ASM)。

(1)调度器(分配Container)

调度器根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。需要注意的是,该调度器是一个“纯调度器”,它不再从事任何与具体应用程序相关的工作,比如不负责监控或者跟踪应用的执行状态等,也不负责重新启动因应用执行失败或者硬件故障而产生的失败任务,这些均交由应用程序相关的ApplicationMaster完成。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位用一个抽象概念“资源容器”(Resource Container,简称Container)表示,Container是一个动态资源分配单位,它将内存、CPU、磁盘、网络等资源封装在一起,从而限定每个任务使用的资源量。此外,该调度器是一个可插拔的组件,用户可根据自己的需要设计新的调度器,YARN提供了多种直接可用的调度器,比如Fair Scheduler和Capacity Scheduler等。

(2)应用程序管理器

应用程序管理器负责管理整个系统中所有应用程序,包括应用程序提交、与调度器协商资源以启动ApplicationMaster、监控ApplicationMaster运行状态并在失败时重新启动它等。

2. ApplicationMaster(AM)

用户提交的每个应用程序均包含一个AM,主要功能包括:

  • 与RM调度器协商以获取资源(以Container表示)
  • 将得到的任务进一步分配给内部的任务
  • 与NM通信以启动/停止任务
  • 监控所有任务运行状态,并在任务失败时重新为任务申请资源以重启任务

3. NodeManager(NM)

NM是每个节点上的资源和任务管理器。一方面,它定时地向RM汇报本节点的资源使用情况和Container运行状态;另一方面,它接受并处理来自AM的Container启动/停止等各种请求。

4. Container

Container是YARN中的资源抽象,它封装了某个节点上的多维资源,如CPU、内存、磁盘、网络等。当AM向RM申请资源时,RM向AM返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。Container是一个动态资源划分单位,是根据应用程序的需求自动生成的。目前,YARN仅支持CPU和内存两种资源。

YARN工作流程

运行在YARN上的应用程序主要分为两类:短应用程序和长应用程序。其中,短应用程序是指一定时间内可运行完成并正常退出的应用程序,如MapReduce作业、Spark DAG作业等。长应用程序是指不出意外,永不终止运行的应用程序,通常是一些服务,比如Storm Service(包括Nimbus和Supervisor两类服务),HBase Service(包括HMaster和RegionServer两类服务)等,而它们本身作为一种框架提供编程接口供用户使用。尽管这两类应用程序作业不同,一类直接运行数据处理程序,一类用于部署服务(服务之上再运行数据处理程序),但运行在YARN上的流程是相同的。

当用户向YARN中提交一个应用程序后,YARN将分两个阶段运行该应用程序:第一阶段是启动ApplicationMaster。第二阶段是由ApplicationMaster创建应用程序,为它申请资源,并监控它的整个运行过程,直到运行完成。具体如下:

  1. 用户向YARN中提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
  2. ResourceManager为该应用程序分配第一个Container,并与对应的NodeManager通信,要求它在这个Container中启动应用程序的ApplicationMaster。
  3. ApplicationMaster首先向ResourceManager注册,这样用户就可以直接通过ResourceManager查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7。
  4. ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源。
  5. 一旦ApplicationMaster申请到资源后,便与对应的NodeManager通信,要求它启动任务。
  6. NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。
  7. 各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。
  8. 应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。

YARN工作流程

Hadoop HDFS 详解

原文

HDFS 架构

HDFS是Hadoop应用中一个最主要的分布式存储系统。一个HDFS集群主要由一个 NameNode ,一个Secondary NameNode 和很多个 Datanode 组成:Namenode管理文件系统的元数据,而Datanode存储了实际的数据。客户端通过Namenode以获取文件的元数据或修饰属性,而真正的文件I/O操作是直接和Datanode进行交互的。

本文将详细介绍HDFS集群中的各个角色的作用以及工作原理、一些重要的特性。下面列出的是HDFS中常用特性的一部分:

  • 机架感知(Rack awareness):在调度任务和分配存储空间时考虑节点的物理位置。
  • 安全模式:一种维护需要的管理模式。
  • fsck:一个诊断文件系统健康状况的工具,能够发现丢失的文件或数据块。
  • Rebalancer:当datanode之间数据不均衡时,平衡集群上的数据负载。
  • 升级和回滚:在软件更新后有异常发生的情形下,能够回滚到HDFS升级之前的状态。
  • Secondary Namenode:对文件系统名字空间执行周期性的检查点,将Namenode上HDFS改动日志文件的大小控制在某个特定的限度下。

HDFS优点:

(1) 适合大数据处理(支持GB,TB,PB级别的数据存储,支持百万规模以上的文件数量)

(2) 适合批处理(支持离线的批量数据处理,支持高吞吐率)

(3) 高容错性(以数据块存储,可以保存多个副本,容易实现负载均衡)

HDFS缺点:

(1) 小文件存取(占用namenode大量内存,浪费磁盘空间)

(2) 不支持并发写入(同一时刻只能有一个进程写入,不支持随机修改)

HDFS中的角色

文件系统的名字空间 (namespace)

HDFS支持传统的层次型文件组织结构。用户或者应用程序可以创建目录,然后将文件保存在这些目录里。文件系统名字空间的层次结构和大多数现有的文件系统类似:用户可以创建、删除、移动或重命名文件。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。

HDFS文件系统常见命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Command                         Descriptionhadoop
fs -mkdir mydir             Create a directory (mydir) in HDFShadoop
fs -ls                      List files and directories in HDFShadoop
fs -cat myfile              View a file contenthadoop
fs -du                      Check disk space usage in HDFShadoop
fs -expunge                 Empty trash on HDFShadoop
fs -chgrp hadoop file1      Change group membership of a filehadoop
fs -chown huser file1       Change file ownershiphadoop
fs -rm file1                Delete a file in HDFShadoop
fs -touchz file2            Create an empty filehadoop
fs -stat file1              Check the status of a filehadoop
fs -test -e file1           Check if file exists on HDFShadoop
fs -test -z file1           Check if file is empty on HDFShadoop
fs -test -d file1           Check if file1 is a directory on HDFS

用户存储下载文件命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
Command                                                     Description
hadoop fs -copyFromLocal <source> <destination>     Copy from local fileystem to HDFS
hadoop fs -copyFromLocal file1 data                 Copies file1 from local FS to data dir in HDFS
hadoop fs -copyToLocal <source> <destination>       copy from hdfs to local filesystem
hadoop fs -copyToLocal data/file1 /var/tmp          Copies file1 from HDFS data directory to /var/tmp on local FS
hadoop fs -put <source> <destination>               Copy from remote location to HDFS
hadoop fs -get <source> <destination>               Copy from HDFS to remote directory

hadoop distcp hdfs://192.168.0.8:8020/input hdfs://192.168.0.8:8020/output  
Copy data from one cluster to another using the cluster URL

hadoop fs -mv file:///data/datafile /user/hduser/data   
Move data file from the local directory to HDFShadoop

NameNode

HDFS采用master/slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组成。Namenode是一个中心服务器:

(1) 负责管理文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。

(2) 负责确定数据块到具体Datanode节点的映射(文件到块的映射,块到DataNode的映射)。

(3) 监督Data nodes的健康

(4) 协调数据的存取

Datanode负责处理文件系统客户端的读写请求,在Namenode的统一调度下进行数据块的创建、删除和复制。

NameNode的特性可以总结如下:

(1) NameNode运行时所有数据都保存到内存,整个HDFS可存储的文件数受限于NameNode的内存大小。

(2) 一个block在NameNode中对应一条记录(一般一条记录占用150字节),如果是大量的小文件,会消耗大量内存。

(3) NameNode的数据会持久化到本地磁盘,但不保存block的位置信息,block由DataNode注册时上报和运行时维护

(4) NameNode失效则整个HDFS都失效了,所以要保证NameNode的可用性。

  • 文件系统元数据的持久化

Namenode上保存着HDFS的名字空间。对于任何对文件系统元数据产生修改的操作,Namenode都会使用一种称为EditLog的事务日志记录下来。例如,在HDFS中创建一个文件,Namenode就会在Editlog中插入一条记录来表示;同样地,修改文件的副本系数也将往Editlog插入一条记录。Namenode在本地操作系统的文件系统中存储这个Editlog。整个文件系统的名字空间,包括数据块到文件的映射、文件的属性等,都存储在一个称为FsImage的文件中,这个文件也是放在Namenode所在的本地文件系统上。

Namenode在内存中保存着整个文件系统的名字空间和文件数据块映射(Blockmap)的映像。这个关键的元数据结构设计得很紧凑,因而一个有4G内存的Namenode足够支撑大量的文件和目录。当Namenode启动时,它从硬盘中读取Editlog和FsImage,将所有Editlog中的事务作用在内存中的FsImage上,并将这个新版本的FsImage从内存中保存到本地磁盘上,然后删除旧的Editlog,因为这个旧的Editlog的事务都已经作用在FsImage上了。这个过程称为一个检查点(checkpoint)。在当前实现中,检查点只发生在Namenode启动时,在不久的将来将实现支持周期性的检查点。

  • 元数据磁盘错误

FsImage和Editlog是HDFS的核心数据结构。如果这些文件损坏了,整个HDFS实例都将失效。因而,Namenode可以配置成支持维护多个FsImage和Editlog的副本。任何对FsImage或者Editlog的修改,都将同步到它们的副本上。这种多副本的同步操作可能会降低Namenode每秒处理的名字空间事务数量。然而这个代价是可以接受的,因为即使HDFS的应用是数据密集的,它们也非元数据密集的。当Namenode重启的时候,它会选取最近的完整的FsImage和Editlog来使用。

  • 单一NameNode的不足

Namenode是HDFS集群中的单点故障(single point of failure)所在。如果Namenode机器故障,是需要手工干预的。目前,自动重启或在另一台机器上做Namenode故障转移的功能还没实现。

集群中单一Namenode的结构大大简化了系统的架构,但同时也带来了如下问题:

(1) NameNode的职责过重,无法避免单点故障

(2) 最大的瓶颈来自于内存,目前的NameNode,其元数据都是存储于单台服务器的内存里,那么其存储容量就受到了单台服务器内存容量的限制, 据估算,在装配100GB内存的服务器上,一般只能存储几亿级别的文件数。

(3) 随着集群规模的扩大,对于元数据的读写请求也会随之增多,那么元数据的访问性能也会受到单台服务器处理能力的限制。

那么如何对NameNode进行扩展呢? 一种可行的方法是对NameNode的职责进行分离。

NameNode的职责可以分成两部分:1) 名字空间的管理; 2) 块管理:文件到块的映射,块到DataNode的映射。因此对其进行职责分离的解决方案可以为:NameNode只负责命名空间管理,在HDFS系统中新增加一个角色,这个角色专门负责块管理(文件到块的映射,块到DataNode的映射)

Secondary NameNode

NameNode将对文件系统的改动追加保存到本地文件系统上的一个日志文件(edits)。当一个NameNode启动时,它首先从一个映像文件(fsimage)中读取HDFS的状态,接着应用日志文件中的edits操作。然后它将新的HDFS状态写入(fsimage)中,并使用一个空的edits文件开始正常操作。因为NameNode只有在启动阶段才合并fsimage和edits,所以久而久之日志文件可能会变得非常庞大,特别是对大型的集群。日志文件太大的另一个副作用是下一次NameNode启动会花很长时间。

Secondary NameNode定期(缺省为每小时)合并fsimage和edits日志,将edits日志文件大小控制在一个限度下。Secondary Namenode会连接到Namenode,同步Namenode的fsimage文件和edits文件。Secondary Namenode 合并fsimage文件和edits文件到一个新的文件中,保存到本地的同时把这些文件发送回NameNode。 当Namenode宕机,保存在Secondary Namenode中的文件可以用来恢复Namenode。在一个繁忙的集群中,系统管理员可以配置同步时间为更小的时间间隔,比如每分钟。

因为内存需求和NameNode在一个数量级上,所以通常secondary NameNode和NameNode运行在不同的机器上。Secondary NameNode通过bin/start-dfs.sh在conf/masters中指定的节点上启动。

总结一下Secondary Namenode: > 1)不是NameNode的备份 2)周期性合并fsimage和editslog,并推送给NameNode 3)辅助恢复NameNode

DataNode

DataNode的特性可以总结为:

(1) 保存具体的block数据

(2) 负责数据的读写操作和复制操作

(3) DataNode启动时会向NameNode报告当前存储的数据块信息,后续也会定时报告修改信息

(4) DataNode之间会进行通信,复制数据块,保证数据的冗余性

  • 数据组织

HDFS被设计成支持大文件,适用HDFS的是那些需要处理大规模的数据集的应用。这些应用都是只写入数据一次,但却读取一次或多次,并且读取速度应能满足流式读取的需要。HDFS支持文件的“一次写入多次读取”语义。一个大文件会被拆分成一个个的块(block),然后存储于不同的DataNode上。如果一个文件小于一个block的大小,那么实际占用的空间为其文件的大小。

DataNode将HDFS数据以文件的形式存储在本地的文件系统中,它并不知道有关HDFS文件的信息。它把每个HDFS数据块(block)存储在本地文件系统的一个单独的文件中,每个块都会被复制到多台机器,默认复制3份。在DataNode中block是基本的存储单位(每次都是读写一个块),默认大小为64M。配置大的块主要是因为:

(1) 减少搜寻时间,一般硬盘传输速率比寻道时间要快,大的块可以减少寻道时间;

(2) 减少管理块的数据开销,每个块都需要在NameNode上有对应的记录;

(3) 对数据块进行读写,减少建立网络的连接成本

  • 数据复制

HDFS被设计成能够在一个大集群中跨机器可靠地存储超大文件。它将每个文件存储成一系列的数据块,除了最后一个,所有的数据块都是同样大小的。为了容错,文件的所有数据块都会有副本。每个文件的数据块大小和副本系数都是可配置的。应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。HDFS中的文件都是一次性写入的,并且严格要求在任何时候只能有一个写入者

Namenode全权管理数据块的复制,它周期性地从集群中的每个DataNode接收 心跳信号块状态报告(Blockreport)接收到心跳信号意味着该DataNode节点工作正常。块状态报告包含了一个该Datanode上所有数据块的列表

副本的存放是HDFS可靠性和性能的关键。优化的副本存放策略是HDFS区分于其他大部分分布式文件系统的重要特性。这种特性需要做大量的调优,并需要经验的积累。HDFS采用一种称为 机架感知(rack-aware) 的策略来改进数据的可靠性、可用性和网络带宽的利用率。大型HDFS实例一般运行在跨越多个机架的计算机组成的集群上,不同机架上的两台机器之间的通讯需要经过交换机。在大多数情况下,同一个机架内的两台机器间的带宽会比不同机架的两台机器间的带宽大。

通过一个机架感知的过程,Namenode可以确定每个Datanode所属的机架id。一个简单但没有优化的策略就是将副本存放在不同的机架上。这样可以有效防止当整个机架失效时数据的丢失,并且允许读数据的时候充分利用多个机架的带宽。这种策略设置可以将副本均匀分布在集群中,有利于当组件失效情况下的负载均衡。但是,因为这种策略的一个写操作需要传输数据块到多个机架,这增加了写的代价。

在大多数情况下,副本系数是3,HDFS的存放策略是将一个副本存放在本地机架的节点上,一个副本放在同一机架的另一个节点上,最后一个副本放在不同机架的节点上。这种策略减少了机架间的数据传输,这就提高了写操作的效率。机架的错误远远比节点的错误少,所以这个策略不会影响到数据的可靠性和可用性。于此同时,因为数据块只放在两个(不是三个)不同的机架上,所以此策略减少了读取数据时需要的网络传输总带宽。在这种策略下,副本并不是均匀分布在不同的机架上。三分之一的副本在一个节点上,三分之二的副本在一个机架上,其他副本均匀分布在剩下的机架中,这一策略在不损害数据可靠性和读取性能的情况下改进了写的性能。

为了降低整体的带宽消耗和读取延时,HDFS会尽量让读取程序读取离它最近的副本。如果在读取程序的同一个机架上有一个副本,那么就读取该副本。如果一个HDFS集群跨越多个数据中心,那么客户端也将首先读本地数据中心的副本。

HDFS中的block数据3备份的复制采用的是的 流水线复制 方式,从前一个节点接收数据,并在同时转发给下一个节点,数据以流水线的方式从前一个DataNode复制到下一个。:

HDFS文件的写入具体过程如下图所示:

(1)客户端将文件写入本地磁盘的临时文件中(Staging)

(2)当临时文件大小达到一个block大小时,HDFS client通知NameNode申请写入文件

(3)NameNode在HDFS的文件系统中创建一个文件,并把该block id和要写入的DataNode的列表返回给客户端

(4)客户端收到这些信息后,将临时文件写入DataNodes

1
2
3
4
5
6
7
4.1 客户端将文件内容写入第一个DataNode(一般以4kb为单位进行传输)
4.2 第一个DataNode接收后,将数据写入本地磁盘,同时也传输给第二个DataNode
4.3 依此类推到最后一个DataNode,数据在DataNode之间是通过pipeline的方式进行复制的
4.4 后面的DataNode接收完数据后,都会发送一个确认给前一个DataNode,最终第一个DataNode返回确认给客户端
4.5 当客户端接收到整个block的确认后,会向NameNode发送一个最终的确认信息
4.6 如果写入某个DataNode失败,数据会继续写入其他的DataNode。然后NameNode会找另外一个好的DataNode继续复制,以保证冗余性
4.7 每个block都会有一个校验码,并存放到独立的文件中,以便读的时候来验证其完整性

(5)文件写完后(客户端关闭),NameNode提交文件(这时文件才可见,如果提交前,NameNode垮掉,那文件也就丢失了。fsync:只保证数据的信息写到NameNode上,但并不保证数据已经被写到DataNode中)

当一个文件的副本系数被减小后,NameNode会选择过剩的副本删除。下次心跳检测时会将该信息传递给DataNode。Datanode遂即移除相应的数据块,集群中的空闲空间加大。

HDFS读文件流程:

  • 1.Hdfs 读数据的时候,客户端首先通过调用hdfs提供的open()读取目标文件,hdfs根据需要向NameNode节点查询这些文件存储在哪些DataNode上
  • 2.NameNode返回所有文件block副本的DataNode节点的位置信息(并且根据他们与客户端的距离进行排序)
  • 3.客户端从这些DataNode上读取block数据,一个block读完,继续寻找下一个block位置节点,直到读取完。
  • 4.在读完一个block后,都会进行checksum校验,如果有错误,会通知NameNode,并且从下一个包含block的Datanode继续读。
  • 数据的可靠性

HDFS 的一个重要目标是可靠存储数据,即使在 NameNode、 DataNode或网络分区中出现故障。HDFS 克服故障的第一个步骤是探测。HDFS 使用心跳消息来探测 NameNode 和 DataNode 之间的连通性。HDFS 心跳有几种情况可能会导致 NameNode 和 DataNode 之间的连通性丧失。因此,每个 DataNode 都向它的 NameNode 发送定期心跳消息,这样,如果 NameNode 不能接收心跳消息,就表明连通性丧失。

NameNode 将不能响应心跳消息的 DataNode 标记为 “死 DataNode ”,并不再向它们发送请求。 存储在一个死节点上的数据不再对那个节点的 HDFS 客户端可用,该节点将被从系统有效地移除。如果一个节点的死亡导致数据块的复制因子降至最小值之下, Name node 将启动附加复制,将复制因子带回正常状态。

DataNode每3秒钟发送一个heartbeats给NameNode ,二者使用TCP9000端口的TCP握手来实现heartbeats。每十个heartbeats会有一个block report,Data node告知它所保存的数据块。block report使得Namenode能够重建它的metadata以确保每个数据block有足够的copy,并且分布在不同的机架上。

  • Rebalancer

HDFS的数据也许并不是非常均匀的分布在各个DataNode中。一个常见的原因是在现有的集群上经常会增添新的DataNode节点。

当新增一个数据块(一个文件的数据被保存在一系列的块中)时,NameNode在选择DataNode接收这个数据块之前,会考虑到很多因素。其中的一些考虑的是:

(1) 将数据块的一个副本放在正在写这个数据块的节点上。 (2) 尽量将数据块的不同副本分布在不同的机架上,这样集群可在完全失去某一机架的情况下还能存活。 (3) 一个副本通常被放置在和写文件的节点同一机架的某个节点上,这样可以减少跨越机架的网络I/O。 (4) 尽量均匀地将HDFS数据分布在集群的DataNode中。

由于上述多种考虑需要取舍,数据可能并不会均匀分布在DataNode中。HDFS为提供了一个工具(balancer 命令),用于分析数据块分布和重新平衡DataNode上的数据分布。

HDFS重要特性

  • 通讯协议

所有的HDFS通讯协议都是建立在TCP/IP协议之上。客户端通过一个可配置的TCP端口连接到NameNode,通过ClientProtocol协议与NameNode交互。而DataNode使用DataNodeProtocol协议与Namenode交互。一个远程过程调用(RPC)模型被抽象出来封装ClientProtocol和Datanodeprotocol协议。在设计上,Namenode不会主动发起RPC,而是响应来自客户端或 Datanode 的RPC请求。

  • 安全模式

NameNode启动后会进入一个称为安全模式的特殊状态。处于安全模式的Namenode是不会进行数据块的复制的。NameNode从所有的 DataNode接收心跳信号和块状态报告。块状态报告包括了某个DataNode所有的数据块列表。每个数据块都有一个指定的最小副本数。当Namenode检测确认某个数据块的副本数目达到这个最小值,那么该数据块就会被认为是副本安全(safely replicated)的;在一定百分比(这个参数可配置)的数据块被NameNode检测确认是安全之后(加上一个额外的30秒等待时间),NameNode将退出安全模式状态。接下来它会确定还有哪些数据块的副本没有达到指定数目,并将这些数据块复制到其他Datanode上。

  • 数据完整性

从某个Datanode获取的数据块有可能是损坏的,损坏可能是由DataNode的存储设备错误、网络错误或者软件bug造成的。HDFS客户端软件实现了对HDFS文件内容的校验和(checksum)检查。当客户端创建一个新的HDFS文件,会计算这个文件每个数据块的校验和,并将校验和作为一个单独的隐藏文件保存在同一个HDFS名字空间下。当客户端获取文件内容后,它会检验从DataNode获取的数据跟相应的校验和文件中的校验和是否匹配,如果不匹配,客户端可以选择从其他DataNode获取该数据块的副本。

  • 存储空间回收

当用户或应用程序删除某个文件时,这个文件并没有立刻从HDFS中删除。实际上,HDFS会将这个文件重命名转移到/trash目录。只要文件还在/trash目录中,该文件就可以被迅速地恢复。文件在/trash中保存的时间是可配置的,当超过这个时间时,Namenode就会将该文件从名字空间中删除。删除文件会使得该文件相关的数据块被释放。注意,从用户删除文件到HDFS空闲空间的增加之间会有一定时间的延迟。

Ref

[Ubuntu] How to change the MySQL data default directory

MySQL is a widely used and fast SQL database server. It is a client/server implementation that consists of a server daemon (mysqld) and many different client programs/libraries.

If you want to install Mysql database server in Ubuntu check this tutorial.
What is Mysql Data Directory?

Mysql data directory is important part where all the mysql databases storage location.By default MySQL data default directory located in /var/lib/mysql.If you are running out of space in /var partition you need to move this to some other location.

Note:- This is only for advanced users and before moving default directory make a backup of your mysal databases.

Procedure to follow

Open the terminal

First you need to Stop MySQL using the following command

sudo /etc/init.d/mysql stop

Now Copy the existing data directory (default located in /var/lib/mysql) using the following command

sudo cp -R -p /var/lib/mysql /path/to/new/datadir

All you need are the data files, so delete the others with the command

sudo rm /path/to/new/datadir

Note:- You will get a message about not being able to delete some directories, but that’s what you want.

Now edit the MySQL configuration file with the following command

sudo vim /etc/mysql/my.cnf

Look for the entry for “datadir”, and change the path (which should be “/var/lib/mysql”) to the new data directory.

Important Note:-From Ubuntu 7.10 (Gutsy Gibbon) forward, Ubuntu uses some security software called AppArmor that specifies the areas of your filesystem applications are allowed to access. Unless you modify the AppArmor profile for MySQL, you’ll never be able to restart MySQL with the new datadir location.

In the terminal, enter the command

sudo vim /etc/apparmor.d/usr.sbin.mysqld

Copy the lines beginning with “/var/lib/mysql”, comment out the originals with hash marks (“#”), and paste the lines below the originals.

Now change “/var/lib/mysql” in the two new lines with “/path/to/new/datadir”. Save and close the file.

Restart the AppArmor profiles with the command

sudo /etc/init.d/apparmor reload

Restart MySQL with the command

sudo /etc/init.d/mysql restart

Now MySQL should start with no errors, and your data will be stored in the new data directory location.

ubuntu 修改mysql 数据文件夹

https://stackoverflow.com/questions/17968287/how-to-find-the-mysql-data-directory-from-command-line-in-windows

https://www.digitalocean.com/community/tutorials/how-to-move-a-mysql-data-directory-to-a-new-location-on-ubuntu-16-04

https://askubuntu.com/questions/790685/cannot-set-a-different-database-directory-for-mysql-errcode-13-permission-d