Eric Chang's Blog


  • 首页

  • 归档

  • 分类

  • 标签

  • 生活

  • 关于

  • 搜索

git常用命令

发表于 2015-07-31 | 分类于 git |

引言

  • git是常用的版本管理工具
  • 本文总结了git最常用的命令,应当熟记于心
  • 使用git应当尽量使用命令行,这样可以帮助熟悉git的流程

配置和状态:

git status git现在状态

git init 初始化git,生成 .git 文件;

常用动作:

git clone (url) 将工程的master分支clone下来;

git clone (url) (空格) (目录) 仅仅将repository某个目录clone到本地;

git clone (url) (空格) /(目录) 将git这个目录下的所有文件下载到本地这个目录下;

git clone -b branchName (url) 将一个分支clone到本地;

git checkout -b csy_ui origin/csy_ui_m clone另一个分支到本地的新建分支中;

git checkout branchName 切换到某个分支,在checkout前需保证当前分支已经commit,否则会报错;

git merge (被合并分支名称) 将被合并分支合并到当前分支,执行此命令后,没有冲突的都已经merge到当前分支,有冲突的会提示,用编辑器解决完冲突后,直接add以及commit即可完成整个merge过程,不用重新merge;

git branch test 新建名为test的分支;

git checkout -b test 新建名为test的分支,并checkout到该分支;

git add . add改动到暂存区域;

git commit -a -m “….” commit改动到repository;

git push origin master push到名字为origin的远端的master分支中;

git diff 对比当前分支在当前状态下和刚刚写换到这个分支的时候有什么不同,列出改动的文件和具体改动哪些内容;

git mv old_name new_name 重命名文件

历史和记录:

git log/git log –graph 查看git历史动作

history 查看git命令历史记录

进制、文件和编码的理解

发表于 2015-07-30 | 分类于 others |

引言

  • 进制、文件、编码是计算机系统的重要概念,应当理解;
  • 本文介绍了进制、文件、编码应当掌握的基本内容

进制

  • 进制间转换请戳这里;

编码

  • 编码是信息从一种形式或格式转换为另一种形式的过程;
  • 常见编码格式:ascii、GBK、UTF-8;
  • 无论何种编码,最终要在计算机中以二进制形式存储,英文和中文占用字节数目不同,具体占用几个字节由编码方式决定;
  • 计算机的文件分为二进制文件和文本文件,二进制文件是经过编译后的,用编辑器打开肯定是乱码,而文本文件中存储了此文件的编码方式,如果编辑器可以自动识别这个文本文件的编码方式,则用编辑器打开文本文件时就会自动正确解码,不会有乱码现象;

文件

  • 计算机的文件有两种:文本文件、二进制文件;
  • 计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的,也可以说文本文件是二进制文件的特殊形式;
  • 两者区别:
    • 文本文件是基于字符编码的文件,常见的编码有ASCII编码,UNICODE编码等等,先将文件中的人类可识别的字符转换为一串数字(具体怎么转换由编码方式决定),然后以二进制的形式存储在计算机中;
    • 二进制文件是基于值编码的文件,你可以根据具体应用,指定某个值是什么意思;
    • 文本文件能够用编辑器打开,二进制文件不能(乱码),二进制文件能够用特定的软件读取其中的内容(WinHex、UltraEdit);
  • 例子1:
    • 文本文件:中文和英文文档、源代码文档;
    • 二进制文件:经过编译后的.class文件、可执行文件.exe;
  • 例子2:
    • 如果用文本文件存储int类型的数字1,其中存储的是1的ascii码(假定用ascii编码)49(一个字节),再将49转换成二进制进行物理存储,读取的时候读到的是49,经过解码显示数字1;
    • 如果用二进制文件存储int类型的数字1,由于int类型占用四个字节,故文件中存储的是四个字节00000000 00000000 00000000 00000001,在读取文件的时候应当告知以int方式读取,即四个四个字节读取;

JVM运行时数据区

发表于 2015-07-29 | 分类于 Java |

JVM运行时数据区的理解

  • 运行时数据区面向线程,而不面向类或方法或对象;
  • 线程共享:方法区、堆内存(heap),线程私有:虚拟机栈(栈内存stack)、本地方法栈、程序计数器;
  • 程序计数器:存放线程执行位置(main函数也是一个线程);
  • 虚拟机栈(栈内存):生命周期和对应的线程相同,存放该线程的局部变量、对象的引用;方法中可能嵌套调用别的方法,这些方法的变量以”先进后出、后进先出“的方式在栈内存中存储,所以内层方法无法访问外层方法的变量(他们在栈底),执行外层方法时内层方法的变量已经弹出栈消失了,所以外层方法也不会访问到内层方法的变量;一个方法的执行过程,就是这个方法对于帧栈的入栈出栈过程;
  • 本地方法栈:作用和虚拟机栈完全相同;虚拟机栈对应普通的java方法,本地方法栈对应native方法;native方法是一个java调用非java代码的接口;
  • 方法区:JVM内存管理中最大一块;存储常量(final修饰)、类变量/成员变量(static修饰)、类信息(每个类的访问控制符、修饰符、继承关系等);
  • 堆内存:JVM启动时创建,存放对象本身,不存放对对象的引用(引用存在栈内存);
  • JVM垃圾收集特指收集堆内存中的失去引用的对象的存储空间;栈内存存储空间不予收集;如果一个对象长期不失去引用、但在程序中已经没有用,那么系统不会进行垃圾收集,可能造成内存泄露/内存溢出;

常用快捷键

发表于 2015-07-29 | 分类于 others |

引言

  • 本文分类总结了常用快捷键
  • 编程时应当尽量使用键盘输入,避免过多的鼠标操作,可以提升编程效率
  • 必要时可以为IDE安装emmet等插件,方便编程和开发

编辑:

ctrl+c:复制

ctrl+v:粘贴

ctrl+shift+v:无格式粘贴

ctrl+x:剪切

ctrl+f:查找

ctrl+z:返回上一状态

ctrl+y:返回下一状态

ctrl+s:保存

ctrl+a:全选

windows系统:

ctrl+tab:标签页切换

alt+tab:窗口切换

alt+滑轮:字体大小转换

windows+d:桌面

windows+e:打开计算机文件夹

windows+r:打开终端

启动按F12:显示启动项

浏览器:

F5:刷新;

F12:开发者工具;

Ctrl+U:查看源代码;

F11:全屏;

Ctrl+N:打开新窗口;

Alt+F4:关闭当前窗口;

Ctrl+T:打开新标签页;

Ctrl+W:关闭当前标签页或弹出式窗口;

Ctrl+Tab:切换到下一个标签页 ;

Ctrl+Shift+Tab:切换到上一个标签页;

Ctrl+1到Ctrl+8:切换到指定位置编号的标签页;

linux系统:

ctrl+alt+T:打开终端

ctrl+alt+L:锁屏

编程/普通编辑器/IDE:

ctrl+space或alt+/:补全代码

ctrl+p:Show parameters for selected method,函数参数提示;

shift+alt+F:格式化代码

ctrl+/:注释代码

ctrl+L:清空控制台

ctrl+Home/End:选中当前光标所在位置之前/之后的一个单词;

ctrl+shift+Home/End:选中当前光标所在位置之前/之后的所有字符;

shift+左右箭头:以字符为单位选中;

ctrl+左右箭头:以单词为单位跳转;

shift+ctrl+左右箭头:以单词为单位选中;

alt+shift+上下箭头:本行和上下行换行;

ctrl+x:删除行;

ctrl+d:复制本行到下一行;

shift+alt+s:自动生成代码(比如get set方法);

选中代码块右键>surround with:自动生成代码(比如try…catch块儿);

MapReduce编程技巧和注意事项

发表于 2015-05-11 | 分类于 hadoop |

引言

  • 在编写Mapreduce程序的过程中会遇到各种各样的问题,本文为您梳理了常见的问题、注意事项和技巧;

MapReduce中常见的数据类型转换方法

类型转换 方法汇总
int>String int i=12345; String s=””; 第一种方法:s=i+””; 第二种方法:s=String.valueOf(i);
String>int s=”12345”; int i; 第一种方法:i=Integer.parseInt(s); 第二种方法:i=Integer.valueOf(s).intValue();
LongWritable>String LongWritable.toString()
String>long Long.parseLong(String)
Text>String Text.toString()
long>LongWritable new LongWritable(long)
String>Text new Text(String)

编程注意事项

  • hadoop特有的数据类型(LongWritable、IntWritable和Text等)和java的数据结构(set、list、map等)不兼容,以下使用情形会出错:
    例如:Set <Text> userSet = new HashSet<Text>(); 或者 List <LongWritable> list = new ArrayList <LongWritable>();
    所以尽量不要同时使用;

  • reduce中遍历values的过程只能执行一遍,因为values是Iterable迭代器类型;如果需要多次遍历values内容,要么每次遍历前移动迭代器指针到初始位置,要么第一次遍历时将values内容放入list中,方便以后重复访问;

  • map的输出必须是Writable类型的(比如IntWritable、LongWritable、Text),如果是普通java类型(Integer、Long、String)会出错(报错:Unable to initialize MapOutputCollector);

  • map的输入固定为,输入类型为,这些都不能随意更改,如需更改,要重写inputFormat;

Mapreduce程序参数设置

参数 设置方法
不执行reduce函数 job.setNumReduceTasks(0);此时不执行reduce,输出文件的数量就是map的数量;
设置执行map的类 job.setMapperClass(FlowFilter.class);
设置执行combine的类(一般就是reduce类) job.setCombinerClass(Reduce.class);
设置执行reduce的类 job.setReducerClass(DNTGUserInfoReducer.class);
设置map的数量 job.setNumMapTasks(maps);
设置reduce数量(最终输出文件数量) job.setNumReduceTasks(reduces);
设置文件输入类型(默认为inputFormat,一行一行读取) job.setInputFormatClass(ProvinceInputFormat.class);
设置map的输出类型(key、value类型) job.setMapOutputKeyClass(HMKey.class); job.setMapOutputValueClass(HMValue.class);
设置redcue的输出类型(key、value类型) job.setReduceOutputKeyClass(Text.class); job.setReduceOutputValueClass(IntWritable.class);
统一设置map和reduce的输出类型 job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class);
设置整个程序输入、输出路径 FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));

MapReduce设计模式实例解析

发表于 2015-05-10 | 分类于 hadoop |

引言

  • MapReduce设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的代码设计经验总结;
  • 使用设计模式的目的:使用设计模式是为了提高编码效率、提高代码重用率、让代码更容易被他人理解、保证代码可靠性;
  • 设计模式千万种,本文为您梳理出来最重要、最常用的几种设计模式,方便理解和掌握;
  • 本文的每一种设计模式都搭配了实例程序,以及输入和输出,让您更好更快地理解;

计数(Counting)一

  • 问题定义:在数据文件中包含大量的记录,每条记录中包含了某个实体的若干数值属性,目标问题是要计算每个实体的某个数值属性的函数表达式值,例如求和、平均值等;
  • 具体问题描述:现在有一个英文文件,需要统计其中每个单词的个数(wordcount);
  • 解决方案:在map中分离每个单词,传入reduce,在reduce中将每个单词的value相加;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package wordcountTest;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

public static class Map
extends Mapper<LongWritable, Text, Text, IntWritable>{


private final static IntWritable one = new IntWritable(1); // type of output value
private Text word = new Text(); // type of output key

public void map(LongWritable key, Text value, Context context
) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString()); // line to string token

while (itr.hasMoreTokens()) {
word.set(itr.nextToken()); // set word as each input keyword
context.write(word, one); // create a pair <keyword, 1>
}
}
}

public static class Reduce
extends Reducer<Text,IntWritable,Text,IntWritable> {


private IntWritable result = new IntWritable();

public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {
int sum = 0; // initialize the sum for each keyword
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);

context.write(key, result); // create a pair <keyword, number of occurences>
}
}

// Driver program
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); // get all args
if (otherArgs.length != 2) {
System.err.println("Usage: WordCount <in> <out>");
System.exit(2);
}

// create a job with name "wordcount"
Job job = new Job(conf, "wordcount");
job.setJarByClass(WordCount.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);

// uncomment the following line to add the Combiner
job.setCombinerClass(Reduce.class);

// set output key type
job.setOutputKeyClass(Text.class);
// set output value type
job.setOutputValueClass(IntWritable.class);
//set the HDFS path of the input data
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
// set the HDFS path for the output
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));

//Wait till job completion
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出:
1
2
3
4
5
6
7
8
9
输入:一篇英文文章,单词之间用空格分割
apple banana banana yellow
yellow orange apple orange

输出:词频统计结果
apple 2
banana 2
yellow 2
orange 2

计数(Counting)二

  • 具体问题描述:输入文件为两列,分别为用户手机号和流量数,现需要统计每个用户的总流量数;
  • 解决方案:map中将每个用户的手机号、流量分别作为key和value传入reduce,由reduce来统计总流量数;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package wordcountTest;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

public static class Map
extends Mapper<LongWritable, Text, Text, IntWritable>{

private final static IntWritable one = new IntWritable(1); // type of output value
private Text user = new Text(); // type of output key
private IntWritable flow = new IntWritable();

public void map(LongWritable key, Text value, Context context
) throws IOException, InterruptedException
String line = value.toString();
String [] array = line.split("\t");
if(array.length==2){
user.set(array[0]);
flow = new IntWritable(Integer.parseInt(array[1]));
context.write(user, flow);
}else{
return;
}
}
}

public static class Reduce
extends Reducer<Text,IntWritable,Text,IntWritable> {

private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {
int sum = 0; // initialize the sum for each keyword
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);

context.write(key, result); // create a pair <keyword, number of occurences>
}
}

// Driver program
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); // get all args
System.out.println(System.getenv("HADOOP_HOME"));
if (otherArgs.length != 2) {
System.err.println("Usage: WordCount <in> <out>");
System.exit(2);
}

// create a job with name "wordcount"
Job job = new Job(conf, "userflow");
job.setJarByClass(WordCount.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);

// uncomment the following line to add the Combiner
// job.setCombinerClass(Reduce.class);
// set output key type
job.setOutputKeyClass(Text.class);
// set output value type
job.setOutputValueClass(IntWritable.class);

//set reduce number
job.setNumReduceTasks(1);
//set the HDFS path of the input data
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
// set the HDFS path for the output
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
//Wait till job completion
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出:
1
2
3
4
5
6
7
8
9
10
11
输入:用户手机号和流量,用空格分割
13500000000 10
13800000000 20
13500000000 20
13800000000 15
18700000000 20

输出:每个手机号的总流量
13500000000 30
13800000000 35
18700000000 20

分类(classfication)

  • 问题定义:在数据文件中包含大量的记录,每条记录中包含了某个实体的若干属性,目标问题是在给定一个计算函数的情况下,将此计算函数计算后得到的结果相同的实体放在一起;
  • 具体问题描述:输入数据为两列,分别是手机号和其访问的网址,目的是统计同一个网址有哪些手机号访问过;
  • 解决方案:map阶段把网址、手机号分别作为key、value传入reduce,由reduce实现分类;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package wordcountTest;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

public static class Map
extends Mapper<LongWritable, Text, Text, LongWritable>{


private final static IntWritable one = new IntWritable(1); // type of output value
private Text webPage = new Text(); // type of output key
private LongWritable flow = new LongWritable();

public void map(LongWritable key, Text value, Context context
) throws IOException, InterruptedException {
String line = value.toString();
String [] array = line.split(" ");
if(array.length==2){
webPage.set(array[1]);
flow = new LongWritable(Long.parseLong(array[0]));
context.write(webPage,flow);
}/*else{
return;
}*/

}
}

public static class Reduce
extends Reducer<Text, LongWritable, Text, LongWritable> {


private IntWritable result = new IntWritable();

public void reduce(Text key, Iterable<LongWritable> values,
Context context
) throws IOException, InterruptedException {

for (LongWritable val : values) {
context.write(key, val);
}
}
}

// Driver program
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); // get all args
System.out.println(System.getenv("HADOOP_HOME"));
if (otherArgs.length != 2) {
System.err.println("Usage: WordCount <in> <out>");
System.exit(2);
}

// create a job with name "wordcount"
Job job = new Job(conf, "userflow");
job.setJarByClass(WordCount.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);

// uncomment the following line to add the Combiner
// job.setCombinerClass(Reduce.class);
// set output key type

job.setOutputKeyClass(Text.class);
// set output value type
job.setOutputValueClass(LongWritable.class);

//set reduce number
job.setNumReduceTasks(3);
//set the HDFS path of the input data
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
// set the HDFS path for the output
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
//Wait till job completion
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
输入:手机号和网址,用空格分割
18500000001 sina.com
18500000002 souhu.com
18500000003 sina.com
18500000004 sina.com
18500000005 souhu.com
18500000006 github.com
18500000007 sina.com
18500000008 github.com

输出:每个网址对应的访问过它的手机号
github.com 18500000006
github.com 18500000008
sina.com 18500000001
sina.com 18500000003
sina.com 18500000004
sina.com 18500000007
souhu.com 18500000002
souhu.com 18500000005
  • 说明:本程序并不能实现将每一个网址放入单独的文件输出,这是因为在“shuffle”过程中,计算出的partitionID相同的key被分到一个reduce中,然而,不同的key的partitionID可能相同,即同一个key肯定被分到同一个reduce,但是同一个reduce中可能有不同的key,所以上述算法不能实现完全分类。关于shuffle请参考我的另一篇博客Mapreduce过程详解

过滤(filtering)

  • 问题定义:在数据文件中包含大量的记录,每条记录中包含了某个实体的若干属性,目标问题是在将符合某个条件的记录取出(或进行格式转换);
  • 具体问题描述:输入文件为三列:手机号、属性、访问网站,目标是将属性为0的记录过滤掉;
  • 解决方案:map中将前两列作为key,最后一列为value,判断属性后输出过滤结果即可,不需要reduce过程;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package wordcountTest;

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

public static class Map extends Mapper<Object, Text, String, Text> {

private final static IntWritable one = new IntWritable(1);

private KVcount user = new KVcount(); // type of output key
private Text webPage = new Text();

public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {

String line = value.toString();
String [] array = line.split(" ");
if(array.length==3){
user.setphoneNum(Long.parseLong(array[0]));
user.setattribute(Integer.parseInt(array[1]));
webPage = new Text(array[2]);
if(user.attribute!=0){
context.write(String.valueOf(user.phoneNum)+" "+String.valueOf(user.attribute),webPage);
}

}else{
return;
}
}
}

//本程序不需要reduce过程
public static class Reduce extends
Reducer<KVcount, Text, Text, LongWritable> {

private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<LongWritable> values,
Context context) throws IOException, InterruptedException {

}
}

// Driver program
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args)
.getRemainingArgs(); // get all args
System.out.println(System.getenv("HADOOP_HOME"));
if (otherArgs.length != 2) {
System.err.println("Usage: WordCount <in> <out>");
System.exit(2);
}

// create a job with name "wordcount"
Job job = new Job(conf, "userflow");
job.setJarByClass(WordCount.class);
job.setMapperClass(Map.class);
// job.setReducerClass(Reduce.class);

// uncomment the following line to add the Combiner
// job.setCombinerClass(Reduce.class);
// set output key type

job.setMapOutputKeyClass(KVcount.class);
job.setMapOutputValueClass(Text.class);

// job.setOutputKeyClass(Text.class);
// // set output value type
// job.setOutputValueClass(LongWritable.class);

// set reduce number
job.setNumReduceTasks(0);
// set the HDFS path of the input data
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
// set the HDFS path for the output
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
// Wait till job completion
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
输入:手机号、属性、网站
18500000001 0 sina.com
18500000002 0 souhu.com
18500000003 1 sina.com
18500000004 0 sina.com
18500000005 1 souhu.com
18500000006 1 github.com
18500000007 1 sina.com
18500000008 0 github.com

输出:属性为1的被过滤出来
18500000003 1 sina.com
18500000005 1 souhu.com
18500000006 1 github.com
18500000007 1 sina.com

排序(Sorting)

  • 问题定义:在数据文件中包含大量的记录,每条记录中包含了某个实体的若干属性,目标问题是在将记录按照一定规则排序后输出;
  • 具体问题描述:输入为三列,手机号、上行流量、下行流量,要求计算每个手机号的总流量并按照从小到大的顺序输出;
  • 解决方案:在map中将上下行流量相加,得出总流量,以<手机号,总流量>形式输出;reduce中将每个手机号按照总流量从小到大的顺序排序后输出;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package wordcountTest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

import com.sun.org.apache.bcel.internal.generic.NEW;
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;
import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils.Collections;

public class WordCount {

public static class Map extends
Mapper<Object, Text, LongWritable, LongWritable> {

private final static IntWritable one = new IntWritable(1);
private LongWritable phoneNumber = new LongWritable();
private LongWritable totalFlow = new LongWritable(); //记录总流量

public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] array = line.split(" ");
totalFlow = new LongWritable(Long.parseLong(array[1])
+ Long.parseLong(array[2])); //上下行流量相加
if (array.length == 3) {
context.write(new LongWritable(Long.parseLong(array[0])), totalFlow);
} else {
return;
}
}
}

public static class Reduce extends
Reducer<LongWritable, LongWritable, LongWritable, Object> {

private IntWritable result = new IntWritable();

public void reduce(LongWritable key, Iterable<LongWritable> values,
Context context) throws IOException, InterruptedException {

List <Long> totalUserFlow = new ArrayList<Long>();
for (LongWritable val : values) {
totalUserFlow.add(val.get());
}

Object[] arrObjects =totalUserFlow.toArray();
Arrays.sort(arrObjects);

for(int j=0; j<arrObjects.length; j++){
context.write(key, arrObjects[j]);
}
}
}


// Driver program
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args)
.getRemainingArgs(); // get all args
System.out.println(System.getenv("HADOOP_HOME"));
if (otherArgs.length != 2) {
System.err.println("Usage: WordCount <in> <out>");
System.exit(2);
}

// create a job with name "wordcount"
Job job = new Job(conf, "userflow");
job.setJarByClass(WordCount.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);

// uncomment the following line to add the Combiner
// job.setCombinerClass(Reduce.class);
// set output key type

job.setMapOutputKeyClass(LongWritable.class);
job.setMapOutputValueClass(LongWritable.class);

job.setOutputKeyClass(LongWritable.class);
job.setOutputValueClass(Object.class);

// set reduce number
job.setNumReduceTasks(1);
// set the HDFS path of the input data
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
// set the HDFS path for the output
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
// Wait till job completion
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出:
1
2
3
4
5
6
7
8
9
10
11
输入:手机号、上行流量、下行流量,以空格分割
15700000000 3333 2222
13900000000 3333 4444
15700000000 1111 2222
13900000000 2222 1111

输出:按照总流量大小排序输出
13900000000 3333
13900000000 7777
15700000000 3333
15700000000 5555

去重计数(Distinct Counting)

  • 问题定义:在数据文件中包含大量的记录,每条记录中包含了某个实体的若干属性,目标问题是在计算某几个属性组合后去掉相同重复组合后,其中某一属性的统计值;
  • 具体问题的描述:输入为两列,手机号、访问网址,要求统计每个网址都有几种手机号访问;
  • 解决方案:map中将网址作为key、手机号作为value,发送给reduce;计数、去重的工作都由reduce完成;去重的工作由HashSet完成;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package wordcount_test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {

public static class TokenizerMapper
extends Mapper<Object, Text, Text, LongWritable>{


private LongWritable phoneNum = new LongWritable();
private Text webPage = new Text();

public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
String line = value.toString();
String[] array = line.split(" ");
if(array.length==2){
phoneNum = new LongWritable(Long.parseLong(array[0]));
webPage = new Text(array[1]);
context.write(webPage, phoneNum);
}else{
return;
}
}
}

public static class IntSumReducer
extends Reducer<Text,LongWritable, Text, IntWritable> {


private IntWritable result = new IntWritable();

public void reduce(Text key, Iterable<LongWritable> values,
Context context
) throws IOException, InterruptedException {

int sum = 0;
Set <String> phoneNumSet = new HashSet<String>();
for(LongWritable val : values){
phoneNumSet.add(val.toString());
}
for(String s : phoneNumSet){
sum++;
}
result.set(sum);
context.write(key, result);
}
}

public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
// job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);

job.setNumReduceTasks(1);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LongWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出:
1
2
3
4
5
6
7
8
9
10
11
输入:手机号、访问网址,用空格分割
15700000000 qq.com
13900000000 qq.com
13900000000 sina.com
15700000000 qq.com
15700000000 sina.com
12900000000 sina.com

输出:每个网址对应的手机号种类数量
qq.com 2
sina.com 3

相关计数(Cross-Correlation)

  • 问题定义:输入若干数组,每个数组是由若干实体构成,目标问题是计算数组中实体以一定条件要求成对出现的次数或概率;
  • 具体问题描述:输入数据是2列,手机号、访问网址,现在需要统计每个手机号访问每个网址的次数;
  • 解决方案:Stripes方法–map中将手机号作为key、访问网址和计数值1作为value,reduce中进行统计;Pairs方法–map中将手机号和访问网址作为key、计数值1作为value,reduce中进行统计;
  • 程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
Stripes方法:

package wordcount_test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {

public static class TokenizerMapper
extends Mapper<Object, Text, LongWritable, Text>{

private LongWritable phoneNum = new LongWritable();
private Text webPage = new Text();

public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
String line = value.toString();
String[] array = line.split(" ");
if(array.length==2){
phoneNum = new LongWritable(Long.parseLong(array[0]));
webPage = new Text(array[1]);
context.write(phoneNum, webPage);
}else{
return;
}
}
}

public static class IntSumReducer
extends Reducer<LongWritable,Text, String, IntWritable> {

private IntWritable result = new IntWritable();

public void reduce(LongWritable key, Iterable<Text> values,
Context context
) throws IOException, InterruptedException {

int sum = 0;
Text webText;
String webString;
List <String> webList = new ArrayList<String>();
Set <String> webSet = new HashSet<String>();

//将values迭代器内容放入list中,方便之后重复访问
for(Text val : values){
webList.add(val.toString());
}
//唯一的网址存入webSet
for (String val : webList) {
webSet.add(val);
}
//分别统计当前手机号(key)的每个访问网址的次数并输出
for(String s: webSet){
for (String web : webList) {
if(s.equals(web)){
sum++;
}
}
result.set(sum);
context.write(key.toString()+" "+s, result);
sum =0;
}
}
}

public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
// job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);

job.setNumReduceTasks(1);
job.setMapOutputKeyClass(LongWritable.class);
job.setMapOutputValueClass(Text.class);
job.setOutputKeyClass(String.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
pairs方法:

package wordcount_test;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {

public static class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable>{


private final static IntWritable one = new IntWritable(1);
private String phoneNum = new String();
private String webPage = new String();

public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
String line = value.toString();
String[] array = line.split(" ");
if(array.length==2){
phoneNum = array[0];
webPage = array[1];
context.write(new Text(phoneNum+" "+webPage), one);
}else{
return;
}
}
}

public static class IntSumReducer
extends Reducer<Text, IntWritable, Text, IntWritable> {


private IntWritable result = new IntWritable();

public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {

int sum = 0;
for (IntWritable val : values) {
sum ++;
}
result.set(sum);
context.write(key, result);
}
}

public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
// job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);

job.setNumReduceTasks(1);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
  • 示例输入输出:
1
2
3
4
5
6
7
8
9
10
11
12
输入:手机号、网址,中间用空格分割
15700000000 qq.com
13900000000 qq.com
13900000000 sina.com
15700000000 qq.com
15700000000 sina.com

输出:手机号、访问网址和对应的次数统计结果
13900000000 qq.com 1
13900000000 sina.com 1
15700000000 qq.com 2
15700000000 sina.com 1

微信公众号制作技巧

发表于 2015-05-06 | 分类于 WeChat |

引言

  • 微信公众号是当今最受欢迎的宣传和推广平台,它凭借微信这个大舞台,让许多个人和小微企业有了宣传自己和推广自己的有力武器;
  • 要想让别人更多的关注和分享抑或是收藏自己的微信公众号,就必须做得漂亮,本文介绍一些我在做公众号的经验和总结;

微信公众号的使用方法

  • 注册用户:https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN;
  • 自定义菜单中可以添加手机下方的菜单项,方便用户查看;
  • 用户管理中可以给用户分组,发布的时候可以更有针对性投放广告;
  • 素材管理中可以添加素材,添加后可选择是否发布;
  • 统计菜单中可以查看分类的统计数据,方便决策;
  • 公众号设置中可以获取二维码;

微信公众号编辑方法

  • 登陆微信公众号;
  • 点击素材管理>新建“单图文消息”;
  • 在里面编辑相应的标题、作者、封面、摘要、正文,正文内容可以用下面推荐的编辑器、素材库编辑;
  • 编辑完成后,单击“预览”输入自己的微信号可预览;
  • 预览检查没有问题后,点击“保存并发布”,扫描二维码向管理员申请发布;
  • 在自定义菜单中加入自己做的这个图文消息的菜单,方便用户查看;
  • 整理“图片库”中的图片,将自己用到的图片放在相应的分组中;

推荐素材库

  • 仅仅用微信公众号自带的素材无法制作出漂亮的页面,下面提供几个素材库;
  • 素材库使用方法:注册账号后即可使用,可以通过添加素材、复制、粘贴的方法将素材放入微信公众号的素材中;
  • 135编辑器
  • 秀米编辑器
  • 微信编辑器
  • 美化二维码工具
  • logo的制作:AAA Logo软件;

几个技巧

  • 添加gif动图:从网上下载所需gif动图,保存为…gif格式,微信公众号编辑时正常上传这张图片即可,普通用户也支持gif图片的显示;
  • 添加指纹识别:从网上下载指纹图样、从公众号中的“公众号设置”菜单下载合适大小的二维码图样,用美图秀秀的拼图功能无缝拼接两张图片,将制作好的图片放入公众号编辑器中即可;

微信公众号样式参考

  • 《Hadoop大数据处理》免费教程系列6-MapReduce原理
  • SQL on Hadoop性能对比-Hive、Spark SQL、Impala

Gitlab基本原理

发表于 2015-04-26 | 分类于 git |

引言

  • gitlab是常用的版本管理工具。
  • 相对于github来说,gitlab不收费,而且基本具有github的全部功能,因此特别适合小微企业和学校实验室等用作版本管理工具。
  • gitlab具有比svn强大多的功能,在代码控制、版本控制、任务进度控制、甚至工资绩效等方面发挥着重大作用。
  • gitlab中有很多容易混淆的过程和名字,本文解释了gitlab的运行过程,可作为初学者的参考。

本地和远端

  • 特别要注意的是,本地和远端remote是相对的概念。一般来说将PC作为本地,服务器作为远端。事实上,普通的PC也可以作为远端,本地和远端的地位是平行的,不存在远端地位较高只说。
  • 远端的名字默认为origin,所以push的时候一般用命令git push origin master,即将本地的内容拉取到名字为origin的远端的master分支上去。如果远端名称不叫origin,则命令要相应变化。

本地和远端的交互动作

  • 下图是网上找到的一张图,清晰地描绘了git本地和远端的交互过程:

git

  • fetch:将本地已有的工程从远端拉取到本地repository;
  • clone:将本地没有的工程从远端拉取到本地repository;
  • pull:直接将本地没有的工程从远端拉取到本地工作目录;
  • checkout:将本地repository存储的某个版本作为工作目录;
  • add:将本地的更改添加到索引中;
  • commit:将索引中的修改一次性写入本地repository;
  • push:将repository中的更改拉取到远端,实现版本非本地端备份;
  • checkout和commit是相反动作,clone/fetch和push是相反动作;

版本管理动作

  • 上图中没有的一些动作,对于版本管理也必不可少,下面将介绍。
  • branch:分支,分支的作用是方便大家同时开发不同的模块。
  • merge:将两个分支合并,比如自己的分支和master合并。
  • 哈希值:gitlab会自动为每个版本计算哈希值,用哈希值来识别版本。

gitlab常用命令

  • git clone url:clone到本地;
  • git add .:添加改动到index;
  • git commit -a -m "...":添加改动到本地库;
  • git push origin master:这个命令上面已经说过,将本地某个版本push到远端,实现版本备份;

gitlab中经典的开发场景解析

  • 最常见的开发场景就是用netbeans中代码管理,下面是流程。
  • 第一步:在远端建立自己的分支;
  • 第二步:将这个分支clone到本地(netbeans中team菜单项>git>clone),注意要将master和自己的分支都clone下来;
  • 第三步:选择netbeans菜单项team>git>repository browser,右键单击remote里面的自己的分支,选择checkout revision,就将本地工作目录设定为了自己的分支;
  • 第四步:按照要求修改代码;
  • 第五步:修改完成代码后,右键单击工程,选择git>commit,然后提交commit信息,将改动添加到本地库;
  • 第六步:commit后,右键单击工程,选择git>remote>push,然后将本地的修改push到远端备份;
  • 第七步:在远端提交merge request,等待上级领导的审阅和合并通过。到此为止,一个完整的有gitlab版本控制参与的开发流程就结束了!

HDFS详解

发表于 2015-04-25 | 分类于 hadoop |

引言

  • HDFS是Hadoop中的重要组件,是一种重要而文件存储机制。
  • HDFS可以同时保证文件读写的效率和安全性,不怕宕机和断电。
  • HDFS内部的机制相当复杂,本文会详细讲解这些机制的作用。

HDFS特点

  • 流量大,流速并不快;
  • 适合读写大块的文件,不适合读写大量小文件;

HDFS的组件构成

  • client:如果用PC连接集群,则PC就是client,用户直接操纵client;
  • namenode:HDFS管理者,保存各个文件块(默认64MB)的位置信息,保存各个datanode的状态信息,保存机架感知的信息,和datanode心跳通信;
  • secondnamenode:namenode的备份;
  • datanode:存储具体的文件块,每个文件块要在不同的机器上一共存储三份,保证文件的安全性;

HDFS读文件的流程

  • client要读文件;
  • client问namenode这个文件的几个块都放在那个datanode上面(一个文件块备有三份分别存在不同的datanode上面),优先选择离client近的数据;
  • client获知datanode信息后,去相应的机器上读取文件块;
  • client依次读取这个文件的所有文件块,组成完整的文件;
  • 中间如果读取某个块出错,会从这个块的备份块所在datanode继续读取;

HDFS写文件流程

  • client要写文件;
  • client问namenode这个文件的几个块都要写在哪个datanode上面(HDFS的备份机制要求同一个文件块要写在三个datanode上面三份,其中两个datanode处于同一机架,另一个和他们不处于同一机架);
  • client获知datanode信息后,去相应的机器上写文件块(client先把数据全部写在datanode1上面,datanode1将数据某一块写在datanode2,datanode2将数据某一块写在datanode3,以此类推,最后这个大文件的每一块都在相应的机器上);
  • 这样做(而不是namenode同时向三台datanode写文件)的原因:client向datanode写的网络IO有限,但是datanode之间的网络IO非常宽,有利于并行;
  • 如果写入过程出错,将文件写入这个datanode的节点会通知namenode写入失败,请求namenode重新分配datanode写入;
  • 三个节点全部写入完毕后,分别ACK通知namenode写入完毕;

HDFS容错机制

  • 应对datanode可能坏掉:datanode和namenode间的心跳机制;
  • 应对网络可能断掉:ACK握手协议等;
  • 应对文件/硬盘可能坏掉:对文件块进行校验码或者纠错码验证,如MD5;
  • 应对namenode坏掉:用secondnamenode定期镜像备份;
  • 应对突然宕机造成的内存中的数据丢失:下面的FsImage+内存元数据+EditLog经典架构,这种架构既不只用内存(效率高但是安全性差),也不只用磁盘(效率低但是安全性好),一般是读/写数据直接面向内存,内存达到一定限值后写入磁盘,同时保证效率和安全性;

hdfs

HDFS机架感知

  • namenode保存机架树信息;
  • 一个文件块存了三份,读文件时给client优先推荐离得近的那一份;
  • 写文件时,每一个文件块都选取和client在一个机架上面的一台机器、和client相邻机架的两台机器,一共写三份;
  • 这样做的好处:既保证了读写效率(一个机架上的网络IO比机架间的网络IO高),而且又在别的机架备份保证了安全性;

Web技术名词解释

发表于 2015-04-15 | 分类于 Web |

引言

  • web开发框架中有很多技术,这些技术支撑着web开发向前发展。我们今天看到的各种各样的漂亮的网页也是在这些技术下得以实现的。本文梳理了web开发中的常用技术,作为参考。

浏览器端

基础语言框架

  • html:页面显示语言,浏览器识别并解析;
  • javascript:前端开发用的轻量级脚本语言,用于页面的控制和内容获取;
  • E4X:javascript的扩展,向JavaScript添加了对 XML 的直接支持,是正式的javascript标准之一;

页面渲染技术

  • css(Cascading Style Sheets):层叠样式表技术,用于新框架下的页面渲染;
  • less:一种动态的css语言,在浏览器端解析;
  • sass:一种动态的css语言,在服务器端解析;
  • bootstrap(twitter支持):由less编写的一套页面渲染框架(样式库),栅格系统和屏幕适配性是它的优势所在;

Javascript常用IDE

  • Sublime Text ;
  • WebStorm ;
  • netbeans;
  • Brackets ;
  • Atom;

常用Javascript辅助工具

  • grunt:自动完成js代码合并压缩等,支持自动化测试;
  • node.js:充当浏览器的js解析器的功能,还可以外加很多插件,方便调试;
  • bower:基于node.js,依赖管理工具,自动下载、管理、监测package的依赖关系;
  • HTTP-server:基于node.js,轻量级的服务器,用于通过http协议访问本机文件夹;
  • KARMA/Jasmine:基于node.js,前端代码单元测试工具(相当于java的JUnit),KARMA提供测试工具驱动,Jasmine提供测试语法;
  • protractor:针对angularjs的自动化测试工具,不能用于其他js库;
  • selenium:Web应用程序测试的工具,自动完成用户操作以便测试网站,可用于轮播系统的制作;

前端网页开发框架

框架名称 描述 优缺点 依赖
angularjs 免费,google支持;辅助JavaScript的网页开发框架;和ExtJS处于竞争地位; 灵活性高但是完备性中等;UI控件库不如ExtJS全面,但是可定制性强;不直接支持移动端; 由于没有全面的UI控件,一般用angularUI或者bootstrap进行页面布局和渲染;
ExtJS 收费;辅助JavaScript的网页开发框架;和angularjs处于竞争地位; 完备性高但是灵活性中等;拥有非常全面的UI控件库,浏览器间可移植性极强,但是用户定制性稍差;直接支持移动端;
jQueryUI 免费; UI控件较为混乱;可定制性强;直接支持移动端;
NEJ(Nice Easy Javascript) 网易前端开发框架;辅助JavaScript的网页开发框架;

前端框架支持库

支持库名称 描述 优缺点
jQuery 纯粹的JavaScript代码库,目的是简化DOM操作 和prototype做的事情相同,方法不同,jQuery火了,prototype没有火起来;
prototype 纯粹的JavaScript代码库,目的是简化DOM操作 没有jQuery火
YUI(Yahoo! UI Library) 开放源代码的 JavaScript 函数库;

异步请求技术

ajax(asynchronous javascript and xml):此技术破除了旧的web框架“只能请求一次”的限制,使得程序员可以指定浏览器什么时候发出请求、发出什么请求、请求内容是什么,ajax已经封装在前端框架中(诸如angularjs等框架),无需人为添加库;

服务器端

基础语言

  • php:开源脚本语言,用于小型web开发,服务器端语言,比java的学习成本和复杂度低得多,但是功能有限,比较简陋;
  • java:后台可以用java去写;
  • jsp(Java Server Pages):动态网页技术标准,用于大型web开发,语言是在html中插入java;
  • servlet:是一种面向底层的jsp;
  • asp:动态服务器页面(Active Server Page),是一种后台编程脚本语言,可以与数据库交互;
  • python:知乎和豆瓣在python写后台;
  • .net:是Microsoft面向XML Web服务的平台,支持的原生语言是c#,.net目前只能运行在windows上;

SSH框架

  • Struts2(view):对浏览器请求处理的一整套框架;
  • Spring(control):提供了依赖注入的思想,提供了大量模板类,配合和支持Struts2完成对用户请求的页面响应;
  • Hibernate(model):面向java环境的对象/关系数据库映射工具,封装了和数据库的连接部分;
  • 这种老框架的劣势:框架太多、太复杂;

RESTful框架

  • RESTful(用java实现的话叫做JAX-RS):
    • 基于HTTP协议的(get put post等方法),一种分层的目录型的设计风格(任何资源可被唯一的URI访问到),支持JSON和XML格式的数据,在javaEE中具体表现为REST.java文件;
    • 它之所以叫做RESTful指的是server端不用承担全部的页面内容传递和逻辑的全部任务,显示逻辑交由client端,剩下的(rest)交给server端;
  • ORM(Object Relational Mapping,用java实现的话叫做JPA):
    • 一种在面向对象语言和数据库等数据源之间传递数据的桥梁,作用是数据映射,在javaEE中具体表现为entity.java文件;
  • JAX-RS(Java API for RESTful Web Services):RESTful设计风格在java中的具体表现,在java中具体表现为REST.java文件;
  • JPA(java persistence API):ORM标准在java中的具体表现,在java中具体表现为entity.java文件;

服务器软件

  • apache:跨平台,安全性高;
  • tomcat:典型的jsp容器,由apache开源组织开发,免费的开放源代码的Web应用服务器,属于轻量级应用服务器,适合中小企业;
  • jetty:典型的jsp容器,由eclipse基金会开发维护;
  • glassfish:一款强健的商业兼容应用服务器,达到产品级质量,可免费用于开发、部署和重新分发;

数据格式

数据格式名称 描述
JOSN 一种数据格式,新版框架下浏览器请求数据时,服务器会返回这种格式的数据,可用javascript解析,可用ajax技术传输;
XML 一种数据格式,比JOSN重,面向数据传输;

设计思想

设计思想 描述
DOM框架 是一种页面元素控制的设计思想,他的树形结构便于获取页面元素;
MVC框架 是一种前端到后端的设计思想,model、view、controller三者分离,要什么请求什么,更加灵活,易于扩展和测试;
同源策略 网景公司(Netscape)提出的著名的安全策略,禁止服务器跨域读取数据;

组织团体

  • W3C(World Wide Web Consortium):万维网联盟的缩写,是对网络标准制定的一个非赢利组织,致力在万维网发展方向上达成共识;
1…891011
Eric Chang

Eric Chang

www.yinshuisiyuan.net

101 日志
15 分类
51 标签
github weibo linkedin mail
  • 阮一峰
  • Azure
  • Python
  • Nodejs
© 2015 - 2020 Eric Chang
由 Hexo 强力驱动
主题 - NexT.Pisces


知识共享许可协议本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可。