首页 文章 精选 留言 我的

精选列表

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

MapReduce 学习(一)

首先我们先来欣赏一下MapReduce的执行过程吧,如下图,自己看,不解释了。 Map 和 Reduce 的处理都是基于Key/Value来进行的,在Map中对文件的每一行进行处理,有两个输入参数,KeyInput,ValueInput,然后有两个输出,KeyOut,ValueOut,在Map执行之后有个Combiner,负责把多个Map传过来的Key相同的Value生成一个Iterable接口的集合,也可以自己指定一个Combiner,可以提高性能,要慎用,经过Combiner处理之后,就把处理过的内容传给Reduce,这是个一对一的过程,Reduce的输出也是KeyOut,ValueOut,最后是输出到文件,这里还有一个Partitiner,实现它可以把输出分别写到多个文件上,否则将会把所有reduce产生的文件输出到一个文件当中,好,我们来看一下下面这个图,大家就可以有一个更直观的感受了! 好啦,理论就讲到这里。

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

EmbossMaskFilter BlurMaskFilter 学习

MaskFilter类可以为Paint分配边缘效果。对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter: BlurMaskFilter 指定了一个模糊的样式和半径来处理Paint的边缘,让目标部分模糊不清。 EmbossMaskFilter 指定了光源的方向和环境光强度来添加浮雕效果,是让目标部分有凹凸的水印图案。 要应用一个MaskFilter,可以使用setMaskFilter方法,并传递给它一个MaskFilter对象 BlurMaskFilter.Blur 4个值: INNER:在目标内显示面具,从边缘向目标内到离边缘radius宽的地方显示,radius为初始化BlurMaskFilter的一个值 NORMAL:在目标内外显示面具,从边缘向目标内和目标外到离边缘radius宽的地方,向外显示面具时都会同时显示在目标边缘处获得的颜色。 OUTER:在目标外显示面具,从边缘向目标外到离边缘radius宽的地方,并且该部分会显示出从目标边缘获得的颜色,不显示目标 SOLID:在目标外显示面具,从边缘向目标外到离边缘radius宽的地方,并且该部分会显示出从目标边缘获得的颜色,显示目标 BlurMaskFilter: package com.soyoungboy.customview.widget; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.view.View; import com.example.customview.R; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public class BlurMaskFilterView extends View { private Paint mPaint; private Bitmap mBitmap; private Bitmap mAlphaBmp; public BlurMaskFilterView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public BlurMaskFilterView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public BlurMaskFilterView(Context context) { super(context); init(); } /** * 进行初始化操作 */ private void init() { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); } mPaint = new Paint(); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); mAlphaBmp = mBitmap.extractAlpha(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 宽度 int width = 200; // 高度 int height = width * mAlphaBmp.getHeight() / mAlphaBmp.getWidth(); // 绘制红色阴影,首先将画笔设置为红色 mPaint.setColor(Color.RED); // 就是添加内外发光效果 mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL)); // 绘制阴影在矩形框里面 左上角坐标 10,10,右下角坐标width,height canvas.drawBitmap(mAlphaBmp, null, new Rect(10, 10, width, height), mPaint); // 绘制原图像 mPaint.setMaskFilter(null); canvas.drawBitmap(mBitmap, null, new Rect(0, 0, width, height), mPaint); } } 效果图: mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.INNER)); 效果图: mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.OUTER)); 效果图: mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID)); 使用EmbossMaskFilter 修改onDraw()里面方法: @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 宽度 int width = 200; // 高度 int height = width * mAlphaBmp.getHeight() / mAlphaBmp.getWidth(); //设置光源的方向 float[] direction = new float[] { 1, 1, -1 }; // 设置环境光亮度 float light = 1f; // 选择要应用的反射等级 float specular = 6; // 向mask应用一定级别的模糊 float blur = 3.5f; EmbossMaskFilter emboss = new EmbossMaskFilter(direction, light, specular, blur); mPaint.setMaskFilter(emboss); mPaint.setColor(Color.BLUE); // 绘制阴影在矩形框里面 左上角坐标 10,10,右下角坐标width,height canvas.drawBitmap(mAlphaBmp, null, new Rect(10, 10, width, height), mPaint); } 效果图:

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

Apache Drill学习

简介 Apache Drill is a low latency distributed query engine for large-scale datasets, including structured and semi-structured/nested data. 官网:http://drill.apache.org/ Apache Drill的用途:Drill是SQL查询引擎,可以构建在几乎所有的NoSQL数据库或文件系统(如:Hive, HDFS, mongo db, Amazon S3等)上,用来加速查询,比如,我们所熟知的Hive,用于在hdfs进行类SQL查询,但是利用Hive的速度比较慢,因此可以利用Drill一类的查询引擎加速查询,用于分布式大数据的实时查询等场景。 架构 drill 通过 Storage plugin interface 即插件的形式实现在不同的数据源上构建查询引擎。 安装,分为嵌入模式与分布模式。 这里介绍linux下嵌入模式的安装: 嵌入模式无需做相关配置,较简便,首先要安装JDK 7; 进入到待安装目录,打开shell; 下载安装包,运行以下命令中其中一条: wget http://getdrill.org/drill/download/apache-drill-1.1.0.tar.gz 或curl -o apache-drill-1.1.0.tar.gz http://getdrill.org/drill/download/apache-drill-1.1.0.tar.gz 下载文件到待安装目录后(或下载后移动至安装目录); 解压缩安装包,执行命令tar -xvzf <.tar.gz file name> 解压缩后,进入目录,此处解压过后的目录为apache-drill-1.1.0,执行命令 bin/drill,如图 此时可能会报错,显示内存不足,这里可以在子目录conf中修改drill-env.sh文件中的默认内存分配设置即可,默认是4G,对于一般家用机器,必然会报错。 即启动嵌入模式drill。 上图中最后一行表明drill已启动,可以开始执行查询,最后一行命令提示符的含义为,0表示连接数,jdbc表示连接类型,zk=local表示使用ZooKeeper本地节点。 退出命令 !quit drill web访问接口,在浏览器输入http://<IP address or host name>:8047 即可,访问效果如图: 以上我们安装好了drill工具,但是并未将其与我们的特定数据源关联,以下我们进行相关配置,使其可以对具体数据执行查询。 1. 内存配置,如上,修改,在drill-env.sh中修改参数 XX:MaxDirectMemorySize 即可。 2. 配置多用户设置 3. 配置用户权限与角色 4. 。。。待续 连接数据源 dril连接数据源,通过存储插件形式,这样增加了灵活性,对于不同的数据源,通过插件实现多数据源的兼容,drill可以连接数据库,文件,分布式文件系统,hive metastore等。 可以通过三种方式指定配置存储插件配置: (1) 通过查询中的FROM语句 (2) 在查询语句前使用USE命令 (3) 在启动drill时指定 Web配置方式 可以在http://<IP address>:8047/storage 查看和配置存储插件,存在以下选项, cp连接jar file dfs连接本地文件系统或任何分布式文件系统,如hadoop,amazon s3等 hbase连接Hbase hive连接hive metastore mongo连接MongoDB 点击进入update选项,可以配置数据格式等选项, 可以输入存储插件名字创建新的存储插件,如图 dfs插件配置示例,如图 drill插件可配置属性介绍 Attribute Example Values Required Description "type" "file" "hbase" "hive" "mongo" yes A valid storage plugin type name. "enabled" true false yes State of the storage plugin. "connection" "classpath:///" "file:///" "mongodb://localhost:27017/" "hdfs://" implementation-dependent The type of distributed file system, such as HDFS, Amazon S3, or files in your file system, and an address/path name. "workspaces" null "logs" no One or more unique workspace names. If a workspace name is used more than once, only the last definition is effective. "workspaces". . . "location" "location": "/Users/johndoe/mydata" "location": "/tmp" no Full path to a directory on the file system. "workspaces". . . "writable" true false no One or more unique workspace names. If defined more than once, the last workspace name overrides the others. "workspaces". . . "defaultInputFormat" null "parquet" "csv" "json" no Format for reading data, regardless of extension. Default = "parquet" "formats" "psv" "csv" "tsv" "parquet" "json" "avro" "maprdb" * yes One or more valid file formats for reading. Drill implicitly detects formats of some files based on extension or bits of data in the file; others require configuration. "formats" . . . "type" "text" "parquet" "json" "maprdb" * yes Format type. You can define two formats, csv and psv, as type "Text", but having different delimiters. formats . . . "extensions" ["csv"] format-dependent File name extensions that Drill can read. "formats" . . . "delimiter" "\t" "," format-dependent Sequence of one or more characters that serve as a record separator in a delimited text file, such as CSV. Use a 4-digit hex code syntax \uXXXX for a non-printable delimiter. "formats" . . . "quote" """ no A single character that starts/ends a value in a delimited text file. "formats" . . . "escape" "`" no A single character that escapes a quotation mark inside a value. "formats" . . . "comment" "#" no The line decoration that starts a comment line in the delimited text file. "formats" . . . "skipFirstLine" true no To include or omit the header when reading a delimited text file. Set to true to avoid reading headers as data. 也可以通过Drill Rest API进行插件配置,使用POST方式传递名字和配置两个属性,例如 curl -X POST -/json" -d '{"name":"myplugin", "config": {"type": "file", "enabled": false, "connection": "file:///", "workspaces": { "root": { "location": "/", "writable": false, "defaultInputFormat": null}}, "formats": null}}' https://localhost:8047/storage/myplugin.json 上面命令创建一个名为myplugin的插件,用于查询本地文件系统根目录的未知文件类型。 介绍连接hive的配置,首先确保hive metastore服务启动,hive.metastore.uris:hive --service metastore 进入Drill Web接口,进入Store选项卡,http://<IP address>:8047/storage 点击hive旁的update选项,进行配置,如图 进入配置界面,在默认内容上添加如下,

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

storm组件学习

场景 伴随着信息科技日新月异的发展,信息呈现出爆发式的膨胀,人们获取信息的途径也更加多样、更加便捷,同时对于信息的时效性要求也越来越高。举个搜索场景中的例子,当一个卖家发布了一条宝贝信息时,他希望的当然是这个宝贝马上就可以被卖家搜索出来、点击、购买啦,相反,如果这个宝贝要等到第二天或者更久才可以被搜出来,估计这个大哥就要骂娘了。再举一个推荐的例子,如果用户昨天在淘宝上买了一双袜子,今天想买一副泳镜去游泳,但是却发现系统在不遗余力地给他推荐袜子、鞋子,根本对他今天寻找泳镜的行为视而不见,估计这哥们心里就会想推荐你妹呀。其实稍微了解点背景知识的码农们都知道,这是因为后台系统做的是每天一次的全量处理,而且大多是在夜深人静之时做的,那么你今天白天做的事情当然要明天才能反映出来啦。 实现一个实时计算系统 全量数据处理使用的大多是鼎鼎大名的hadoop或者hive,作为一个批处理系统,hadoop以其吞吐量大、自动容错等优点,在海量数据处理上得到了广泛的使用。但是,hadoop不擅长实时计算,因为它天然就是为批处理而生的,这也是业界一致的共识。否则最近这两年也不会有s4,storm,puma这些实时计算系统如雨后春笋般冒出来啦。先抛开s4,storm,puma这些系统不谈,我们首先来看一下,如果让我们自己设计一个实时计算系统,我们要解决哪些问题。 低延迟。都说了是实时计算系统了,延迟是一定要低的。 高性能。性能不高就是浪费机器,浪费机器是要受批评的哦。 分布式。系统都是为应用场景而生的,如果你的应用场景、你的数据和计算单机就能搞定,那么不用考虑这些复杂的问题了。我们所说的是单机搞不定的情况。 可扩展。伴随着业务的发展,我们的数据量、计算量可能会越来越大,所以希望这个系统是可扩展的。 容错。这是分布式系统中通用问题。一个节点挂了不能影响我的应用。 好,如果仅仅需要解决这5个问题,可能会有无数种方案,而且各有千秋,随便举一种方案,使用消息队列+分布在各个机器上的工作进程就ok啦。我们再继续往下看。 容易在上面开发应用程序。亲,你设计的系统需要应用程序开发人员考虑各个处理组件的分布、消息的传递吗?如果是,那有点麻烦啊,开发人员可能会用不好,也不会想去用。 消息不丢失。用户发布的一个宝贝消息不能在实时处理的时候给丢了,对吧?更严格一点,如果是一个精确数据统计的应用,那么它处理的消息要不多不少才行。这个要求有点高哦。 消息严格有序。有些消息之间是有强相关性的,比如同一个宝贝的更新和删除操作消息,如果处理时搞乱顺序完全是不一样的效果了。 不知道大家对这些问题是否都有了自己的答案,下面让我们带着这些问题,一起来看一看storm的解决方案吧。 Storm是什么 如果只用一句话来描述storm的话,可能会是这样:分布式实时计算系统。按照storm作者的说法,storm对于实时计算的意义类似于hadoop对于批处理的意义。我们都知道,根据google mapreduce来实现的hadoop为我们提供了map, reduce原语,使我们的批处理程序变得非常地简单和优美。同样,storm也为实时计算提供了一些简单优美的原语。我们会在第三节中详细介绍。 我们来看一下storm的适用场景。 流数据处理。Storm可以用来处理源源不断流进来的消息,处理之后将结果写入到某个存储中去。 分布式rpc。由于storm的处理组件是分布式的,而且处理延迟极低,所以可以作为一个通用的分布式rpc框架来使用。当然,其实我们的搜索引擎本身也是一个分布式rpc系统。 说了半天,好像都是很玄乎的东西,下面我们开始具体讲解storm的基本概念和它内部的一些实现原理吧。 Storm的基本概念 首先我们通过一个 storm 和hadoop的对比来了解storm中的基本概念。 Hadoop Storm 系统角色 JobTracker Nimbus TaskTracker Supervisor Child Worker 应用名称 Job Topology 组件接口 Mapper/Reducer Spout/Bolt 表3-1 接下来我们再来具体看一下这些概念。 Nimbus:负责资源分配和任务调度。 Supervisor:负责接受nimbus分配的任务,启动和停止属于自己管理的worker进程。 Worker:运行具体处理组件逻辑的进程。 Task:worker中每一个spout/bolt的线程称为一个task. 在storm0.8之后,task不再与物理线程对应,同一个spout/bolt的task可能会共享一个物理线程,该线程称为executor。 下面这个图描述了以上几个角色之间的关系。 图3-1 Topology:storm中运行的一个实时应用程序,因为各个组件间的消息流动形成逻辑上的一个拓扑结构。 Spout:在一个topology中产生源数据流的组件。通常情况下spout会从外部数据源中读取数据,然后转换为topology内部的源数据。Spout是一个主动的角色,其接口中有个nextTuple()函数,storm框架会不停地调用此函数,用户只要在其中生成源数据即可。 Bolt:在一个topology中接受数据然后执行处理的组件。Bolt可以执行过滤、函数操作、合并、写数据库等任何操作。Bolt是一个被动的角色,其接口中有个execute(Tuple input)函数,在接受到消息后会调用此函数,用户可以在其中执行自己想要的操作。 Tuple:一次消息传递的基本单元。本来应该是一个key-value的map,但是由于各个组件间传递的tuple的字段名称已经事先定义好,所以tuple中只要按序填入各个value就行了,所以就是一个value list. Stream:源源不断传递的tuple就组成了stream。 10. stream grouping:即消息的partition方法。Storm中提供若干种实用的grouping方式,包括shuffle, fields hash, all, global, none, direct和localOrShuffle等 相比于s4, puma等其他实时计算系统,storm最大的亮点在于其记录级容错和能够保证消息精确处理的事务功能。下面就重点来看一下这两个亮点的实现原理。 Storm记录级容错的基本原理 首先来看一下什么叫做记录级容错?storm允许用户在spout中发射一个新的源tuple时为其指定一个message id, 这个message id可以是任意的object对象。多个源tuple可以共用一个message id,表示这多个源 tuple对用户来说是同一个消息单元。storm中记录级容错的意思是说,storm会告知用户每一个消息单元是否在指定时间内被完全处理了。那什么叫做完全处理呢,就是该message id绑定的源tuple及由该源tuple后续生成的tuple经过了topology中每一个应该到达的bolt的处理。举个例子。在图4-1中,在spout由message 1绑定的tuple1和tuple2经过了bolt1和bolt2的处理生成两个新的tuple,并最终都流向了bolt3。当这个过程完成处理完时,称message 1被完全处理了。 图4-1 在storm的topology中有一个系统级组件,叫做acker。这个acker的任务就是追踪从spout中流出来的每一个message id绑定的若干tuple的处理路径,如果在用户设置的最大超时时间内这些tuple没有被完全处理,那么acker就会告知spout该消息处理失败了,相反则会告知spout该消息处理成功了。在刚才的描述中,我们提到了”记录tuple的处理路径”,如果曾经尝试过这么做的同学可以仔细地思考一下这件事的复杂程度。但是storm中却是使用了一种非常巧妙的方法做到了。在说明这个方法之前,我们来复习一个数学定理。 A xor A = 0. A xor B…xor B xor A = 0,其中每一个操作数出现且仅出现两次。 storm中使用的巧妙方法就是基于这个定理。具体过程是这样的:在spout中系统会为用户指定的message id生成一个对应的64位整数,作为一个root id。root id会传递给acker及后续的bolt作为该消息单元的唯一标识。同时无论是spout还是bolt每次新生成一个tuple的时候,都会赋予该tuple一个64位的整数的id。Spout发射完某个message id对应的源tuple之后,会告知acker自己发射的root id及生成的那些源tuple的id。而bolt呢,每次接受到一个输入tuple处理完之后,也会告知acker自己处理的输入tuple的id及新生成的那些tuple的id。Acker只需要对这些id做一个简单的异或运算,就能判断出该root id对应的消息单元是否处理完成了。下面通过一个图示来说明这个过程。 图4-1 spout中绑定message 1生成了两个源tuple,id分别是0010和1011. 图4-2 bolt1处理tuple 0010时生成了一个新的tuple,id为0110. 图4-3 bolt2处理tuple 1011时生成了一个新的tuple,id为0111. 图4-4 bolt3中接收到tuple 0110和tuple 0111,没有生成新的tuple. 可能有些细心的同学会发现,容错过程存在一个可能出错的地方,那就是,如果生成的tuple id并不是完全各异的,acker可能会在消息单元完全处理完成之前就错误的计算为0。这个错误在理论上的确是存在的,但是在实际中其概率是极低极低的,完全可以忽略。 Storm的事务拓扑 事务拓扑(transactional topology)是storm0.7引入的特性,在最近发布的0.8版本中已经被封装为Trident,提供了更加便利和直观的接口。因为篇幅所限,在此对事务拓扑做一个简单的介绍。 事务拓扑的目的是为了满足对消息处理有着极其严格要求的场景,例如实时计算某个用户的成交笔数,要求结果完全精确,不能多也不能少。Storm的事务拓扑是完全基于它底层的spout/bolt/acker原语实现的,通过一层巧妙的封装得出一个优雅的实现。个人觉得这也是storm最大的魅力之一。 事务拓扑简单来说就是将消息分为一个个的批(batch),同一批内的消息以及批与批之间的消息可以并行处理,另一方面,用户可以设置某些bolt为committer,storm可以保证committer的finishBatch()操作是按严格不降序的顺序执行的。用户可以利用这个特性通过简单的编程技巧实现消息处理的精确。 Storm在淘宝 由于storm的内核是clojure编写的(不过大部分的拓展工作都是java编写的),为我们理解它的实现带来了一定的困难,好在大部分情况下storm都比较稳定,当然我们也在尽力熟悉clojure的世界。我们在使用storm时通常都是选择java语言开发应用程序。 在淘宝,storm被广泛用来进行实时日志处理,出现在实时统计、实时风控、实时推荐等场景中。一般来说,我们从类kafka的metaQ或者基于hbase的timetunnel中读取实时日志消息,经过一系列处理,最终将处理结果写入到一个分布式存储中,提供给应用程序访问。我们每天的实时消息量从几百万到几十亿不等,数据总量达到TB级。对于我们来说,storm往往会配合分布式存储服务一起使用。在我们正在进行的个性化搜索实时分析项目中,就使用了timetunnel + hbase + storm + ups的架构,每天处理几十亿的用户日志信息,从用户行为发生到完成分析延迟在秒级。 Storm的未来 Storm0.7系列的版本已经在各大公司得到了广泛使用,最近发布的0.8版本中引入了State,使得其从一个纯计算框架演变成了一个包含存储和计算的实时计算新利器,还有刚才提到的Trident,提供更加友好的接口,同时可定制scheduler的特性也为其针对不同的应用场景做优化提供了更便利的手段,也有人已经在基于storm的实时ql(query language)上迈出了脚本。在服务化方面,storm一直在朝着融入mesos框架的方向努力。同时,storm也在实现细节上不断地优化,使用很多优秀的开源产品,包括kryo, Disruptor, curator等等。可以想象,当storm发展到1.0版本时,一定是一款无比杰出的产品,让我们拭目以待,当然,最好还是参与到其中去吧,同学们。 参考文献 [1]storm官方wiki及code.https://github.com/nathanmarz/storm

资源下载

更多资源
Oracle

Oracle

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Apache Tomcat

Apache Tomcat

Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。

Eclipse

Eclipse

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。

JDK

JDK

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。