海量数据挖掘之中移动流量运营系统

---------------------------------------------------------------------------------------------------------------
[ 版权申明:本文系作者原创,转载请注明出处]
文章出处: http://blog.csdn.net/sdksdk0/article/details/51691862
作者:朱培   ID:sdksdk0

---------------------------------------------------------------------------------------------------------------

因为整个项目工程师非常庞大的,一方面由于整个开发流量非常繁琐,不可能通过一篇文章就可以说得清楚的,另一方面由于保密性,所以这里只分享其中的部分内容。首先会从整体架构等说起,通过本文的学习主要是进一步了解海量数据挖掘的框架流程,对数据采集流程、内容识别、知识库的建立以及行为轨迹增强有初步的了解,学会简单的url清洗以及能够开发出简单的分类MapReducer程序。当然,如果部分内容看不懂也没关系,毕竟这需要经验的积累,不要太急于求成,可以先查看我的其他文章!


一、项目背景介绍


1.1 项目背景

对于运营商来说,使用海量数据挖掘对客户移动互联网行为进行采集,分析,发现用户关注的内容,为开展营销提供号码支持。当然,也不局限于这些功能。例如一个用户在用手机看小说,那么肯定有一个url的网址啦,用户所有访问的网址,ip,时间戳,上下行流量,基站,网络模式,手机型号等一大串信息都会被记录下来并在运营商的的云端进行存储,这个数据量是非常非常大的。这个时候我们可以通过抓取到用户访问过的url和总流量,然后通过爬虫去分析用户浏览的这个网页是怎么样的一个网页,通过内容识别机制来找出这个网页的内容,例如一个用户在看的是新闻url,然后我们通过爬虫发现其访问的是新浪新闻,然后内容识别发现其经常访问关于娱乐新闻,明星八卦等,(基于流量和这类新闻的浏览次数来判读是否经常访问),那么这个时候我们就可以给其推送一些娱乐周边新闻等,只要用户点击去浏览了那么肯定会产生流量啊,那么运营商的营销的目的不就达成了么,哈哈哈!

该项目投产之后的收效为:

l用户响应率有三倍提升
本次营销相关激励措施和前期开展的WAP PUSH营销相同;
对比以往的群发响应率1%-3%,本次群发响应率效果明显,达到5.80%-10.21%,有近乎3倍的提升效果。
l访问用户活跃度高
用户后有继续点击其他内容的行为,最高占比达到91.4%
产生二次点击行为的用户数的占比高,反映贴合用户需求的内容对用户的吸引力,用户粘性越高。


1.2 项目概况


在每个省单独一套系统,分为3个集群:数据采集集群(6-10个节点),行为轨迹增强处理集群(20-25节点),ETL、统计分析集群(35节点)

节点就是:PC服务器,放到机柜中,配置(4颗12核cpu,64G或128G内存,磁盘1T*8/12)

数据量,每天2T左右(10亿行以上),时间维度,地域维度。最长分析3个月的。每天增量不断增长。
项目组成员:
  研发团队:数据采集(3-4人),行为轨迹增强(10人左右),ETL(20人左右,需要写web程序)
  实施团队:部署环境,2-3个实施人员带上20多个开发人员
  运维团队:
  销售团队等

1.3 系统架构图




二、数据采集系统架构

既然前面说到了要抓取url的网址,那么我们如何来获得这些用户的数据呢!当然,普通人肯定是得不到运营商的数据啦,因为这些数据都是保密的,那么我要说的是运营商如何得到用户数据呢!

项目所处理的数据
硬件设备(网关,基站等)
其他系统(运营系统等)

业务日志:
HTTP日志/WAP日志/MMS日志/CONN日志/DNS日志



从移动运营商的核心网关中把需要的数据发送到ftp服务器上,然后我们这边就会提供ftp的客户端去采集ftp服务器的数据,然后处理之后过来进行分析。




三、内容识别模块

把url经过爬虫然后到识别系统,分析出网站名,主题,类别,(作者)等
将分类体系导入到数据库中,url json封装的内容信息。
大量的日志不断的产生,然后通过行为轨迹增强,通过一个mapreduce,
如果这个数据匹配到了,则将原始行+内容分析结果信息(从知识库来的数据)导出到增强日志。如果匹配不到的数据就输出到一个待爬清单中。


识别系统:自然语言处理SVM(实时识别),人工识别(人工一条条的去识别),模板识别(一个网页的内容的位置一般不会变,用xpath来定位到我们所需要查找的节点)

相信学过xml的应该都会使用xpath了,如果不会的话,可以查阅我这篇文章:http://blog.csdn.net/sdksdk0/article/details/51555090


在这个项目中庸xpath来做这个模板匹配:例如

对于一个网页的html页面来说,我们可以这样来匹配其标题,例如我们打开搜狐的html,我们可以看到他的这个网页标题是<title></title>的,所以我们对于这类网站就可以用xpath来定位这个title在哪里,然后去获取这title节点中内容


<site>
souhu.com
<site>
	<property>
		<name>movie_name</name>
		<xpath>/path/.../</xpath>
	</property>

</site>
</site>
当然了,使用xpath和xml去做这种模板匹配有一定的局限性,适用于一个结构非常清晰的网页,例如视频、小说、音乐等,对于那种奇奇怪怪的网友就不适用了。

所以总的来说,对于内容识别要采用多种方式去做,不要局限于一种,不同类型的网站最好有不同的解决方案。

我们使用自然语言处理来进行分析的时候还有问题就是,一个网页的内容太多了,svm分析有时候不能完全的识别到我们想要的内容,就像一条新闻,本来这个新闻的主标题才是中国网页的主要内容,而使用自然语言处理系统的话它可能会把新闻下面的广告读成了这个网页的主要内容了,所以这样的话就会有误差了。当然咯,自然语言分析还是很有用,那么为了更精确的识别照顾好网页的内容怎么办呢。好吧,那当然是最传统的人工读取了,由可爱的实习生们把这些网页一条条的浏览,然后记录这个网页的主要内容!(好吧,不要惊讶微笑,移动就是这么干的)。然后读取大概10万个网页,这样的话就形成了一个规则库,这个就比自然语言处理和模板匹配的结果更加精确了。


四、知识库url挑选

两个知识库,一个规则库(人工分析的),还有一个实例库(自动分析系统)。
先把url进行规则分析,如果有则输出,没有没有则放到实例库,如果实例库也没有了,就放到待爬清单中。
先拿1T的样本数据,然后网址按流量汇总排序出来,总流量的前80%,总条数10万条。
因为只要挑选出来就可以了,不需要实时在运行的,所以只要一个job就可以了。


这里我们主要拿到一个url和总流量来进行分析和处理,其他更为复杂的情况这里就不分享了哦。

我们首先可以在eclipse总新建一个jav工程,导入各种hadoop/lib下面的jar包,或者直接新建一个mapRedecer工程也可以。

新建一个bean类:记得要继承一个Comparable接口。

package cn.tf.kpi;

public class FlowBean implements Comparable<FlowBean>{

	private String url;
	private long upflow;
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public long getUpflow() {
		return upflow;
	}
	public void setUpflow(long upflow) {
		this.upflow = upflow;
	}
	public FlowBean(String url, long upflow) {
		super();
		this.url = url;
		this.upflow = upflow;
	}
	public FlowBean() {
		super();
	}
	@Override
	public int compareTo(FlowBean o) {
		return (int) (o.getUpflow() - this.upflow) ;
	}
	@Override
	public String toString() {
		return "FlowBean [url=" + url + ", upflow=" + upflow + "]";
	}	
}
然后写主方法:

其实这里和我之前写的那个用户流量分析系统有很多类似的地方。

package cn.tf.kpi;

import java.io.IOException;
import java.util.TreeSet;

import org.apache.commons.lang.StringUtils;
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;

import cn.tf.kpi.TopURL.TopURLMapper.TopURlReducer;

public class TopURL {

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

		private Text k = new Text();
		private LongWritable v = new LongWritable();

		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {

			String line = value.toString();
			String[] fields = StringUtils.split(line, "\t");
			try {
				String url = fields[26];

				long upFlow = Long.parseLong(fields[30]);

				k.set(url);
				v.set(upFlow);

				context.write(k, v);
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

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

			private Text k = new Text();
			private LongWritable v = new LongWritable();

			TreeSet<FlowBean> urls = new TreeSet<FlowBean>();

			//全局流量和
			long globalFlowSum  =0;
			
			
			@Override
			protected void reduce(Text key, Iterable<LongWritable> values,
					Context context) throws IOException, InterruptedException {

				long count = 0;
				for (LongWritable v : values) {
					count += v.get();
				}
				
				globalFlowSum +=count;
				FlowBean bean = new FlowBean(key.toString(), count);
				urls.add(bean);
			}
			
			@Override
			protected void cleanup(Context context) throws IOException, InterruptedException {
					
				long tempSum=0;
				for(FlowBean bean:urls){
					//取前80%的
					if(tempSum/globalFlowSum<0.8){
					k.set(bean.getUrl());
					v.set(bean.getUpflow());
					context.write(k,v);
					
					tempSum+=bean.getUpflow();
					}else{
						return;
					}
				}
			}
		}
	}

	
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		Configuration conf = new Configuration();
		Job job = Job.getInstance();

		job.setJarByClass(TopURL.class);

		// 指定本job使用的mapper类
		job.setMapperClass(TopURLMapper.class);
		// 指定本job使用的reducer类
		job.setReducerClass(TopURlReducer.class);

		// 指定mapper输出的kv的数据类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(LongWritable.class);

		// 指定reducer输出的kv数据类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(LongWritable.class);

		// 指定本job要处理的文件所在的路径
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		// 指定本job输出的结果文件放在哪个路径
		FileOutputFormat.setOutputPath(job, new Path(args[1]));

		// 将本job向hadoop集群提交执行
		boolean res = job.waitForCompletion(true);

		System.exit(res ? 0 : 1);

	}

}

然后把这个工程打成一个jar包,命名为top.jar。存放到你指定的一个位置就可以了,我存放的位置是在/home/admin1/hadoop/lx/top.jar

现在启动hadoop集群服务,
把采集到的数据上传到hdfs的/topflow/data目录下,下载地址在文末贴出。(源数据下载地址:http://download.csdn.net/detail/sdksdk0/9551559)。把这个log.1文件上传你的hdfs目录中,这个log.1主要是几十万条采集到的用户流量的数据。

bin/hadoop fs -mkdir -p /topflow/data
bin/hadoop fs -put ../lx/log.1  /topflow/data

把jar包放到hadoop中执行:

bin/hadoop jar ../lx/top.jar  cn.tf.kpi.TopURL  /topflow/data   /topflow/output  

执行之后会见过系统的处理就可以选出url了。

内容如下:就是一个url网址+总流量大小,并且按照降序排列,所以我们只要拿到这个数据源的总流量最大的前80%的用户数据就可以了,然后就可以进行下一步的操作了。编译好的这个文件会存放在你的hdfs目录中,去查看一下就可以了。



然后你需要先准备一个mysql数据库,用于存放清洗好的数据,也就是我们把刚才得到的数据,是存放在hdfs的/topflow/output目录下的那个文件,把这个文件存到mysql数据库中,作为一个知识库。

在mysql数据中新建一个test数据库,然后建一个名字叫rule的表:

create database test;
use test;
create table rule(
  url  varchar(1024),
  info varchar(20) default 'complited'
)

然后需要导入数据,这里我直接使用sqoop来把hdfs中的数据导入到mysql中去,先去下载一个sqoop,

sqoop是一个用来在hadoop体系和关系型数据库之间进行数据互导的工具
----实质就是将导入导出命令转换成mapreduce程序来实现。sqoop安装:安装在一台节点上就可以了。

首先下载好sqoop之后解压进入conf目录下,配置hadoop的路径,然后把mysql的驱动jar包复制一份放到sqoop的lib目录中。

在sqoop的conf目录下,修改sqoop-env.sh

export HADOOP_COMMON_HOME=/home/admin1/hadoop/hadoop-2.5.2
export HADOOP_MAPRED_HOME=/home/admin1/hadoop/hadoop-2.5.2

然后启动:进入sqoop的目录下,运行下面这个程序

bin/sqoop export --connect jdbc:mysql://ubuntu2:3306/test --username hive --password  a \
--table rule \
--export-dir /topflow/output \
--columns url \
--input-fields-terminated-by '\t'

然后就会把数据全部存入到mysql中,经过清洗之后,这里大概是6070条数据,在实际生产中的数据量可不仅仅只有这么一点点。

select *from rule;查看这个表里面的内容。


到这里,我们这个url知识库就建立好了,接下来就可以愉快的进行后续操作了。


五、用户行为轨迹增强


用户行为增强就是把原始的数据源来和这个知识库做匹配,如果有则把原来的数据+分析后的数据作为一个增强的模块,如果没有在这个知识库中匹配到,则放到待爬数据中。接下来演示的就是把原始数据(也就是前面提到的log.1)的数据与我们刚才存放到mysql中的六千多条数据进行匹配,若有,则输出到增强日至,若无则存放到待爬数据。

这个部分的内容其实是比较简单的,就是流程比较复杂一点。接下来继续在那个eclipse中新建3个类。

先把mysql的驱动包导入我们新建的这个工程,并build path一下。

这里写一个连接数据库的泪,因为我们要和数据库中的知识库做对比嘛,这是一个基础的jdbc连接类,这种很简单的我相信大街上随便一个人都会写的哈大笑。这里就不再重复啰嗦啦!

package cn.tf.kpi;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

import java.util.HashMap;



public class DBLoader {

	public static void dbLoader(HashMap<String, String> ruleMap) {

		Connection conn = null;

		Statement st = null;

		ResultSet res = null;

		try {

			Class.forName("com.mysql.jdbc.Driver");

			conn = DriverManager.getConnection("jdbc:mysql://ubuntu2:3306/test", "hive", "a");

			st = conn.createStatement();

			res = st.executeQuery("select url,info from rule");

			while (res.next()) {

				ruleMap.put(res.getString(1), res.getString(2));

			}

		} catch (Exception e) {

			e.printStackTrace();

		} finally {

			try{

				if(res!=null){

					res.close();

				}

				if(st!=null){

					st.close();

				}

				if(conn!=null){

					conn.close();

				}
			}catch(Exception e){

				e.printStackTrace();

			}

		}

	}

	public static void main(String[] args) {

		DBLoader db = new DBLoader();

		HashMap<String, String> map = new HashMap<String,String>();

		db.dbLoader(map);

		System.out.println(map.size());

	}

}

接下来就是一个增强日志类:

package cn.tf.kpi;



import java.io.IOException;



import org.apache.hadoop.fs.FSDataOutputStream;

import org.apache.hadoop.fs.FileSystem;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IOUtils;

import org.apache.hadoop.io.NullWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.RecordWriter;

import org.apache.hadoop.mapreduce.TaskAttemptContext;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;



public class LogEnhanceOutputFormat extends FileOutputFormat<Text, NullWritable>{



	@Override

	public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext context) throws IOException, InterruptedException {

		

		FileSystem	fs = FileSystem.get(context.getConfiguration());

		FSDataOutputStream tocrawlOut = fs.create(new Path("hdfs://ubuntu2:9000/topflow/tocrawl/url.list"));

		FSDataOutputStream enhancedOut = fs.create(new Path("hdfs://ubuntu2:9000/topflow/enhanced/enhanced.log"));

		

		

		return new LogEnhanceRecordWriter(tocrawlOut,enhancedOut);

	}


	public static class LogEnhanceRecordWriter extends RecordWriter<Text, NullWritable>{


		private FSDataOutputStream tocrawlOut;

		private FSDataOutputStream enhancedOut;

		

		public LogEnhanceRecordWriter(FSDataOutputStream tocrawlOut, FSDataOutputStream enhancedOut) {

			this.tocrawlOut = tocrawlOut;

			this.enhancedOut = enhancedOut;

		}



		@Override

		public void write(Text key, NullWritable value) throws IOException, InterruptedException {


			if(key.toString().contains("tocrawl")){

				//写入待爬清单目录(hdfs://)

				tocrawlOut.write(key.toString().getBytes());

			}else{

				//写入增强日志目录(hdfs://)

				enhancedOut.write(key.toString().getBytes());		

			}
		}



		@Override

		public void close(TaskAttemptContext context) throws IOException, InterruptedException {

			IOUtils.closeStream(enhancedOut);

			IOUtils.closeStream(tocrawlOut);

			

		}	

		

	}

}

最后把最重要的一个类写完就可以了;这里只要写一个map就可以了

package cn.tf.kpi;



import java.io.IOException;

import java.util.HashMap;



import org.apache.commons.lang.StringUtils;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.LongWritable;

import org.apache.hadoop.io.NullWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;



public class LogEnhance {



	public static class LogEnhanceMapper extends Mapper<LongWritable, Text, Text, NullWritable> {

		private HashMap<String, String> contentMap = new HashMap<String, String>();

		@Override

		protected void setup(Context context) throws IOException, InterruptedException {

			// 加载整个内容识别知识库到内存中

			DBLoader.dbLoader(contentMap);

		}

		@Override

		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {



			String line = value.toString();

			String[] fields = StringUtils.split(line, "\t");



			try {

				// 抽取url字段,去匹配规则库获取url页面的内容识别信息
				String url = fields[26];

				String contentResult = contentMap.get(url);


				String result = null;

				// 如果知识库中没有这条url的内容识别信息,就只输出url字段到待爬清单

				if (StringUtils.isBlank(contentResult)) {

					result = url + "\t" + "tocrawl" + "\n";

				} else {

					// 在原始日志内容后面追加内容识别结果信息作为增强之后的输出

					result = line + "\t" + contentResult +"\n";

				}


				context.write(new Text(result), NullWritable.get());

			} catch (Exception e) {

				context.getCounter("malformed", "line").increment(1);

			}

		}

	}



	public static void main(String[] args) throws Exception {

		Configuration conf = new Configuration();

		Job job = Job.getInstance();



		job.setJarByClass(LogEnhance.class);



		// 指定本job使用的mapper类

		job.setMapperClass(LogEnhanceMapper.class);



		// 指定mapper输出的kv的数据类型

		job.setMapOutputKeyClass(Text.class);

		job.setMapOutputValueClass(NullWritable.class);



		// 指定reducer输出的kv数据类型

		job.setOutputKeyClass(Text.class);

		job.setOutputValueClass(NullWritable.class);



		// 指定采用自定义的outputformat

		job.setOutputFormatClass(LogEnhanceOutputFormat.class);



		// 指定本job要处理的文件所在的路径

		FileInputFormat.setInputPaths(job, new Path(args[0]));

		// 虽然自定义outputformat中已有输出目录,但是这里还是要设置一个目录用来输出_SUCCESS文件

		FileOutputFormat.setOutputPath(job, new Path(args[1]));



		// 将本job向hadoop集群提交执行

		boolean res = job.waitForCompletion(true);



		System.exit(res ? 0 : 1);

	}



}
写完之后发现这三个类内容好简单,有木有!

继续把这个工程达成jar包,命名为top1.jar,然后放到hadoop下面去运行:


bin/hadoop jar top.jar  cn.tf.kpi.LogEnhance  /topflow/data  /topflow/output1


然后去查看一个数据就可以了。


也可以到浏览器中查看:


到这里,就在于分享完毕了,按照我分享的这个流量一步步做,我估计要一两天的时间才可以完全做完这个部分!其实总的来说就是过程非常繁琐,不过也正符合我们的实际工作,要知道,我们实际工作中,远超乎这些繁琐流程,中间还会报各种奇奇怪怪的错,有非常多的细节要处理,如果没有耐心,估计都会疯掉,哈哈!

欢迎关注,欢迎在评论区留言!



数据源下载地址:http://download.csdn.net/detail/sdksdk0/9551559


  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据下的数据分析平台架构 ⼤数据下的数据分析平台架构 转载: 随着互联⽹、移动互联⽹和物联⽹的发展,谁也⽆法否认,我们已经切实地迎来了⼀个海量数据的时代,数据调查公司IDC预计2011年的数 据总量将达到1.8万亿GB,对这些海量数据的分析已经成为⼀个⾮常重要且紧迫的需求。 作为⼀家互联⽹数据分析公司,我们在海量数据的分析领域那真是被"逼上梁⼭"。多年来在严苛的业务需求和数据压⼒下,我们⼏乎尝试了 所有可能的⼤数据分析⽅法,最终落地于Hadoop平台之上。 Hadoop在可伸缩性、健壮性、计算性能和成本上具有⽆可替代的优势,事实上已成为当前互联⽹企业主流的⼤数据分析平台。本⽂主要介 绍⼀种基于Hadoop平台的多维分析和数据挖掘平台架构。 ⼤数据分析的分类 Hadoop平台对业务的针对性较强,为了让你明确它是否符合你的业务,现粗略地从⼏个⾓度将⼤数据分析的业务需求分类,针对不同的具 体需求,应采⽤不同的数据分析架构。 按照数据分析的实时性,分为实时数据分析和离线数据分析两种。 实时数据分析⼀般⽤于⾦融、移动和互联⽹B2C等产品,往往要求在数秒内返回上亿⾏数据的分析,从⽽达到不影响⽤户体验的⽬的。要满 ⾜这样的需求,可以采⽤精⼼设计的传统关系型数据库组成并⾏处理集群,或者采⽤⼀些内存计算平台,或者采⽤HDD的架构,这些⽆疑都 需要⽐较⾼的软硬件成本。⽬前⽐较新的海量数据实时分析⼯具有EMC的Greenplum、SAP的HANA等。 对于⼤多数反馈时间要求不是那么严苛的应⽤,⽐如离线统计分析、机器学习、搜索引擎的反向索引计算、推荐引擎的计算等,应采⽤离线 分析的⽅式,通过数据采集⼯具将⽇志数据导⼊专⽤的分析平台。但⾯对海量数据,传统的ETL⼯具往往彻底失效,主要原因是数据格式转 换的开销太⼤,在性能上⽆法满⾜海量数据的采集需求。互联⽹企业的海量数据采集⼯具,有Facebook开源的Scribe、LinkedIn开源的 Kafka、淘宝开源的Timetunnel、Hadoop的Chukwa等,均可以满⾜每秒数百MB的⽇志数据采集和传输需求,并将这些数据上载到Hadoop 中央系统上。 按照⼤数据数据量,分为内存级别、BI级别、海量级别三种。 这⾥的内存级别指的是数据量不超过集群的内存最⼤值。不要⼩看今天内存的容量,Facebook缓存在内存的Memcached中的数据⾼达 320TB,⽽⽬前的PC服务器,内存也可以超过百GB。因此可以采⽤⼀些内存数据库,将热点数据常驻内存之中,从⽽取得⾮常快速的分析 能⼒,⾮常适合实时分析业务。图1是⼀种实际可⾏的MongoDB分析架构。 图1 ⽤于实时分析的MongoDB架构 MongoDB⼤集群⽬前存在⼀些稳定性问题,会发⽣周期性的写堵塞和主从同步失效,但仍不失为⼀种潜⼒⼗⾜的可以⽤于⾼速数据分析的 NoSQL。 此外,⽬前⼤多数服务⼚商都已经推出了带4GB以上SSD的解决⽅案,利⽤内存+SSD,也可以轻易达到内存分析的性能。随着SSD的发 展,内存数据分析必然能得到更加⼴泛的 应⽤。 BI级别指的是那些对于内存来说太⼤的数据量,但⼀般可以将其放⼊传统的BI产品和专门设计的BI数据之中进⾏分析。⽬前主流的BI产品 都有⽀持TB级以上的数据分析⽅案。种类繁多,就不具体列举了。 海量级别指的是对于数据库和BI产品已经完全失效或者成本过⾼的数据量。海量数据级别的优秀企业级产品也有很多,但基于软硬件的成本 原因,⽬前⼤多数互联⽹企业采⽤Hadoop的HDFS分布式⽂件系统来存储数据,并使⽤MapReduce进⾏分析。本⽂稍后将主要介绍 Hadoop上基于MapReduce的⼀个多维数据分析平台。 数据分析的算法复杂度 根据不同的业务需求,数据分析的算法也差异巨⼤,⽽数据分析的算法复杂度和架构是紧密关联的。举个例⼦,Redis是⼀个性能⾮常⾼的 内存Key-Value NoSQL,它⽀持List和Set、SortedSet等简单集合,如果你的数据分析需求简单地通过排序,链表就可以解决,同时总的数 据量不⼤于内存(准确地说是内存加上虚拟内存再除以2),那么⽆疑使⽤Redis会达到⾮常惊⼈的分析性能。 还有很多易并⾏问题(Embarrassingly Parallel),计算可以分解成完全独⽴的部分,或者很简单地就能改造出分布式算法,⽐如⼤规模脸 部识别、图形渲染等,这样的问题⾃然是使⽤并⾏处理集群⽐较适合。 ⽽⼤多数统计分析,机器学习问题可以⽤MapReduce算法改写。MapReduce⽬前最擅长的计算领域有流量统计、推荐引擎、趋势分析、⽤ 户⾏为分析、数据挖掘分类器、分布式索引等。 图2 RCFile的⾏列混合存 ⾯对⼤数据OLAP分析的⼀些问题 OLAP分析需要进⾏⼤量的数据分组和表间关联,⽽这

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值