首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Hbase 学习(五) 调优

1.垃圾回收器调优 当我们往hbase写入数据,它首先写入memstore当中,当menstore的值大于hbase.hregion.memstore.flush.size参数中设置的值后,就会写入硬盘。 在hbase-env.sh文件中,我们可以设置HBASE_OPTS或者HBASE_REGIONSERVER_OPTS,后者只影响region server进程。 export HBASE_REGIONSERVER_OPTS="-Xmx8g -Xms8g -Xmn128m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:$HBASE_HOME/logs/gc-$(hostname)-hbase.log" 《hbase权威指南》推荐了上述的写法,下面是从网上搜的,原书中为什么要这么设置的解释真心看不懂。 -Xmx8g -Xms8g –Xmn128m :最大堆内存8G,最小堆内存8G,新生代内存-Xmn128m。 -XX:+UseParNewGC : 设置对于新生代的垃圾回收器类型,这种类型是会停止JAVA进程,然后再进行回收的,但由于新生代体积比较小,持续时间通常只有几毫秒,因此可以接受。 -XX:+UseConcMarkSweepGC :设置老生代的垃圾回收类型,如果用新生代的那个会不合适,即会导致JAVA进程停止的时间太长,用这种不会停止JAVA进程,而是在JAVA进程运行的同时,并行的进行回收。 -XX:CMSInitiatingOccupancyFraction :设置CMS回收器运行的频率,避免前两个参数引起JAVA进程长时间停止,设置了这个之后,不需要停止JAVA进程,但是会提高CPU使用率。 最后两句是输出详细的日志。 2.MemStore-Local Allocation Buffer MemStore-Local Allocation Buffer,是Cloudera在HBase 0.90.1时提交的一个patch里包含的特性。它基于Arena Allocation解决了HBase因Region flush导致的内存碎片问题。 MSLAB的实现原理(对照Arena Allocation,HBase实现细节): MemstoreLAB为Memstore提供Allocator。 创建一个2M(默认)的Chunk数组和一个chunk偏移量,默认值为0。 当Memstore有新的KeyValue被插入时,通过KeyValue.getBuffer()取得data bytes数组。将data复制到Chunk数组起始位置为chunk偏移量处,并增加偏移量=偏移量+data.length。 当一个chunk满了以后,再创建一个chunk。 所有操作lock free,基于CMS原语。 优势: KeyValue原始数据在minor gc时被销毁。 数据存放在2m大小的chunk中,chunk归属于memstore。 flush时,只需要释放多个2m的chunks,chunk未满也强制释放,从而为Heap腾出了多个2M大小的内存区间,减少碎片密集程度。 开启MSLAB hbase.hregion.memstore.mslab.enabled=true // 开启MSALB hbase.hregion.memstore.mslab.chunksize=2m // chunk的大小,越大内存连续性越好,但内存平均利用率会降低,要比插入的单元格的数据大一些。 hbase.hregion.memstore.mslab.max.allocation=256K // 通过MSLAB分配的对象不能超过256K,否则直接在Heap上分配,256K够大了。 3.压缩存储 直接上图吧,说多了没用。 推荐使用Snappy,性能最好,但是Snappy要单独安装,安装教程等我装成功了,再发一个文档出来吧。 4.优化Splits and Compactions 对于实时性要求稳定的系统来说,不定时的split和compact会使集群的响应时间出现比较大的波动,因此建议把split和compact关闭,手动进行操作,比如我们把hbase.hregion.max.filesize设置成100G(major compaction大概需要一小时,设置太大了,compaction会需要更多的时间),major compaction是必须要做的,群里有个网友给数据设置了过期时间,数据被逻辑删除了,但是没有释放硬盘空间,why?没有进行major compaction,最后是手动进行的合并。 5.平衡分布 在我们设计rowkey的时候,在前面加上随机数,比如0rowkey-1,1rowkey-2,0rowkey-3,1rowkey-4,去前面加上个随机数,就会有负载均衡的效果,但是如果这样做了,某个机器的数据还是比别的机器要多很多,这个怎么办呢?我们可以手动调用move()方法,通过shell或者HBaseAdmin类,或者调用unassign()方法,数据就会转移了。

优秀的个人博客,低调大师

Hbase 学习(七) rowkey设计

一直以来对rowkey的设计都比较迷茫,《hbase权威指南》倒是给出了个还算靠谱的例子。 下面这个例子有点儿像帖子表结构,它的rowkey设计是这样的,可以简单的理解为,什么人在什么时间发了什么信息,信息包括什么附件,它是用户为主线的一个设计。 <userId>-<date>-<messageId>-<attachmentId> 如果我们想查某个用户发的信息,我们可以设置scan的start rowkey 为该userId,end rowkey为userId+1即可。 当我们要查某个用户某天发了什么信息,我们可以使用<userId>-<date>来搜索该用户所有的帖子。 当我们要查某个具体的帖子的内容,rowkey过滤<userId>-<date>-<messageId>即可。 所以rowkey的设计是要看具体的应用的。 上面这个例子没有考虑热点的问题,实际上每个用户的帖子被访问的热度是不一样的,有些帖子被大量访问,有的无人问津。 那怎么办呢?有的书上写,在前面加0-n的随机数,random % 机器数 。但是这样子的话,以后你想取某个用户的userId的时候只能开多线程去访问了,因为你不能逆推出来它的rowkey。在和支付宝的工程狮聊了一下,他们是这样处理的取md5(userId)的前4位+reverse(userId)这个样子来处理userId,这样子的话,能解决热点的问题,也可以逆推出来rowkey。

优秀的个人博客,低调大师

MapReduce编程实现学习

MapReduce主要包括两个阶段:一个是Map,一个是Reduce. 每一步都有key-value对作为输入和输出。 Map阶段的key-value对的格式是由输入的格式决定的,如果是默认的TextInputFormat,则每行作为一个记录进程处理,其中key为此行的开头相对文件的起始位置,value就是此行的字符文本。Map阶段的输出的key-value对的格式必须同reduce阶段的输入key-value对的格式相对应。 下面开始尝试,假设我们需要处理一批有关天气的数据,其格式如下:按照ASCII码存储,每行一条记录每一行字符从0开始计数,第15个到第18个字符为年第25个到第29个字符为温度,其中第25位是符号+/- Text文本样例: 0067011990999991950051507+0000+ 0043011990999991950051512+0022+ 0043011990999991950051518-0011+ 0043012650999991949032412+0111+ 0043012650999991949032418+0078+ 0067011990999991937051507+0001+ 0043011990999991937051512-0002+ 0043011990999991945051518+0001+ 0043012650999991945032412+0002+ 0043012650999991945032418+0078+ 上代码啦: package Hadoop; import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.Reducer.Context; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.input.TextInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; import java.io.IOException; import java.util.StringTokenizer; /** * Created by root on 4/23/16. */ public class hadoopTest extends Configured implements Tool{ //map将输入中的value复制到输出数据的key上,并直接输出 public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> { //实现map函数 @Override public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); String year = line.substring(15, 19); int airTemperature; if (line.charAt(25) == '+') { airTemperature = Integer.parseInt(line.substring(26, 30)); } else { airTemperature = Integer.parseInt(line.substring(25, 30)); } context.write(new Text(year), new IntWritable(airTemperature)); } } //reduce将输入中的key复制到输出数据的key上,并直接输出 public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> { public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int maxValue = Integer.MIN_VALUE; for (IntWritable sorce : values) { maxValue = Math.max(maxValue, sorce.get()); } context.write(key, new IntWritable(maxValue)); } } @Override public int run(String[] arg0) throws Exception { //这里测试用,传入的路径直接赋值 String InputParths = "/usr/local/hadooptext.txt"; String OutputPath = "/usr/local/hadoopOut"; //声明一个job对象,这里的getConf是获取hadoop的配置信息,需要继承Configured. Job job = new Job(getConf()); //设置job名称 job.setJobName("AvgSorce"); //设置mapper输出的key-value对的格式 job.setOutputKeyClass(Text.class); //设置Mapper,默认为IdentityMapper,这里设置的代码中的Mapper job.setMapperClass(hadoopTest.Map.class); //Combiner可以理解为小的Reducer,为了降低网络传输负载和后续Reducer的计算压力 可以单独写一个方法进行调用 job.setCombinerClass(Reduce.class); //设置reduce输出的key-value对的格式 job.setOutputValueClass(IntWritable.class); //设置输入格式 job.setInputFormatClass(TextInputFormat.class); //设置输入输出目录 FileInputFormat.setInputPaths(job, new Path(InputParths)); FileOutputFormat.setOutputPath(job, new Path(OutputPath)); boolean success = job.waitForCompletion(true); return success ? 0 : 1; } public static void main(String[] args) throws Exception { int ret = ToolRunner.run(new hadoopTest(), args); System.exit(ret); } } Map函数继承自MapReduceBase,它实现了Mapper接口,此接口是一个范型类型,它有4种形式的参数,分别用来指定map的输入key值类型、输入value值类型、输出key值类型和输出value值类型。这里使用的是TextInputFormat,它的输出key值是LongWritable类型,输出value是Text类型。因为需要输出<word,1>形式,因此输出的key值类型是Text,输出的value值类型是IntWritable InputFormat()和inputSplit InputSplit是Hadoop定义的用来传输给每个单独的map的数据,InputSplit存储的并非数据本身,而是一个分片长度和一个记录数据位置的数组。生成InputSplit的方法可以通过InputFormat()来设置。当数据传输给map时,map会将输入分片传送到InputFormat上,InputFormat调用getRecordReader()方法生成RecordReader,RecordReader再通过creatKey()、creatValue()方法创建可供map处理的<key,value>对,即<k1,v1>,InputFormat()方法是用来生成可供map处理的<key,value>对的。 TextInputFormat是Hadoop默认的输入方法,在TextInputFormat中,每个文件都会单独地作为map的输入,而这是继承自FileInputFormat的,之后,每行数据都会生成一条记录,每条记录则表示成<key,value>形式。 这里的key是每个数据的记录在数据分片中的字节偏移量,数据类型是LongWritable. value值是每行的内容,数据类型是Text. 执行结果:

优秀的个人博客,低调大师

hadoop学习笔记--集群搭建

注:大家常说的ssh其实就是一个免密码访问的东西,为了简化操作的,不用每次访问其他节点重新输入密码。但是要想配置如下: 1.在每台机器上执行 ssh-keygen -t rsa,连敲三次回车键(即设置空密码) 2.然后在每台机器上都执行cd ~/.ssh,并分别把id_rsa.pub复制到authorized_keys中, 即执行 cp id_rsa.pub authorized_keys 3.然后分别把slave0,slave1的authorized_keys都复制到master主节点的authorized_keys中, 即分别在两个从节点slave0和slave1中执行 ssh-copy-id -i master 4.再分别复制到slave0,slave1中(即每一个节点的authorized_keys中都有这三个节点的密钥) 即在主节点master上执行 scp -r ~/.ssh/authorized_keys slave0:~/.ssh/ scp -r ~/.ssh/authorized_keys slave1:~/.ssh/ 此时成功。 简单测试:比如说在master上执行ssh slave0,这时候发现不需要输入密码即可转 到slave0从节点上,这时成功 hadoop-0.20.2的配置文件 hadoop-0.20.0的配置文件: core-site.xml <property> <name>fs.default.name</name> <value>hdfs://cMaster:9000</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/joe/cloudData</value> </property> hdfs-site.xml <property> <name>dfs.name.dir</name> <value>/home/joe/hdfs/name</value> </property> <property> <name>dfs.data.dir</name> <value>/home/joe/hdfs/data</value> </property> <property> <name>dfs.replication</name> <value>1</value> </property> mapred-site.xml <property> <name>mapred.job.tracker</name> <value>cMaster:9001</value> </property> hadoop-0.20.2集群操作命令: hadoop-0.20.2的集群操作命令 上传本地文件至hdfs:[rio@cMaster hadoop-0.20.2]#bin/hadoop dfs -put /home/rio/input/* /in 用WordCount计算数据:[rio@cMaster hadoop-2.2.0]#bin/hadoop jar hadoop-0.20.2-examples.jar wordcount /in /out/wc-01 hadoop-2.2.0的配置文件: hadoop-2.2.0的配置文件: core-site.xml <property> <name>fs.defaultFS</name> <value>hdfs://cMaster:8020</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/home/joe/cloudData</value> </property> yarn-site.xml <property> <name>yarn.resourcemanager.hostname</name> <value>cMaster</value> </property> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> mapred-site.xml(注:将mapred-site.xml.template重命名为mapred-site.xml) <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> hadoop-2.2.0进程启动命令: 启动(或关闭)全部服务:[rio@cMaster hadoop-2.2.0]#sbin/start-all.sh [rio@cMaster hadoop-2.2.0]#sbin/stop-all.sh 格式化主节点:[rio@cMaster hadoop-2.2.0]#bin/hdfs namenode -format(注:仅格式化一次) 启动主节点上的namenode:[rio@cMaster hadoop-2.2.0]#sbin/hadoop-daemon.sh start namenode 启动主节点上的resourcemanager:[rio@cMaster hadoop-2.2.0]#sbin/yarn-daemon.sh start resourcemanager 启动从节点上的datanode:[rio@cMaster hadoop-2.2.0]#sbin/hadoop-daemon.sh start datanode 启动从节点上的nodemanager:[rio@cMaster hadoop-2.2.0]#sbin/yarn-daemon.sh start nodemanager 启动日志历史查询:[rio@cMaster hadoop-2.2.0]#sbin/mr-jobhistory-daemon.sh start historyserver 查看服务是否启动:[rio@cMaster hadoop-2.2.0]#/usr/java/jdk1.8.0_71/bin/jps hadoop-2.2.0集群操作命令: 创建目录:[rio@cMaster hadoop-2.2.0]#bin/hdfs dfs -mkidr /in 删除文件及目录:[rio@cMaster hadoop-2.2.0]#bin/hdfs dfs -rmr /out/input 上传本地文件至hdfs:[rio@cMaster hadoop-2.2.0]#bin/hdfs dfs -put /home/rio/input/* /in 查看hdfs里的文件:[rio@cMaster hadoop-2.2.0]#bin/hdfs dfs -cat /in/* [rio@cMaster hadoop-2.2.0]#bin/hdfs dfs -cat /out/wc-01/* 用WordCount计算数据:[rio@cMaster hadoop-2.2.0]#bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-example-2.2.0.jar wordcount /in /out/wc-01 当神已无能为力,那便是魔渡众生

优秀的个人博客,低调大师

Hadoop学习(二)——HDFS简介

Hadoop提供了一个被称为HDFS的分布式文件系统的实现。HDFS是Hadoop系统的基础层,主要负责数据的存储、管理和容错处理,设计思想来源于Google的GFS(Google File System)文件系统。HDFS是一个运行在普通的硬件之上的分布式文件系统,它和现有的分布式文件系统有着很多的相似性,然而和其他分布式文件系统的区别也很明显:HDFS是高容错性的,可以部署在低成本的硬件之上;HDFS提供高吞吐量以应对应用程序数据访问,适合大数据集的应用程序;HDFS放开一些POSIX的需求去实现流式地访问文件数据;HDFS最初是为开源的Apache项目Nutch的基础结构而创建;HDFS是Hadoop项目的一部分。 HDFS的特点 HDFS认为硬件出现错误是经常发生的事情。HDFS部署在由廉价机器组成的集群中,整个集群中可能会有非常多的机器结点,结点的故障也是不可避免的,这种情况下,HDFS必须保证某些结点故障时,整个集群的工作不会受到影响。 HDFS支持超大规模的数据集。 HDFS采用“一次写入多次读取”的文件访问模型。HDFS简化了传统的文件访问模型,它假定当一个文件被创建、写入并关闭后就不会被修改了。 HDFS提供了类似于流式的数据访问模式。并不是标准的流式,而是将数据以较小的数据包的形式进行传输,提供数据方法的吞吐量。 HDFS提供了很强的容错处理能力。HDFS将大文件分割成很多文件块分开存储,并采用了完全备份的策略,每个文件块的副本数量最少是3个。 HDFS具有很强的系统扩展性。HDFS可以动态的向集群中添加或者从集群中撤出结点。 HDFS具有良好的平台移植性。由于HDFS是用Java语言开发的,所以它可以运行在Linux、Windows的等操作系统上,具有很好的可移植性。 HDFS文件系统架构 HDFS系统架构采用主从架构,整个集群由一个NameNode、一个SecondNameNode和若干个DataNode组成。NameNode是一个中心服务器,负责管理整个文件系统的命名空间元数据和客户端对文件的访问。SecondNameNode是NameNode的备份结点,定期对NameNode上的系统信息文件进行备份。一般情况下,一个结点运行一个DataNode,主要负责存储用户数据,并在NameNode的控制下进行数据的读写和出错处理。在HDFS内部,一个文件会被分隔成一个或多个Block,这些Block存储在DataNode上。

优秀的个人博客,低调大师

Hadoop学习笔记(四):HBase

HBase是在一个HDFS上开发的面向列的分布式数据库。HBase不是关系型数据库,不支持SQL。 HTable一些基本概念 Row key 行主键, HBase不支持条件查询和Order by等查询,读取记录只能按Row key(及其range)或全表扫描,因此Row key需要根据业务来设计以利用其存储排序特性(Table按Row key字典序排序如1,10,100,11,2)提高性能。 Column Family(列族) 在表创建时声明,每个Column Family为一个存储单元。在上例中设计了一个HBase表blog,该表有两个列族:article和author。 Column(列) HBase的每个列都属于一个列族,以列族名为前缀,如列article:title和article:content属于article列族,author:name和author:nickname属于author列族。Column不用创建表时定义即可以动态新增,同一Column Family的Columns会群聚在一个存储单元上,并依Column key排序,因此设计时应将具有相同I/O特性的Column设计在一个Column Family上以提高性能。 Timestamp HBase通过row和column确定一份数据,这份数据的值可能有多个版本,不同版本的值按照时间倒序排序,即最新的数据排在最前面,查询时默认返回最新版本。如上例中row key=1的author:nickname值有两个版本,分别为1317180070811对应的“一叶渡江”和1317180718830对应的“yedu”(对应到实际业务可以理解为在某时刻修改了nickname为yedu,但旧值仍然存在)。Timestamp默认为系统当前时间(精确到毫秒),也可以在写入数据时指定该值。 Value 每个值通过4个键唯一索引,tableName+RowKey+ColumnKey+Timestamp=>value,例如上例中{tableName=’blog’,RowKey=’1’,ColumnName=’author:nickname’,Timestamp=’ 1317180718830’}索引到的唯一值是“yedu”。 存储类型 TableName 是字符串RowKey 和 ColumnName 是二进制值(Java 类型 byte[])Timestamp 是一个 64 位整数(Java 类型 long)value 是一个字节数组(Java类型 byte[])。 SHELL操作 HBase提供了丰富的访问接口,其中HBase Shell是常用的便捷方式。 • HBase Shell • Java clietn API • Jython、Groovy DSL、Scala • REST • Thrift(Ruby、Python、Perl、C++…) • MapReduce • Hive/Pig 创建表> create 'test','data1','data2' Column Family是schema的一部分,而Column不是。这里的data1和data2是Column Family。 增加记录>put 'test','1','data1:name','luc'>put 'test','1','data1:age','24'>put 'test','1','data2:height','170cm'>put 'test','1','data2:weight','65kg'>put 'test','1','data1:nickname','vichao'Column完全动态扩展,每行可以有不同的Columns。(ps:好像有点胖啊,要减肥~~) 根据RowKey查询> get 'test','1' HTable按RowKey字典序(1,10,100,11,2)自动排序,每行包含任意数量的Columns,Columns按ColumnKey(data1:age,data1:name,data1:nickname,data2:height,data2:weight)自动排序。 更新操作 查询值: >get 'test','1','data1:nickname' 更新nickname为'vic': >put 'test','1','data1:nickname','vic' 查询更新后的结果:(返回的将是vic) > get ‘blog’,’1’,’data1:nickname’ 知识点回顾:查询默认返回最近的值。 查询nickname的多个(本示例为2个)版本值 > get 'test','1',{COLUMN => 'data1:nickname',VERSIONS => 2}知识点回顾:每个Column可以有任意数量的Values,按Timestamp倒序自动排序。 如何只查询到以前的旧版本呢,需要借助Timestamp >get 'test','1',{COLUMN=>'data1:nickname',TIMESTAMP=>1373707746997} 知识点回顾:TabelName+RowKey+Column+Timestamp=>Value 删除记录 delete只能删除一个column >delete 'test','1','data1:nickname' 删除RowKey的所有column用deleteall >deleteall 'test','1' 删除表练习完毕,把练习表删了吧,删除之前需要先disable>disable 'test'>drop 'test' JAVA API操作 javaAPI操作还是比较简单的,各种api类和api函数,直接上代码了 import java.io.IOException; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.client.HTable; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.conf.Configuration; public class ExampleClient { public static void main(String[] args) throws IOException { Configuration conf = HBaseConfiguration.create(); // Create table HBaseAdmin admin = new HBaseAdmin(conf); HTableDescriptor htd = new HTableDescriptor("test"); HColumnDescriptor hcd = new HColumnDescriptor("data"); htd.addFamily(hcd); admin.createTable(htd); byte[] tablename = htd.getName(); HTableDescriptor[] tables = admin.listTables(); if (tables.length != 1 && Bytes.equals(tablename, tables[0].getName())) { throw new IOException("Failed create of table!"); } // Run some operations HTable table = new HTable(conf, tablename); byte[] row1 = Bytes.toBytes("row1"); Put p1 = new Put(row1); byte[] databytes = Bytes.toBytes("data"); p1.add(databytes, Bytes.toBytes("1"), Bytes.toBytes("value1")); table.put(p1); Get g = new Get(row1); Result result = table.get(g); System.out.println("GET:" + result); Scan scan = new Scan(); ResultScanner scanner = table.getScanner(scan); try { for (Result scannerResult : scanner) { System.out.println("Scan:" + scannerResult); } } catch (Exception e) { e.printStackTrace(); } finally { scanner.close(); } // Drop the table admin.disableTable(tablename); admin.deleteTable(tablename); } } 这里要注意的一点是连接到HBase需要将将HBase环境的hbase-site.xml文件引入到工程中,就像jdbc的数据库连接一样,不然是连不上hbase滴。 Configuration conf = HBaseConfiguration.create();//这行代码会从hbase-site.xml中读取配置信息 HBase MapReduce操作 直接上代码了: import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.KeyValue; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil; import org.apache.hadoop.hbase.mapreduce.TableMapper; import org.apache.hadoop.hbase.mapreduce.TableReducer; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.mapreduce.Job; public class testHBaseMR { public static class Mapper extends TableMapper<ImmutableBytesWritable, ImmutableBytesWritable> { public Mapper() { } @Override public void map(ImmutableBytesWritable row, Result values, Context context) throws IOException { ImmutableBytesWritable value = null; String[] tags = null; for (KeyValue kv : values.list()) { if ("author".equals(Bytes.toString(kv.getFamily())) && "nickname".equals(Bytes.toString(kv.getQualifier()))) { value = new ImmutableBytesWritable(kv.getValue()); } if ("article".equals(Bytes.toString(kv.getFamily())) && "tags".equals(Bytes.toString(kv.getQualifier()))) { tags = Bytes.toString(kv.getValue()).split(","); } } for (int i = 0; i < tags.length; i++) { ImmutableBytesWritable key = new ImmutableBytesWritable( Bytes.toBytes(tags[i].toLowerCase())); try { context.write(key, value); } catch (InterruptedException e) { throw new IOException(e); } } } } public static class Reducer extends TableReducer<ImmutableBytesWritable, ImmutableBytesWritable, ImmutableBytesWritable> { @Override public void reduce(ImmutableBytesWritable key, Iterable values, Context context) throws IOException, InterruptedException { String friends = ""; for (ImmutableBytesWritable val : values) { friends += (friends.length() > 0 ? "," : "") + Bytes.toString(val.get()); } Put put = new Put(key.get()); put.add(Bytes.toBytes("person"), Bytes.toBytes("nicknames"), Bytes.toBytes(friends)); context.write(key, put); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); conf = HBaseConfiguration.create(conf); Job job = new Job(conf, "HBase_FindFriend"); job.setJarByClass(testHBaseMR.class); Scan scan = new Scan(); scan.addColumn(Bytes.toBytes("author"), Bytes.toBytes("nickname")); scan.addColumn(Bytes.toBytes("article"), Bytes.toBytes("tags")); TableMapReduceUtil .initTableMapperJob("blog", scan, Mapper.class, ImmutableBytesWritable.class, ImmutableBytesWritable.class, job); TableMapReduceUtil .initTableReducerJob("tag_friend", Reducer.class, job); System.exit(job.waitForCompletion(true) ? 0 : 1); } } TableMapReduceUtil.initTableMapperJob;TableMapReduceUtil.initTableReducerJob 用来指定map和reduce。相当于hbase的MR操作工具类吧~ 优化 针对行的键按数据排列的次序进行随机处理; 每个任务只实例化一个HTable对象; HTable.put(put)执行put操作时不使用任何缓冲。可以通过使用HTable.setAutoFlush(false),设置禁用自动刷入,并设置写缓冲大小,同时在任务的最后设置HTable.flushCommits()或者HTable.close(),以确保缓冲中最后没有剩下的未刷入的数据; 设计行键的时候要多加考虑,可以使用复合键,如果键是整数,则应该使用二进制形式以节省存储空间; HBase和RDBMS的比较 HBase: HBase是一个分布式的面向列的数据存储系统; HBase表可以很高和很宽(数十亿行,数百万列); 水平分区并在数千个商用机节点上自动复制; 表的模式是物理存储的直接反映; 不支持SQL; 不需要强一致性和参照完整性; 不支持索引;行是顺序存储的,每行中的列也是,不存在索引膨胀的问题,插入性能和表的大小无关 事务好像仅仅支持针对某一行的一系列Put/Delete操作。不同行、不同表间的操作是无法放在一个事务中的; HBase不支持条件查询和Order by等查询,读取记录只能按Row key(及其range)或全表扫描; 没有内置对连接操作的支持,但是由于表的宽度可以很大,一个宽行可以容下一个主键相关的所有数据,并不需要使用连接; RDBMS: 支持SQL; 需要强一致性和参照完整性; 支持事务,索引等; HBase的特性 没有索引,行是顺序存储的,每行中的列也是,不存在索引膨胀的问题,插入性能和表的大小无关; 自动分区,在表增长的时候,表会自动分裂成区域,并分布到可用的节点上; 线性扩展和对于新节点的自动处理,增加一个节点,把它指向现有的集群,并运行Regionserver,区域会自动重新进行平衡,负载会均匀分布; 普通商用硬件支持; 容错,大量节点意味着每个节点的重要性并不突出,不用担心单个节点失效; 批处理,支持MapReduce操作,可以用全并行的分布式作业来处理数据;

优秀的个人博客,低调大师

同时开启JAVA学习记录

大概翻了一下HADOOP的资料。 好像会点JAVA语法,更能深入了争MAP和REDUCE过程。 那只好再开启这个JAVA了。 印象中,大学时,上世纪九十年代,我就买过类似JAVA的书,但一直是当新奇玩意看,从未到现在这样触及IT心脏的了解过它。 去年,也简短的涉及过,由于没有应用目标,也是草草看过了事。 现在从浅到深,再慢慢来过中。 以网上PDF《JAVA基础教程-JAVA快车》为蓝本,先慢慢干起来。。

优秀的个人博客,低调大师

学习Hbase之quick start

1.2. Quick Start Loopback IP /etc/hosts should look something like this: vi /etc/hosts 127.0.0.1 localhost 127.0.0.1 ubuntu.ubuntu-domain ubuntu 1.2.1. Download and unpack the latest stable release.(下载和解压稳定版本) $ tar xfvz hbase-0.94.3-security.tar.gz $ cd hbase-0.94.3-security 安装之前,编辑 conf/hbase-site.xml.其中hbase.rootdir,是Hbase写数据的目录 其中hbase.zookeeper.property.dataDir,是ZooKeeper写数据的目录 <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> hbase.rootdir /data/hbase hbase.zookeeper.property.dataDir /data/zookeeper 1.2.2. Start HBase [root@ZSDDB8 hbase-0.94.3-security]# ./bin/start-hbase.sh starting master, logging to /root/hbase-0.94.3-security/bin/../logs/hbase-root-master-ZSDDB8.out 这样就算开启了单实例的HBase Is java Installed?可以查看http://blog.chinaunix.net/space.php?uid=26446098&do=blog&id=3438622 java7安装方式1.2.3. Shell Exercises 通过shell连接HBASE [root@ZSDDB8 hbase-0.94.3-security]# ./bin/hbase shell HBase Shell; enter 'help' for list of supported commands. Type "exit" to leave the HBase Shell Version 0.94.3, r1408904, Wed Nov 14 16:41:36 UTC 2012 hbase(main):001:0> 创建一个表为test且一个列集合为cf。通过list 'test'验证它的创建然后插入一些数据 hbase(main):003:0> create 'test', 'cf' 0 row(s) in 1.2200 seconds hbase(main):002:0> list 'test' TABLE test 1 row(s) in 0.0170 seconds 1 row(s) in 0.0550 seconds hbase(main):004:0> put 'test', 'row1', 'cf:a', 'value1' 0 row(s) in 0.0560 seconds hbase(main):005:0> put 'test', 'row2', 'cf:b', 'value2' 0 row(s) in 0.0370 seconds hbase(main):006:0> put 'test', 'row3', 'cf:c', 'value3' 0 row(s) in 0.0450 seconds 通过执行scan 命令验证刚插入的数据 hbase(main):006:0> scan 'test' ROW COLUMN+CELL row1 column=cf:a, timestamp=1355386368983, value=value1 row2 column=cf:b, timestamp=1355386374028, value=value2 row3 column=cf:c, timestamp=1355386377745, value=value3 3 row(s) in 0.0600 seconds 得到一行的数据 hbase(main):007:0> get 'test', 'row1' COLUMN CELL cf:a timestamp=1355386368983, value=value1 1 row(s) in 0.0330 seconds 现在disable然后drop掉你的表,就可以清除上面你做的所有操作 hbase(main):008:0> disable 'test' 0 row(s) in 2.0730 seconds hbase(main):009:0> drop 'test' 0 row(s) in 0.1100 seconds 退出 hbase(main):013:0> exit 1.2.4. Stopping HBase 执行stop-hbase.sh关闭HBase $ ./bin/stop-hbase.sh [root@ZSDDB8 hbase-0.94.3-security]# ./bin/stop-hbase.sh stopping hbase........... 1.2.5.Where to go next The above described standalone setup is good for testing and experiments only. In the next chapter, Chapter2, Apache HBase (TM) Configuration, we'll go into depth on the different HBase run modes, system requirements running HBase, and critical configurations setting up a distributed HBase deploy.

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册