首页 文章 精选 留言 我的

精选列表

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

重新学习Java语言(一)--Java语言的标识符和关键字

一、标识符 1、什么是标识符? Java语言中,对于变量,常量,函数,语句块也有名字,我们统统称之为Java标识符. 标识符是用来给类、对象、方法、变量、接口和自定义数据类型命名的。 2、标识符的构成 标识符是没有长度限制的由Java字母和数字构成的序列,其中首字母必须是Java字母 "Java字母" 是作为参数调用Character.isJavaIdentifierStart(int)方法时返回true的字符 "Java字母或数字" 是作为参数调用 Character.isJavaIdentifierPart(int)方法时返回true的字符 "Java字母"包括大写和小写的ASCII拉丁字母A~Z ( \u0041 ~ \u005a )和 a~z (\u0061 ~ \u007a ),并且由于历史原因还包括下划线 (_ 或 \u005f) 和美元符号( $ 或 \u0024 )。$符号应该仅出现在机器生成的源代码中,或者用于另一种函件的情况,即访问遗留系统中已有的名字。 "Java数字"包括ASCII数字0~9(\u0030 ~ \u0039) 例子: package com.yy.test; /** * Created by anyang on 2018/1/4. */ public class Class_2018_01_04_01 { public static void 挖到(){ System.out.println("我是汉字"); } public static void Á(){ //注意:这是两个字符,是希腊字母A和一个无空格上提号 复制下来退格就能清楚的看到了(非空格标记) System.out.println("我是字母A和无空格间隙的上提号组合"); } public static void Á(){ System.out.println("我是希腊字母"); } public enum test{ 我是DJ, 我不是DJ, 我到底是不是DJ } public static void main(String[] args) { 挖到(); System.out.println(Character.isJavaIdentifierPart(97)); System.out.println("代码点值是: "+(int)'_'); } } 如上例,看似完全相同的 Á和 Á 却有着天壤之别。 3、 使用标识符应该注意 标识符的拼写不能与关键字、布尔字面常量、空字面常量或编译时发生的错误的拼写相同 两个标识符只有在拼写完全相同,即每个对应的Unicode字母或者数字都相同的时候才会被认为是相同的标识符。具有相同外观的标识符仍旧有可能是不同的。 二、关键字 1、关键字都有哪些 Java保留了50个关键字,他们都是由ASCII字母构成的字符序列,并且不能当做标识符使用,他们包括: abstract continue for new switch assert default if package synchronized boolean do goto private this break double implements protected throw byte else import public throws case enum instanceof return transient catch extends int short try char final interface static void class finally long strictfp volatile const float native super while 2、其他注意事项 尽管现在已经不再使用关键字const和goto了,但仍旧保留了。这使得当这些C++关键字在程序中使用不当时,Java编译器能够产生更有用的错误消息 尽管true和false看起来应该被当做关键字,但从技术上讲,他们仅仅只是布尔字面常量。与此类似null看起来也应该被当做关键字,但他也仅仅只是空字面常量。 三、关于Character.isJavaIdentifierPart(int) /** * Determines if the character (Unicode code point) may be part of a Java * identifier as other than the first character. * <p> * A character may be part of a Java identifier if any of the following * are true: * <ul> * <li> it is a letter 字母组合(单词) * <li> it is a currency symbol (such as {@code '$'}) 货币符号如:美元符号 * <li> it is a connecting punctuation character (such as {@code '_'}) 连接标点字符如:下划线 * <li> it is a digit 数字 * <li> it is a numeric letter (such as a Roman numeral character) 数字字母如:罗马数字等 * <li> it is a combining mark 结合字符(举例说明) * <li> it is a non-spacing mark 非空格标记(举例说明) * <li> {@link #isIdentifierIgnorable(int) * isIdentifierIgnorable(codePoint)} returns {@code true} for * the character * </ul> * * @param codePoint the character (Unicode code point) to be tested. * @return {@code true} if the character may be part of a * Java identifier; {@code false} otherwise. * @see Character#isIdentifierIgnorable(int) * @see Character#isJavaIdentifierStart(int) * @see Character#isLetterOrDigit(int) * @see Character#isUnicodeIdentifierPart(int) * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ public static boolean isJavaIdentifierPart(int codePoint) { return CharacterData.of(codePoint).isJavaIdentifierPart(codePoint); } package java.lang; abstract class CharacterData { abstract int getProperties(int ch); abstract int getType(int ch); abstract boolean isWhitespace(int ch); abstract boolean isMirrored(int ch); abstract boolean isJavaIdentifierStart(int ch); abstract boolean isJavaIdentifierPart(int ch); abstract boolean isUnicodeIdentifierStart(int ch); abstract boolean isUnicodeIdentifierPart(int ch); abstract boolean isIdentifierIgnorable(int ch); abstract int toLowerCase(int ch); abstract int toUpperCase(int ch); abstract int toTitleCase(int ch); abstract int digit(int ch, int radix); abstract int getNumericValue(int ch); abstract byte getDirectionality(int ch); //need to implement for JSR204 int toUpperCaseEx(int ch) { return toUpperCase(ch); } char[] toUpperCaseCharArray(int ch) { return null; } boolean isOtherLowercase(int ch) { return false; } boolean isOtherUppercase(int ch) { return false; } boolean isOtherAlphabetic(int ch) { return false; } boolean isIdeographic(int ch) { return false; } // Character <= 0xff (basic latin) is handled by internal fast-path // to avoid initializing large tables. // Note: performance of this "fast-path" code may be sub-optimal // in negative cases for some accessors due to complicated ranges. // Should revisit after optimization of table initialization. static final CharacterData of(int ch) { if (ch >>> 8 == 0) { // fast-path return CharacterDataLatin1.instance; } else { switch(ch >>> 16) { //plane 00-16 case(0): return CharacterData00.instance; case(1): return CharacterData01.instance; case(2): return CharacterData02.instance; case(14): return CharacterData0E.instance; case(15): // Private Use case(16): // Private Use return CharacterDataPrivateUse.instance; default: return CharacterDataUndefined.instance; } } } } //假设传参获得的实例是 CharacterData00 的 那么接下来就有 boolean isJavaIdentifierPart(int ch) { int props = getProperties(ch); return ((props & 0x00003000) != 0); } int getProperties(int ch) { char offset = (char)ch; int props = A[Y[X[offset>>5]|((offset>>1)&0xF)]|(offset&0x1)]; return props; } 参考资料:http://blog.csdn.net/mazhimazh/article/details/17708001 https://www.zhihu.com/question/20552606 https://baike.baidu.com/item/java%E6%A0%87%E8%AF%86%E7%AC%A6/11010420?fr=aladdin http://utf8.supfree.net/ 说明:本文大部分引用自《Java语言规范-基于Java SE 8》

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

【案例学习】两年打造150,000个容器,看PAYPAL的Docker实践之路

背景介绍 PayPal(贝宝)是美国eBay公司的全资子公司。1998年12月由Peter Thiel及Max Levchin建立,总部位于美国加利福尼亚州圣荷西市。PayPal致力于使金融服务大众化,让人们与企业能够参与到全球经济的繁荣发展中。PayPal开放式的数字支付平台让2.18亿用户相信他们能够以一种全新且强大的方式进行交易。为了实现这一目标,PayPal建立了全球性服务网络,确保用户可以随时、随地使用PayPal。如果PayPal的服务器出现故障,那么这种影响会波及到许多只依靠PayPal进行支付解决方案的小型企业客户。 案例简介 PayPal借助于Docker 企业版来帮助他们提高运营效率(构建、测试、部署周期的速度提高50%)。与此同时,他们通过Docker的动态部署能力和基础设施的独立性提高了其应用程序的可用性。为了提

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

《从零开始学Swift》学习笔记(Day 13)——数据类型之整型和浮点型

Swift提供8、16、32、64位形式的有符号及无符号整数。这些整数类型遵循C语言的命名规约,我归纳了Swift中的整型: 整型示例: 1 2 3 4 5 6 print( "UInt8range:\(UInt8.min)~\(UInt8.max)" ) print( "Int8range:\(Int8.min)~\(Int8.max)" ) print( "UIntrange:\(UInt.min)~\(UInt.max)" ) print( "UInt64range:\(UInt64.min)~\(UInt64.max)" ) print( "Int64range:\(Int64.min)~\(Int64.max)" ) print( "Intrange:\(Int.min)~\(Int.max)" ) 输出结果如下: UInt8 range: 0 ~ 255 Int8 range: -128 ~ 127 UInt range: 0 ~18446744073709551615 UInt64 range: 0 ~18446744073709551615 Int64 range:-9223372036854775808 ~ 9223372036854775807 Int range:-9223372036854775808 ~ 9223372036854775807 上述代码是通过整数的min和max属性计算各个类型的范围。 浮点型主要用来储存小数数值,也可以用来储存范围较大的整数。它分为浮点数(float)和双精度浮点数(double)两种,双精度浮点数所使用的内存空间比浮点数多,可表示的数值范围与精确度也比较大。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746103,如需转载请自行联系原作者

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

《从零开始学Swift》学习笔记(Day 14)——字符串的插入、删除和替换

对应可变字符串可以插入、删除和替换,String提供了几个方法可以帮助实现这些操作。这些方法如下: splice(_:atIndex:)。在索引位置插入字符串。 insert(_:atIndex:)。在索引位置插入字符。 removeAtIndex(_:)。在索引位置删除字符。 removeRange(_:)。删除指定范围内的字符串。 replaceRange(_:,with: String)。使用字符串或字符替换指定范围内的字符串。 代码: 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 varstr= "Swift" print( "原始字符串:\(str)" ) str.splice( "Objective-Cand" .characters,atIndex:str.startIndex) print( "插入字符串后:\(str)" ) str.insert( "." ,atIndex:str.endIndex) print( "插入.字符后:\(str)" ) str.removeAtIndex(str.endIndex.predecessor()) print( "删除.字符后:\(str)" ) varstartIndex=str.startIndex varendIndex=advance(startIndex, 9 ) varrange=startIndex...endIndex str.removeRange(range) print( "删除范围后:\(str)" ) startIndex=str.startIndex endIndex=advance(startIndex, 0 ) range=startIndex...endIndex str.replaceRange(range,with: "C++" ) print( "替换范围后:\(str)" ) 输出结果: 原始字符串:Swift 插入字符串后:Objective-C and Swift 插入.字符后:Objective-Cand Swift. 删除.字符后:Objective-Cand Swift 删除范围后:C and Swift 替换范围后:C++ and Swift 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746108,如需转载请自行联系原作者

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

《从零开始学Swift》学习笔记(Day 53)——do-try-catch错误处理模式

Swift 1.x的错误处理模式存在很多弊端,例如:为了在编程时候省事,给error参数传递一个nil,或者方法调用完成后不去判断error是否为nil,不进行错误处理。 1 2 3 4 5 6 letcontents=NSString(contentsOfFile:filePath, encoding:NSUTF8StringEncoding,error:nil) //error参数传递一个nil 或者 varerr:NSError? letcontents=NSString(contentsOfFile:filePath, encoding:NSUTF8StringEncoding,error:&err) 不好的编程习惯,由于Objective-C和Swift 1.x没有强制处理机制,因此一旦真的发生错误,程序就会发生崩溃。 同样的从文件中读取字符串示例,如果使用Swift2错误处理模式代码如下: 1 2 3 4 5 6 7 8 import Foundation do { //要做一些操作 letstr= try NSString(contentsOfFile:filePath, encoding:NSUTF8StringEncoding) //要尝试做的事情 } catch leterrasNSError{ //如果失败则进入catch代码块 err.description } do-try-catch这种错误模式与Java中异常处理机制非常类似,本意就是尝试(try)做一件事情,如果失败则捕获(catch)处理。 捕获错误 完整的do-try-catch错误处理模式的语法如下: 1 2 3 4 5 6 do { try 语句 成功处理语句组 } catch 匹配错误{ 错误处理语句组 } 在try语句中可以产生错误,当然也可能不会产生错误,如果有错误发生,catch就会处理错误。catch代码块可以有多个,错误由哪个catch代码块处理是由catch后面的错误匹配与否而定的。错误类型的多少就决定了catch可以有多少。我们先介绍一下错误类型。 错误类型 在Swift中错误类型必须遵从ErrorType协议,其次考虑到错误类型的匹配,它应该被设计成为枚举类型,枚举类型非常适合将一组相关值关联起来。 如果我们编写访问数据库表程序,实现对表数据插入、删除、修改和查询等操作,我们会需要类似如下代码的错误类型: 1 2 3 4 enum DAOError:ErrorType{ case NoData case PrimaryKeyNull } NoData表示没有数据情况,PrimaryKeyNull表示表的主键(Primary Key)为空情况。 那么我们就可以通过如下代码捕获错误。 1 2 3 4 5 6 7 do { //try访问数据表函数或方法 } catch DAOError.NoData{ print( "没有数据。" ) }catchDAOError.PrimaryKeyNull{ print( "主键为空。" ) } 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1748300,如需转载请自行联系原作者

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

Hadoop概念学习系列之常见的分布式文件系统(二十六)

常见的分布式文件系统有, GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS、FastDFS等。各自适用于不同的领域。它们都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务。 Google学术论文,这是众多分布式文件系统的起源 ================================== Google File System(大规模分散文件系统) MapReduce (大规模分散FrameWork) BigTable(大规模分散数据库) Chubby(分散锁服务) 一般你搜索Google_三大论文中文版(Bigtable、 GFS、 Google MapReduce)就有了。 做个中文版下载源:http://dl.iteye.com/topics/download/38db9a29-3e17-3dce-bc93-df9286081126 做个原版地址链接: http://labs.google.com/papers/gfs.html http://labs.google.com/papers/bigtable.html http://labs.google.com/papers/mapreduce.html GFS(Google File System) -------------------------------------- Google公司为了满足本公司需求而开发的基于Linux的专有分布式文件系统。。尽管Google公布了该系统的一些技术细节,但Google并没有将该系统的软件部分作为开源软件发布。 下面分布式文件系统都是类 GFS的产品。 HDFS -------------------------------------- Hadoop 实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。 Hadoop是Apache Lucene创始人Doug Cutting开发的使用广泛的文本搜索库。它起源于Apache Nutch,后者是一个开源的网络搜索引擎,本身也是Luene项目的一部分。Aapche Hadoop架构是MapReduce算法的一种开源应用,是Google开创其帝国的重要基石。 Ceph --------------------------------------- 是加州大学圣克鲁兹分校的Sage weil攻读博士时开发的分布式文件系统。并使用Ceph完成了他的论文。 说 ceph 性能最高,C++编写的代码,支持Fuse,并且没有单点故障依赖, 于是下载安装, 由于 ceph 使用 btrfs 文件系统, 而btrfs 文件系统需要 Linux 2.6.34 以上的内核才支持。 可是ceph太不成熟了,它基于的btrfs本身就不成熟,它的官方网站上也明确指出不要把ceph用在生产环境中。 Lustre --------------------------------------- Lustre是一个大规模的、安全可靠的,具备高可用性的集群文件系统,它是由SUN公司开发和维护的。 该项目主要的目的就是开发下一代的集群文件系统,可以支持超过10000个节点,数以PB的数据量存储系统。 目前Lustre已经运用在一些领域,例如HP SFS产品等。 适合存储小文件、图片的分布文件系统研究 ==================================== 用于图片等小文件大规模存储的分布式文件系统调研 架构高性能海量图片服务器的技术要素 nginx性能改进一例(图片全部存入google的leveldb) FastDFS分布文件系统 TFS(Taobao File System)安装方法 动态生成图片 Nginx + GraphicsMagick MogileFS --------------------------------------- 由memcahed的开发公司danga一款perl开发的产品,目前国内使用mogielFS的有图片托管网站yupoo等。 MogileFS是一套高效的文件自动备份组件,由Six Apart开发,广泛应用在包括LiveJournal等web2.0站点上。 MogileFS由3个部分组成: 第1个部分是server端,包括mogilefsd和mogstored两个程序。前者即是 mogilefsd的tracker,它将一些全局信息保存在数据库里,例如站点domain,class,host等。后者即是存储节点(store node),它其实是个HTTP Daemon,默认侦听在7500端口,接受客户端的文件备份请求。在安装完后,要运行mogadm工具将所有的store node注册到mogilefsd的数据库里,mogilefsd会对这些节点进行管理和监控。 第2个部分是utils(工具集),主要是MogileFS的一些管理工具,例如mogadm等。 第3个部分是客户端API,目前只有Perl API(MogileFS.pm)、PHP,用这个模块可以编写客户端程序,实现文件的备份管理功能。 mooseFS --------------------------------------- 持FUSE,相对比较轻量级,对master服务器有单点依赖,用perl编写,性能相对较差,国内用的人比较多 MooseFS与MogileFS的性能测试对比 FastDFS --------------------------------------- 是一款类似Google FS的开源分布式文件系统,是纯C语言开发的。 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合以文件为载体的在线服务,如相册网站、视频网站等等。 官方论坛 http://bbs.chinaunix.net/forum-240-1.html FastDfs google Code http://code.google.com/p/fastdfs/ 分布式文件系统FastDFS架构剖析 http://www.programmer.com.cn/4380/ TFS ------------------------------------- TFS(Taobao !FileSystem)是一个高可扩展、高可用、高性能、面向互联网服务的分布式文件系统,主要针对海量的非结构化数据,它构筑在普通的Linux机器 集群上,可为外部提供高可靠和高并发的存储访问。TFS为淘宝提供海量小文件存储,通常文件大小不超过1M,满足了淘宝对小文件存储的需求,被广泛地应用 在淘宝各项应用中。它采用了HA架构和平滑扩容,保证了整个文件系统的可用性和扩展性。同时扁平化的数据组织结构,可将文件名映射到文件的物理地址,简化 了文件的访问流程,一定程度上为TFS提供了良好的读写性能。 官网 : http://code.taobao.org/p/tfs/wiki/index/ GridFS文件系统 ------------------------------------- MongoDB是一种知名的NoSql数据库,GridFS是MongoDB的一个内置功能,它提供一组文件操作的API以利用MongoDB存储文件,GridFS的基本原理是将文件保存在两个Collection中,一个保存文件索引,一个保存文件内容,文件内容按一定大小分成若干块,每一块存在一个Document中,这种方法不仅提供了文件存储,还提供了对文件相关的一些附加属性(比如MD5值,文件名等等)的存储。文件在GridFS中会按4MB为单位进行分块存储。 MongoDB GridFS 数据读取效率 benchmark http://blog.nosqlfan.com/html/730.html nginx + gridfs 实现图片的分布式存储 安装(一年后出问题了) http://www.cnblogs.com/zhangmiao-chp/archive/2011/05/05/2038285.html 基于MongoDB GridFS的图片存储 http://liut.cc/blog/2010/12/about-imsto_my-first-open-source-project.html nginx+mongodb-gridfs+squid http://1008305.blog.51cto.com/998305/885340 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5683055.html,如需转载请自行联系原作者

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

Swift 2.0学习笔记(Day 6)——哎呀常量和变量都该什么时候用啊?

使用var还是let? 在我们开发过程中啊什么时候定义关键字为var,还是定义为let呢? 其实啊都能满足我们的需求,那我们到底应该如何选择? 例如:可以将圆周率π定义为let或var。 let π = 3.14159 var π = 3.14159 上面代码编译不会报错。但是从业务逻辑层面讲,π应该定义为常量(let)的,因为一方面常量(let)不能修改,另外在程序中使用常量(let)可以提高程序的可读性。 我觉得:原则上优先使用let,它有很多好处,可以防止程序运行过程中不必要的修改、提高程序的可读性。特别是引用数据类型声明时候经常采用let声明,虽然在业务层面上并不是一个常量,而是防止程序运行过程中错误地修改它引用。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746077,如需转载请自行联系原作者

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

IBatis.Net学习笔记十二:发现一个好用的IBatis.Net生成工具

现一个好用的IBatis.Net生成工具,可以根据数据库自动生成domain和xml文件,名称是 MyGeneration 。 我试用了一下,效果不错。 详细介绍参见它的主页: http://www.mygenerationsoftware.com/portal/default.aspx 支持的语言为:C#,vb.net 支持的数据库有: Microsoft SQL , Oracle , IBM DB2 , PostgreSQL , Microsoft Access , FireBird , Interbase , VistaDB , SQLite , MySQL , Advantage andPervasive 支持的架构有: dOOdads ,EntitySpaces,EasyObjects.NET/EntLib, Gentle.NET , Opf3 , NHibernate , Microsoft's DAAB , DotNetNuke , iBatis 也就是说这个工具是根据模板配置的,你也可以写一个自己的模板,来生成自己需要的格式的代码文件,比较方便灵活。 目前已经提供了一些常用的ORM框架的模板 下载地址: http://www.download.com/3001-10252_4-10685426.html?spi=76243c3b641e877670346e8d0bffceb9 IBatis模板的下载地址:http://www.mygenerationsoftware.com/TemplateLibrary/Archive/?guid=19d6d575-13f0-4aad-b887-e8ff7b6b17b2 本文转自永春博客园博客,原文链接:http://www.cnblogs.com/firstyi/archive/2007/10/11/921094.html,如需转载请自行联系原作者

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

cocos2d-x学习笔记07:在cocos2d-x中使用RTTI

有时,我们在开发中需要使用RTTI。什么?写的好的代码可以避免使用RTTI。不一定。什么情况下使用RTTI,一种很常见的例子,就是,我使用了一个父类指针容器,但是持有的是子类指针。并且,我需要调用子类指针的接口。这种情况下,就必须用RTTI了(或其他替代方案)。 使用RTTI的步骤。 #1.打开项目目录\android\jni\Application.mk #2. 注释APP_STL := stlport_static 添加两行: APP_STL := gnustl_static APP_CPPFLAGS += -frtti 解释:NDK中默认关闭RTTI,所以使用-frtti开启。NDK中附带的stlport库不支持RTTI(也不支持异常)。所以,我们要将其替换为GNU的STL库。(NDK一共有四个STL库,system,stlport静态,stilport动态,gnu静态) #3. 然后,使用cygwin控制台进入项目目录,clean一下。(最好直接删项目里的lib和obj文件夹,因为你改了编译选项,clean也是删不干净的。) 重新执行编译sh脚本即可 题外话: 1.我测试了自己的手机,黑屏原因不明,连cocos2dx自带例子用RTTI编译都不行。另外,也不是所有平台都支持RTTI,android也是后续才增加支持的。所以你用了RTTI兼容性需考虑。 2.RTTI会造成代码体积膨胀。效率可能会下降一点,不过我认为这不算什么问题。 3.替代方案,最简单的使用cocos2dx的setTag和getTag。不过这要你自己定义一套符号系统,而且看起来傻一些。 本文转自 老G 51CTO博客,原文链接: http://blog.51cto.com/goldlion/762112 ,如需转载请自行联系原作者

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

Hadoop概念学习系列之如何去找到历史版本的Hadoop发行包(三十四)

如何去找到历史版本的Hadoop发行包 找到Hadoop历史版本 这里我需要的Hadoop版本是2.0.3。打开hadoop的下载页面 http://www.apache.org/dyn/closer.cgi/hadoop/common/ 随便打开一个下载镜像,我们都找不到2.0.3这个版本。 具体怎么找到历史版本的Hadoop发行包,步骤如下: http://hadoop.apache.org/releases.html https://archive.apache.org/dist/hadoop/common/ 成功! 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5891316.html,如需转载请自行联系原作者

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

Spark RDD概念学习系列之RDD的依赖关系(宽依赖和窄依赖)(三)

RDD的依赖关系? RDD和它依赖的parent RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency)。 1)窄依赖指的是每一个parent RDD的Partition最多被子RDD的一个Partition使用,如图1所示。 2)宽依赖指的是多个子RDD的Partition会依赖同一个parent RDD的Partition,如图2所示。 RDD作为数据结构,本质上是一个只读的分区记录集合。一个RDD可以包含多个分区,每个分区就是一个dataset片段。RDD可以相互依赖。 1)如果RDD的每个分区最多只能被一个Child RDD的一个分区使用,则称之为narrow dependency。 2)如果多个Child RDD分区都可以依赖,则称之为wide / shuffle dependency 。 Spark之所以将依赖分为narrow 和 shuffle / wide 。基于两点原因 1、首先,narrow dependencies可以支持在同一个cluster node上,以pipeline形式执行多条命令,例如在执行了map后,紧接着执行filter。 相反,shuffle / wide dependencies 需要所有的父分区都是可用的,可能还需要调用类似MapReduce之类的操作进行跨节点传递。 2、其次,则是从失败恢复的角度考虑。narrow dependencies的失败恢复更有效,因为它只需要重新计算丢失的parent partition即可,而且可以并行地在不同节点进行重计算。 相反,shuffle / wide dependencies 牵涉RDD各级的多个parent partition。 图 1 RDD的窄依赖 图 2RDD的宽依赖 接下来可以从不同类型的转换来进一步理解RDD的窄依赖和宽依赖的区别,如图3所示。 对于map和filter形式的转换来说,它们只是将Partition的数据根据转换的规则进行转化,并不涉及其他的处理,可以简单地认为只是将数据从一个形式转换到另一个形式。对于union,只是将多个RDD合并成一个,parent RDD的Partition(s)不会有任何的变化,可以认为只是把parent RDD的Partition(s)简单进行复制与合并。对于join,如果每个Partition仅仅和已知的、特定的Partition进行join,那么这个依赖关系也是窄依赖。对于这种有规则的数据的join,并不会引入昂贵的Shuffle。对于窄依赖,由于RDD每个Partition依赖固定数量的parent RDD(s)的Partition(s),因此可以通过一个计算任务来处理这些Partition,并且这些Partition相互独立,这些计算任务也就可以并行执行了。 对于groupByKey,子RDD的所有Partition(s)会依赖于parent RDD的所有Partition(s),子RDD的Partition是parent RDD的所有Partition Shuffle的结果,因此这两个RDD是不能通过一个计算任务来完成的。同样,对于需要parent RDD的所有Partition进行join的转换,也是需要Shuffle,这类join的依赖就是宽依赖而不是前面提到的窄依赖了。 不同的操作依据其特性,可能会产生不同的依赖。例如map、filter操作会产生narrow dependency。reduceBykey操作会产生wide / shuffle dependency。 通俗点来说,RDD的每个Partition,仅仅依赖于父RDD中的一个Partition,这才是窄。就这么简单! 反正子Rdd的partition和父Rdd的Partition如果是一对一就是窄依赖,这样理解就好区分了 !!! 我以前总感觉这是窄依赖,其实 Rdd1的partition0依赖父Rdd0的 partition0和partition1,所以是宽依赖! 所有的依赖都要实现trait Dependency[T]: abstract class Dependency[T] extends Serializable { def rdd: RDD[T] } 其中rdd就是依赖的parent RDD。 对于窄依赖的实现(有两种) abstract class NarrowDependency[T](_rdd: RDD[T]) extends Dependency[T] { //返回子RDD的partitionId依赖的所有的parent RDD的Partition(s) def getParents(partitionId: Int): Seq[Int] override def rdd: RDD[T] = _rdd } 窄依赖是有两种具体实现,分别如下: ·一种是一对一的依赖,即OneToOneDependency: class OneToOneDependency[T](rdd: RDD[T]) extends NarrowDependency[T](rdd) { override def getParents(partitionId: Int) = List(partitionId) 通过getParents的实现不难看出,RDD仅仅依赖于parent RDD相同ID的Partition。 还有一个是范围的依赖,即 RangeDependency,它仅仅被org.apache.spark.rdd.UnionRDD使用。UnionRDD是把多个RDD合成一个RDD,这些RDD是被拼接而成,即每个parent RDD的Partition的相对顺序不会变,只不过每个parent RDD在UnionRDD中的Partition的起始位置不同。因此它的getPartents如下: override def getParents(partitionId: Int) = { if(partitionId >= outStart && partitionId < outStart + length) { List(partitionId - outStart + inStart) } else { Nil } } 其中,inStart是parent RDD中Partition的起始位置,outStart是在UnionRDD中的起始位置,length就是parent RDD中Partition的数量。 对于宽依赖的实现(只有一种) 宽依赖的实现只有一种:ShuffleDependency。子RDD依赖于parent RDD的所有Partition,因此需要Shuffle过程: class ShuffleDependency[K, V, C]( @transient _rdd: RDD[_ <: Product2[K, V]], val partitioner: Partitioner, val serializer: Option[Serializer] = None, val keyOrdering: Option[Ordering[K]] = None, val aggregator: Option[Aggregator[K, V, C]] = None, val mapSideCombine: Boolean = false) extends Dependency[Product2[K, V]] { override def rdd = _rdd.asInstanceOf[RDD[Product2[K, V]]] //获取新的shuffleId val shuffleId: Int = _rdd.context.newShuffleId() //向ShuffleManager注册Shuffle的信息 val shuffleHandle: ShuffleHandle = _rdd.context.env.shuffleManager.registerShuffle( shuffleId, _rdd.partitions.size, this) _rdd.sparkContext.cleaner.foreach(_.registerShuffleForCleanup(this)) } 注意:宽依赖支持两种Shuffle Manager。 即org.apache.spark.shuffle.hash.HashShuffleManager(基于Hash的Shuffle机制) 和org.apache.spark.shuffle.sort.SortShuffleManager(基于排序的Shuffle机制)。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5723403.html,如需转载请自行联系原作者

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

Hadoop概念学习系列之分布式数据集的容错性(二十七)

一般来说,分布式数据集的容错性有两种方式: 1、数据检查点 2、记录数据的更新 我们面向的是大规模数据分析,数据检查点操作成本很高:需要通过数据中心的网络连接在机器之间复制庞大的数据集,而网络带宽往往比内存带宽低得多,同时还需要消耗更多的存储资源(在内存中复制数据可以减少需要缓存的数据量,而存储到磁盘则会降低应用程序速度)。所以,我们选择记录更新的方式。 但是,如果更新太多,记录更新成本也不低。因此,RDD只支持粗粒度转换,即在大量记录上执行的单个操作。将创建RDD的一系列转换记录下来(即Lineage),以便恢复丢失的分区。 本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/5718799.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

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

Spring

Spring

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

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册