搭建 Hadoop 伪分布式环境

软硬件环境 CentOS 7.2 64位 OpenJDK-1.7 Hadoop-2.7 关于本教程的说明 云实验室云主机自动使用root账户登录系统,因此本教程中所有的操作都是以root用户来执行的。若要在自己的云主机上进行本教程的实验,为了系统安全,建议新建一个账户登录后再进行后续操作。 安装 SSH 客户端 任务时间:1min ~ 5min 安装SSH 安装SSH: sudo yum install openssh-clients openssh-server 安装完成后,可以使用下面命令进行测试: ssh localhost 输入root账户的密码,如果可以正常登录,则说明SSH安装没有问题。测试正常后使用exit命令退出ssh。 安装 JAVA 环境 任务时间:5min ~ 10min 安装 JDK 使用yum来安装1.7版本OpenJDK: sudo yum install java-1.7.0-openjdk java-1.7.0-openjdk-devel 安装完成后,输入java和javac命令,如果能输出对应的命令帮助,则表明jdk已正确安装。 配置 JAVA 环境变量 执行命令: 编辑 ~/.bashrc,在结尾追加: export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk 保存文件后执行下面命令使JAVA_HOME环境变量生效: source ~/.bashrc 为了检测系统中JAVA环境是否已经正确配置并生效,可以分别执行下面命令: java -version $JAVA_HOME/bin/java … Continue reading "搭建 Hadoop 伪分布式环境"

Facebook针对hbase的优化方案分析

使用hbase的目的是为了海量数据的随机读写,但是在实际使用中却发现针对随机读的优化和gc是一个很大的问题,而且hbase的数据是存储在Hdfs,而Hdfs是面向流失数据访问进行设计的,就难免带来效率的下降。下面介绍一下Facebook Message系统在HBase online storage场景下的一个案例(《Apache Hadoop Goes Realtime at Facebook》, SIGMOD 2011),最近他们在存储领域顶级会议FAST2014上发表了一篇论文《Analysis of HDFS Under HBase: A Facebook Messages Case Study》分析了他们在使用HBase中遇到的一些问题和解决方案。该论文首先讲了Facebook的分析方法包括tracing/analysis/simulation,FM系统的架构和文件与数据构成等,接下来开始分析FM系统在性能方面的一些问题,并提出了解决方案。 FM系统的主要读写I/O负载 Figure 2描述了每一层的I/O构成,解释了在FM系统对外请求中读占主导,但是由于logging/compaction/replication/caching导致写被严重放大。 HBase的设计是分层结构的,依次是DB逻辑层、FS逻辑层、底层系统逻辑层。DB逻辑层提供的对外使用的接口主要操作是put()和get()请求,这两个操作的数据都要写到HDFS上,其中读写比99/1(Figure 2中第一条)。 由于DB逻辑层内部为了保证数据的持久性会做logging,为了读取的高效率会做compaction,而且这两个操作都是写占主导的,所以把这两个操作(overheads)加上之后读写比为79/21(Figure 2中第二条)。 相当于调用put()操作向HBase写入的数据都是写入了两份:一份写入内存Memstore然后flush到HFile/HDFS,另一份通过logging直接写HLog/HDFS。Memstore中积累一定量的数据才会写HFile,这使得压缩比会比较高,而写HLog要求实时append record导致压缩比(HBASE-8155)相对较低,导致写被放大4倍以上。    Compaction操作就是读取小的HFile到内存merge-sorting成大的HFile然后输出,加速HBase读操作。Compaction操作导致写被放大17倍以上,说明每部分数据平均被重复读写了17次,所以对于内容不变的大附件是不适合存储在HBase中的。由于读操作在FM业务中占主要比例,所以加速读操作对业务非常有帮助,所以compaction策略会比较激进。 HBase的数据reliable是靠HDFS层保证的,即HDFS的三备份策略。那么也就是上述对HDFS的写操作都会被转化成三倍的local file I/O和两倍的网络I/O。这样使得在本地磁盘I/O中衡量读写比变成了55/45。 然而由于对本地磁盘的读操作请求的数据会被本地OS的cache缓存,那么真正的读操作是由于cache miss引起的读操作的I/O量,这样使得读写比变成了36/64,写被进一步放大。    另外Figure 3从I/O数据传输中真正业务需求的数据大小来看各个层次、各个操作引起的I/O变化。除了上面说的,还发现了整个系统最终存储在磁盘上有大量的cold data(占2/3),所以需要支持hot/cold数据分开存储。 总的来说,HBase stack的logging/compaction/replication/caching会放大写I/O,导致业务逻辑上读为主导的HBase系统在地层实际磁盘I/O中写占据了主导。 FM系统的主要文件类型和大小   FM系统的几种文件类型如Table 2所示,这个是纯业务的逻辑描述。在HBase的每个RegionServer上的每个column family对应一个或者多个HFile文件。FM系统中有8个column family,由于每个column family存储的数据的类型和大小不一样,使得每个column family的读写比是不一样的。而且很少数据是读写都会请求的,所以cache all writes可能作用不大(Figure 4)。 对于每个column family的文件,90%是小于15M的。但是少量的特别大的文件会拉高column family的平均文件大小。例如MessageMeta这个column family的平均文件大小是293M。从这些文件的生命周期来看,大部分FM的数据存储在large,long-lived files,然而大部分文件却是small, … Continue reading "Facebook针对hbase的优化方案分析"

Hadoop快速入门

目的 这篇文档的目的是帮助你快速完成单机上的Hadoop安装与使用以便你对Hadoop分布式文件系统(HDFS)和Map-Reduce框架有所体会,比如在HDFS上运行示例程序或简单作业等。   先决条件   支持平台 GNU/Linux是产品开发和运行的平台。 Hadoop已在有2000个节点的GNU/Linux主机组成的集群系统上得到验证。 Win32平台是作为开发平台支持的。由于分布式操作尚未在Win32平台上充分测试,所以还不作为一个生产平台被支持。   所需软件 Linux和Windows所需软件包括: JavaTM1.5.x,必须安装,建议选择Sun公司发行的Java版本。 ssh 必须安装并且保证 sshd一直运行,以便用Hadoop 脚本管理远端Hadoop守护进程。 Windows下的附加软件需求 Cygwin – 提供上述软件之外的shell支持。   安装软件 如果你的集群尚未安装所需软件,你得首先安装它们。 以Ubuntu Linux为例: $ sudo apt-get install ssh $ sudo apt-get install rsync 在Windows平台上,如果安装cygwin时未安装全部所需软件,则需启动cyqwin安装管理器安装如下软件包: openssh – Net 类   下载 为了获取Hadoop的发行版,从Apache的某个镜像服务器上下载最近的 稳定发行版。   运行Hadoop集群的准备工作 解压所下载的Hadoop发行版。编辑 conf/hadoop-env.sh文件,至少需要将JAVA_HOME设置为Java安装根路径。 尝试如下命令: $ bin/hadoop 将会显示hadoop 脚本的使用文档。 现在你可以用以下三种支持的模式中的一种启动Hadoop集群: … Continue reading "Hadoop快速入门"

HFile存储格式

HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要包括两种文件类型: 1. HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile 2. HLog File,HBase中WAL(Write Ahead Log) 的存储格式,物理上是Hadoop的Sequence File 下面主要通过代码理解一下HFile的存储格式。 HFile 下图是HFile的存储格式: HFile由6部分组成的,其中数据KeyValue保存在Block 0 … N中,其他部分的功能有:确定Block Index的起始位置;确定某个key所在的Block位置(如block index);判断一个key是否在这个HFile中(如Meta Block保存了Bloom Filter信息)。具体代码是在HFile.java中实现的,HFile内容是按照从上到下的顺序写入的(Data Block、Meta Block、File Info、Data Block Index、Meta Block Index、Fixed File Trailer)。 KeyValue: HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构: 开始是两个固定长度的数值,分别表示Key的长度和Value的长度。紧接着是Key,开始是固定长度的数值,表示RowKey的长度,紧接着是 RowKey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier,然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据了。 Data Block:由DATABLOCKMAGIC和若干个record组成,其中record就是一个KeyValue(key length, value length, key, value),默认大小是64k,小的数据块有利于随机读操作,而大的数据块则有利于scan操作,这是因为读KeyValue的时候,HBase会将查询到的data block全部读到Lru Block Cache中去,而不是仅仅将这个record读到cache中去。 private void append(final byte [] key, final int koffset, … Continue reading "HFile存储格式"

分布式文件系统Ceph调研1 – RADOS

Ceph是加州大学Santa Cruz分校的Sage Weil(DreamHost的联合创始人)专为博士论文设计的新一代自由软件分布式文件系统。自2007年毕业之后,Sage开始全职投入到Ceph开 发之中,使其能适用于生产环境。Ceph的主要目标是设计成基于POSIX的没有单点故障的分布式文件系统,使数据能容错和无缝的复制。2010年3 月,Linus Torvalds将Ceph client合并到内 核2.6.34中。 Ceph中有很多在分布式系统领域非常新颖的技术点,对解决分布式文件系统中一些常见的问题的研究非常有指导意义。所以值得研究。 RADOS简介 1 RADOS概述 RADOS (Reliable, Autonomic Distributed Object Store) 是Ceph的核心之一,作为Ceph分布式文件系统的一个子项目,特别为Ceph的需求设计,能够在动态变化和异质结构的存储设备机群之上提供一种稳定、可扩展、高性能的单一逻辑对象(Object)存储接口和能够实现节点的自适应和自管理的存储系统。事实上,RADOS也可以单独作为一种分布式数据存储系统,给适合相应需求的分布式文件系统提供数据存储服务。 2 RADOS架构简介 RADOS系统主要由两个部分组成(如图1所示): 1.由数目可变的大规模OSDs(Object Storage Devices)组成的机群,负责存储所有的Objects数据; 2.由少量Monitors组成的强耦合、小规模机群,负责管理Cluster Map,其中Cluster Map是整个RADOS系统的关键数据结构,管理机群中的所有成员、关系、属性等信息以及数据的分发。 图1 RADOS系统架构图示 对于RADOS系统,节点组织管理和数据分发策略均有内部的Monitors全权负责,所以,从Clients角度设计相对比较简单,它给应用提供的仅为简单的存储接口。 3 RADOS详细介绍 3.1 扩展机群 1.Cluster Map 存储机群的管理,唯一的途径是Cluster Map通过对Monitor Cluster操作完成。Cluster Map是整个RADOS系统的核心数据结构,其中指定了机群中的OSDs信息和所有数据的分布情况。所有涉及到RADOS系统的Storage节点和Clients都有最新epoch的Cluster Map副本。因为Cluster Map的特殊性,Client向上提供了非常简单的接口实现将整个存储机群抽象为单一的逻辑对象存储结构。 Cluster Map的更新由OSD的状态变化或者其他事件造成数据层的变化驱动,每一次Cluster Map更新都需要将map epoch增加,map epoch使Cluster Map在所有节点上的副本都保持同步,同时,map epoch可以使一些过期的Cluster Map能够通过通信对等节点及时更新。 在大规模的分布式系统中,OSDs的failures/recoveries是常见的,所以,Cluster Map的更新就比较频繁,如果将整个Cluster Map进行分发或广播显然会造成资源的浪费,RADOS采用分发incremental map的策略避免资源浪费,其中incremental … Continue reading "分布式文件系统Ceph调研1 – RADOS"

Lucene Query Parser

Lucene Query Parser 翻译这篇文章的初衷是希望能更系统的理解Lucene的用法,同时试试自己的翻译水平:) 原文:http://jakarta.apache.org/lucene/docs/queryparsersyntax.html 概述 虽然Lucene提供的API允许你创建你自己的Query(查询语句),但它同时也通过Query Parser(查询分析器)提供了丰富的查询语言。 这个页面提供的是Lucene的Query Parser的语法介绍:一个可通过用JavaCC把一个字符串解释成为Lucene的查询语句的规则。 在选择使用被提供的Query Parser前,请考虑一下几点: 1、如果你是通过编写程序生成一个查询语句,然后通过Query Parser分析,那么你需要认真的考虑是否该直接利用Query的API构造你的查询。换句话说,Query Parser是为那些人工输入的文本所设计的,而不是为了程序生成的文本。 2、未分词的字段最好直接加到Query中,而不要通过Query Parser。如果一个字段的值是由程序生成的,那么需要为这个字段生成一个Query Clause(查询子句)。Query Parser所用的Analyzer是为转换人工输入的文本为分词的。而程序生成的值,比如日期、关键字等,一般都由程序直接生成(?)。 3、在一个查询表单里,通常是文本的字段应该使用Query Parser。所有其他的,比如日期范围、关键字等等,最好是通过Query API直接加入到Query中。一个有有限个值的字段,比如通过下拉表单定义的那些,不应该被加到查询字串中(后面会分析到),而应该被添加为一个TermQuery子句。 分词 一个查询语句是有分词和操作符组成的。这里有两种类型的:单个的分词和短语。 一个单一分词就是一个简单的单词,比如”test”或”hello”。 一个短语就是一组被双引号包括的单词,比如”hello dolly”。 多个分词可以用布尔操作符组合起来形成一个更复杂的查询语句(下面会详细介绍)。 注意:用于建立索引的分析器(Analyzer)将被用于解释查询语句中的分词和短语。因此,合理的选择一个分析器是很重要的,当然这不会影响你在查询语句中使用的分词。 字段 Lucene支持字段数据。当执行一个搜索时,你可以指定一个字段,或者使用默认的字段。字段的名字和默认的字段是取决于实现细节的。 你可以搜索任何字段,做法是输入字段名称,结尾跟上一个冒号 “:” , 然后输入你想查找的分词。 举个例子,让我们假设Lucene的索引包含两个字段,标题和正文,正文是默认字段。如果你想标题为 “The Right Way” 并且正文包含文本 “don’t go this way”的记录的话,你可以输入:   title:”The Right Way” AND text:go  或者   title:”Do it right” … Continue reading "Lucene Query Parser"

索引有哪些优点?

索引有哪些优点?1、  通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。 2、  可以大大加快数据的检索速度,这也是创建索引的最主要原因。 3、  可以加速表和表之间的连接,这在实现数据的参考完整性方面特别有意义。 4、  在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。 索引有哪些缺点?1、  创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 2、  除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,需要的空间就会更大。 3、  当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 索引有哪些类型?1、 普通索引 这是最基本的索引类型,而且它没有唯一性之类的限制。 2、 唯一性索引 这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。 3、主键 它是一种特殊的唯一索引,不允许有空值。 4、全文索引 MySQL从3.23.23版开始支持全文索引和全文检索。 单列索引和组合索引:单列索引就是把索引单独建立在一个字段上。 组合索引复合索引就是一个索引创建在两个列或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。 建立和使用索引有哪些注意事项:1、           索引要建立在经常进行select操作的字段上。这是因为,如果这些列很少用到,那么有无索引并不能明显改变查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。 2、           索引要建立在值比较唯一的字段上。这样做才是发挥索引的最大效果。,比如主键的id字段,唯一的名字name字段等等。如果索引建立在唯一值比较少的字段,比如性别gender字段,寥寥无几的类别字段等,刚索引几乎没有任何意义。 3、           对于那些定义为text、 image和bit数据类型的列不应该增加索引。因为这些列的数据量要么相当大,要么取值很少。 4、           当修改性能远远大于检索性能时,不应该创建索引。修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。 5、           在WHERE和JOIN中出现的列需要建立索引。 6、           在以通配符 % 和 _ 开头作查询时,MySQL索引是无效的。但是这样索引是有效的:select * from tbl1 where name like ‘xxx%’,所以谨慎的写你的SQL是很重要的。

lucene简单实例<二>

 写文章的时候,感觉比较难写的就是标题,有时候不知道起什么名字好,反正这里写的都是关于lucene的一些简单的实例,就随便起啦. Lucene 其实很简单的,它最主要就是做两件事:建立索引和进行搜索 来看一些在lucene中使用的术语,这里并不打算作详细的介绍,只是点一下而已—-因为这一个世界有一种好东西,叫搜索。 IndexWriter:lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。 Analyzer:分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。 Directory:索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。 Document:文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。 Field:字段。 IndexSearcher:是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具; Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。 QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。 Hits:在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在lucene中,搜索的结果的集合是用Hits类的实例来表示的。 上面作了一大堆名词解释,下面就看几个简单的实例吧: 1、简单的的StandardAnalyzer测试例子 Java代码 package lighter.javaeye.com;      import java.io.IOException;   import java.io.StringReader;      import org.apache.lucene.analysis.Analyzer;   import org.apache.lucene.analysis.Token;   import org.apache.lucene.analysis.TokenStream;   import org.apache.lucene.analysis.standard.StandardAnalyzer;      public class StandardAnalyzerTest    {       //构造函数,       public StandardAnalyzerTest()       {       }       public static void main(String[] args)        {           //生成一个StandardAnalyzer对象           Analyzer aAnalyzer = new StandardAnalyzer();           //测试字符串           StringReader sr = new StringReader(“lighter javaeye com is the are on”);           //生成TokenStream对象           TokenStream ts = aAnalyzer.tokenStream(“name”, sr);            try {               int i=0;               Token t = ts.next();               while(t!=null)               {                   //辅助输出时显示行号                   i++;                   //输出处理后的字符                   System.out.println(“第”+i+“行:”+t.termText());                   //取得下一个字符                   t=ts.next();               }           } catch (IOException e) {               e.printStackTrace();   … Continue reading "lucene简单实例<二>"