首页 文章 精选 留言 我的

精选列表

搜索[DUOX技术],共10007篇文章
优秀的个人博客,低调大师

Hystrix降级技术解析-Fallback

一、降级 所谓降级,就是指在在Hystrix执行非核心链路功能失败的情况下,我们如何处理,比如我们返回默认值等。如果我们要回退或者降级处理,代码上需要实现HystrixCommand.getFallback()方法或者是HystrixObservableCommand. HystrixObservableCommand()。 publicclassCommandHelloFailureextendsHystrixCommand<String>{ privatefinalStringname; publicCommandHelloFailure(Stringname){ super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.name=name; } @Override protectedStringrun(){ thrownewRuntimeException("thiscommandalwaysfails"); } @Override protectedStringgetFallback(){ return"HelloFailure"+name+"!"; } } 二、Hystrix的降级回退方式 Hystrix一共有如下几种降级回退模式: 1、Fail Fast 快速失败 @Override protectedStringrun(){ if(throwException){ thrownewRuntimeException("failurefromCommandThatFailsFast"); }else{ return"success"; } } 如果我们实现的是HystrixObservableCommand.java则 重写 resumeWithFallback方法 @Override protectedObservable<String>resumeWithFallback(){ if(throwException){ returnObservable.error(newThrowable("failurefromCommandThatFailsFast")); }else{ returnObservable.just("success"); } } 2、Fail Silent 无声失败 返回null,空Map,空List fail silent.png @Override protectedStringgetFallback(){ returnnull; } @Override protectedList<String>getFallback(){ returnCollections.emptyList(); } @Override protectedObservable<String>resumeWithFallback(){ returnObservable.empty(); } 3、Fallback: Static 返回默认值 回退的时候返回静态嵌入代码中的默认值,这样就不会导致功能以Fail Silent的方式被清楚,也就是用户看不到任何功能了。而是按照一个默认的方式显示。 @Override protectedBooleangetFallback(){ returntrue; } @Override protectedObservable<Boolean>resumeWithFallback(){ returnObservable.just(true); } 4、Fallback: Stubbed 自己组装一个值返回 当我们执行返回的结果是一个包含多个字段的对象时,则会以Stubbed 的方式回退。Stubbed 值我们建议在实例化Command的时候就设置好一个值。以countryCodeFromGeoLookup为例,countryCodeFromGeoLookup的值,是在我们调用的时候就注册进来初始化好的。CommandWithStubbedFallback command = new CommandWithStubbedFallback(1234, "china");主要代码如下: publicclassCommandWithStubbedFallbackextendsHystrixCommand<UserAccount>{ protectedCommandWithStubbedFallback(intcustomerId,StringcountryCodeFromGeoLookup){ super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.customerId=customerId; this.countryCodeFromGeoLookup=countryCodeFromGeoLookup; } @Override protectedUserAccountgetFallback(){ /** *Returnstubbedfallbackwithsomestaticdefaults,placeholders, *andaninjectedvalue'countryCodeFromGeoLookup'thatwe'lluse *insteadofwhatwewouldhaveretrievedfromtheremoteservice. */ returnnewUserAccount(customerId,"UnknownName", countryCodeFromGeoLookup,true,true,false); } 5、Fallback: Cache via Network 利用远程缓存 通过远程缓存的方式。在失败的情况下再发起一次remote请求,不过这次请求的是一个缓存比如redis。由于是又发起一起远程调用,所以会重新封装一次Command,这个时候要注意,执行fallback的线程一定要跟主线程区分开,也就是重新命名一个ThreadPoolKey。 Cache via Network.png publicclassCommandWithFallbackViaNetworkextendsHystrixCommand<String>{ privatefinalintid; protectedCommandWithFallbackViaNetwork(intid){ super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceX")) .andCommandKey(HystrixCommandKey.Factory.asKey("GetValueCommand"))); this.id=id; } @Override protectedStringrun(){ //RemoteServiceXClient.getValue(id); thrownewRuntimeException("forcefailureforexample"); } @Override protectedStringgetFallback(){ returnnewFallbackViaNetwork(id).execute(); } privatestaticclassFallbackViaNetworkextendsHystrixCommand<String>{ privatefinalintid; publicFallbackViaNetwork(intid){ super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("RemoteServiceX")) .andCommandKey(HystrixCommandKey.Factory.asKey("GetValueFallbackCommand")) //useadifferentthreadpoolforthefallbackcommand //sosaturatingtheRemoteServiceXpoolwon'tprevent //fallbacksfromexecuting .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("RemoteServiceXFallback"))); this.id=id; } @Override protectedStringrun(){ MemCacheClient.getValue(id); } @Override protectedStringgetFallback(){ //thefallbackalsofailed //sothisfallback-of-a-fallbackwill //failsilentlyandreturnnull returnnull; } } } 6、Primary + Secondary with Fallback 主次方式回退(主要和次要) 这个有点类似我们日常开发中需要上线一个新功能,但为了防止新功能上线失败可以回退到老的代码,我们会做一个开关比如使用zookeeper做一个配置开关,可以动态切换到老代码功能。那么Hystrix它是使用通过一个配置来在两个command中进行切换。 Primary + Secondary with Fallback.png /** *Sample{@linkHystrixCommand}patternusingasemaphore-isolatedcommand *thatconditionallyinvokesthread-isolatedcommands. */ publicclassCommandFacadeWithPrimarySecondaryextendsHystrixCommand<String>{ privatefinalstaticDynamicBooleanPropertyusePrimary=DynamicPropertyFactory.getInstance().getBooleanProperty("primarySecondary.usePrimary",true); privatefinalintid; publicCommandFacadeWithPrimarySecondary(intid){ super(Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX")) .andCommandKey(HystrixCommandKey.Factory.asKey("PrimarySecondaryCommand")) .andCommandPropertiesDefaults( //wewanttodefaulttosemaphore-isolationsincethiswraps //2otherscommandsthatarealreadythreadisolated //采用信号量的隔离方式 HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE))); this.id=id; } //通过DynamicPropertyFactory来路由到不同的command @Override protectedStringrun(){ if(usePrimary.get()){ returnnewPrimaryCommand(id).execute(); }else{ returnnewSecondaryCommand(id).execute(); } } @Override protectedStringgetFallback(){ return"static-fallback-"+id; } @Override protectedStringgetCacheKey(){ returnString.valueOf(id); } privatestaticclassPrimaryCommandextendsHystrixCommand<String>{ privatefinalintid; privatePrimaryCommand(intid){ super(Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX")) .andCommandKey(HystrixCommandKey.Factory.asKey("PrimaryCommand")) .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("PrimaryCommand")) .andCommandPropertiesDefaults( //wedefaulttoa600mstimeoutforprimary HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(600))); this.id=id; } @Override protectedStringrun(){ //performexpensive'primary'servicecall return"responseFromPrimary-"+id; } } privatestaticclassSecondaryCommandextendsHystrixCommand<String>{ privatefinalintid; privateSecondaryCommand(intid){ super(Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("SystemX")) .andCommandKey(HystrixCommandKey.Factory.asKey("SecondaryCommand")) .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("SecondaryCommand")) .andCommandPropertiesDefaults( //wedefaulttoa100mstimeoutforsecondary HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(100))); this.id=id; } @Override protectedStringrun(){ //performfast'secondary'servicecall return"responseFromSecondary-"+id; } } publicstaticclassUnitTest{ @Test publicvoidtestPrimary(){ HystrixRequestContextcontext=HystrixRequestContext.initializeContext(); try{ //将属性"primarySecondary.usePrimary"设置为true,则走PrimaryCommand;设置为false,则走SecondaryCommand ConfigurationManager.getConfigInstance().setProperty("primarySecondary.usePrimary",true); assertEquals("responseFromPrimary-20",newCommandFacadeWithPrimarySecondary(20).execute()); }finally{ context.shutdown(); ConfigurationManager.getConfigInstance().clear(); } } @Test publicvoidtestSecondary(){ HystrixRequestContextcontext=HystrixRequestContext.initializeContext(); try{ //将属性"primarySecondary.usePrimary"设置为true,则走PrimaryCommand;设置为false,则走SecondaryCommand ConfigurationManager.getConfigInstance().setProperty("primarySecondary.usePrimary",false); assertEquals("responseFromSecondary-20",newCommandFacadeWithPrimarySecondary(20).execute()); }finally{ context.shutdown(); ConfigurationManager.getConfigInstance().clear(); } } } } 三、总结 降级的处理方式,返回默认值,返回缓存里面的值(包括远程缓存比如redis和本地缓存比如jvmcache)。 但回退的处理方式也有不适合的场景: 1、写操作 2、批处理 3、计算 以上几种情况如果失败,则程序就要将错误返回给调用者。 参考资料:https://github.com/Netflix/Hystrix/wiki

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

iOS ShareSDK桥接技术

前言 在游戏开发中,难免会出现与原生平台有交互才能完成一些特定的必要的功能。比如iOS的内购功能,或者你想用一款第三方SDK,但是此SDK却没有对应平台的版本、并且未提供插件的情况下,就会涉及到与第三方平台的交互。 Unity3D 简介:Unity3D(以下简称U3D)是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。 Unity3D调用原生iOS接口 Unity3D 无法直接调用iOS原生的OC或者swift语言,但是Unity3D使用的C#可以和C进行交互。而C是可以和OC进行交互的。从而就可以实现C#调用OC。 以ShareSDK的Unity桥接为例: 先定义 分享的C语言方法 void __iosShareSDKShare (int reqID, int platType, void *content, void *observer){ NSMutableDictionary *shareParams = __getShareParamsWithString(contentStr); [ShareSDK share:platType parameters:shareParams onStateChanged:nil]; } C#中则可以像下面代码一样进行引入和调用: using System.Runtime.InteropServices; [DllImport("__Internal")] private static extern void __iosShareSDKShare (int reqID, int platType, string content, string observer); 其中DllImport为一个Attribute,目的是通过非托管方式将库中的方法导出到C#中进行使用。而传入"__Internal"则是表示这个是一个静态库或者是一个内部方法。通过上面的声明,这个方法就可以在C#里面进行调用了 比如Unity游戏需要分享的时候直接调用下面方法就可以了: void ShareContent (int reqID, PlatformType platform, ShareContent content) { __iosShareSDKShare (reqID, (int)platform, content.GetShareParamsStr(), _callbackObjectName); } iOS 调用Unity的接口 在特定场景下也会有iOS接口调用Unity的C#接口的情况,比如分享后回调的分享结果就要传递到原生的unity层。最简单的方式是通过UnitySendMessage方法来调用Unity所定义的方法。 仍然以ShareSDK的回调为例: 在Unity的里ShareSDK.cs定义一个回调方法 private void _Callback (string data) { Debug.LogFormat ("result string = {0}", data); } 挂载ShareSDK.cs到Main Camera中 在OC层,在ShareSDK的分享回调block执行UnitySendMessage void __iosShareSDKShare (int reqID, int platType, void *content, void *observer) { NSMutableDictionary *shareParams = __getShareParamsWithString(contentStr); [ShareSDK share:platType parameters:shareParams onStateChanged:^(SSDKResponseState state, NSDictionary *userData, SSDKContentEntity *contentEntity, NSError *error) { NSString *resultStr = nil; // process resultStr // ... UnitySendMessage(observer, "_Callback", [resultStr UTF8String]); }]; } 其中 observer值为挂载的"Main Camera" 注意:UnitySendMessage方式无法同步获取返回值,并且必须要挂载到对象后才能调用,复杂需求可以使用 非托管的方式进行交互,具体可以参考:https://www.jianshu.com/p/1ab65bee6692 Cocos2d 是一个基于MIT协议的开源框架,用于构建游戏、应用程序和其他图形界面交互应用。可以让你在创建自己的多平台游戏时节省很多的时间。 由于主流的cocos2d游戏开发语言是C++,而C++ 和OC是可以直接交互的,只需把OC的实现文件.m修改为.mm即可,那么只需要定义一个C++的接口直接调用OC既可 typedef void(*C2DXShareResultEvent) (int reqID, C2DXResponseState state, C2DXPlatType platType, C2DXDictionary *res); void C2DXiOSShareSDK::shareContent(int reqID,C2DXPlatType platType, C2DXDictionary *content,bool useClientShare, C2DXShareResultEvent callback) { NSMutableDictionary *parameters = convertPublishContent(content); [ShareSDK share:(SSDKPlatformType)platType parameters:parameters onStateChanged:^(SSDKResponseState state, NSDictionary *userData, SSDKContentEntity *contentEntity, NSError *error) { // process callback ... //callback callback(reqID,(C2DXResponseState)state,(C2DXPlatType)platType,userInfoDict); }]; }

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

Docker技术实践——高级篇

1.1 搭建私有仓库 我们需要看下如何搭建容器的私有仓库: Mavan的管理一样,Dockers不仅提供了一个中央仓库,同时也允许我们使用registry搭建本地私有仓库。 私有仓库有许多优点: 1.节省网络带宽,不用每个人都去中央仓库上面去下载,只需要从私有仓库中下载即可; 2.提供镜像资源利用,针对于公司内部使用的镜像,推送到本地的私有仓库中,以供公司内部相关人员使用。 #docker pull registry #dockerrun -d -p 5000:5000 --name registry-srv registry 默认仓库存放于容器内的/tmp/registry目录下 镜像需要通过docker tag进行修改,符合仓库需要。 #docker push 192.168.1.104:5000/hello-world 如果出现如下错误: http: server gave HTTP response to HTTPS client 这是因为docker registry交互默认使用的是https,然而此处搭建的私有仓库只提供http服务,所以当与私有仓库交互时就会报上面的错误。 MAC机器中修改: 在Docker的preference中,点击Daemon,Basic页签中,在Insecureregistries中增加一行: http://192.168.1.104:5000 点击apply and restart重启docker即可。 Ubuntu机器中修改: (Ubuntu的地址为/etc/init/docker.conf),在其中增加 --insecure-registry 192.168.1.104:5000 exec"$DOCKERD"$DOCKER_OPTS--raw-logs --insecure-registry 192.168.1.104:5000 然后重启 docker; #service docker restart; 如果上述方法不行,那么如下: 在”/etc/docker/“目录下,创建”daemon.json“文件。在文件中写入: { "insecure-registries":["192.168.1.104:5000"]} 然后重启 docker; #service docker restart; 1.2 上传镜像 # docker push registry:5000/image_name 1.3 查看镜像 # curl -XGET http://registry:5000/v2/_catalog # curl -XGEThttp://registry:5000/v2/image_name/tags/list 例如: #curl -XGEThttp://192.168.1.104:5000/v2/_catalog 输出如下: {"repositories":["centos","hello-world"]} # curl -XGEThttp://192.168.1.104:5000/v2/centos/tags/list 输出如下: {"name":"centos","tags":["7.1"]} 1.4 Docker-compose Docker-compose需要docker-compose.yml文件,依赖yml文件,没有yml文件就没有勇武之地了。 Docker Compose是一个用来定义和运行复杂应用的Docker工具。使用Compose,你可以在一个文件中定义一个多容器应用,然后使用一条命令来启动你的应用,完成一切准备工作。 编辑docker-compose.yml内容如下: mysql: image: csphere/mysql:5.5 ports: - "3306:3306" wordpress: image: csphere/wordpress:10 ports: -"80:80" 启动容器如下: docker-composeup-d 关闭容器: docker-compose stop 2. Q&A 2.1 编译错误 Rpmdb checksum is invalid: dCDPT(pkgchecksums): elfutils-libs.x86_64 0:0.168-8.el7 - u 答:在 Docker 文件中第一个 yum 之前加入如下命令对rpmdb 进行构筑. RUN rpm --rebuilddb&& \

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

Docker技术实践——中级篇

1.1 存储机制 每个镜像由多个镜像层组成,镜像层都是只读的,从下往上,以栈方式组合在一起,组成容器的根文件系统。镜像文件默认保存在主机的/var/lib/docker/volumes中。 容器层是可读写层。每个容器运行时都有自己的容器层,保存容器运行相关的数据,容器层之下的所有镜像都是只读的,多个容器可以共享一个镜像。容器层是保存在/var/lib/docker/containers路径。每次新建容器时,只需要为每个容器新建一个可写的数据层,而不用复制所有的镜像层。 容器层和镜像层都保存在宿主机的文件系统中,通过Docker存储驱动来管理。 1.2 数据卷和存储驱动 容器使用数据卷保证数据持久性,删除容器时候,所有不在数据卷中的数据都会被删除。因为数据卷是主机上的一个文件或者目录,不受存储驱动程序管理。 Docker设计了一套存储驱动插件框架,开发者可以基于此套标准,设计开发自己的存储驱动。 可以使用docker info查看当前存储驱动。 使用哪种存储驱动取决于用户在宿主机上使用何种文件系统。有些存储驱动可以工作在不同的后端文件系统上。 可以在启动Docker使用使用--storage-driver来指定。 Docker中每种存储驱动都是基于Linux文件系统或卷管理工具的。 1.3 定制Docker Daemon 因为Docker Daemon有七八十个启动选项,根据应用场景定制Docker运行环境就显得非常有必要。 在命令行中输入dockerd即可启动,就是默认的方式启动Daemon了。 如果开启debug模式,可以执行 #dockerd -D 仓库相关配置: --disable-legacy-registry选项,可以选择不从旧版本的镜像仓库中下载镜像。因为Docker从1.6版本后,支持从V2版本的镜像仓库下载镜像。 使用镜像仓库,使用参数—registry-mirror选项。 此外,还有何网络配置相关的等等。 因为,旧版本docker的配置文件默认的在 /etc/default/docker ,现在已不推荐。 变量的使用查看/lib/systemd/system/docker.service 可以参考官方指南:

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

ZooKeeper 技术内幕初探(二)

前面介绍了ZooKeeper的一些基本特性,ZooKeeper入门,也安装运行了一个简单的ZooKeeper的例子。这此主要介绍ZooKeeper内部的一些工作方式理论部分。 与文无关 主要涉及以下: ZooKeeper服务的架构 ZooKeeper的数据模型 ZooKeeper的节点特性 ZooKeeper的访问控制 Watcher(监听器) ZooKeeper服务概览 ZooKeeper是一个复制式的分布式应用,有点像DNS服务或一些中心化的服务。 ZooKeeper服务架构 这是官网给的ZooKeeper服务图,所有组成ZooKeeper服务的服务器都相互知晓,它们维护了一个内存状态的镜像,也包含事务日志,持久存储的快照等。只要半数以上的的服务器是可用的,ZooKeeper服务就是可用的。 顺便提一下ZooKeeper的设计目标(Design Goals) 简单 复制式的 所有节点相互复制状态 有序的,所有的事务都有时间戳 快速 在读大于写的时候... ZooKeeper读写图 ZooKeeper在读数据的时候可以直接从当前节点读取数据,在写数据的时候需要将写请求转发到Leader节点上。 ZooKeeper数据模型 ZooKeeper的各个服务器节点共同维护一个可以注册数据的层级结构,类似于Unix的文件系统。数据注册的位置也称为znode。 Znode图 注意: 数据节点一般以字节形式存储,节点存储的数据大小最大不超过1MB。协作的数据一般不会太大。最好让数据远小于1MB会好些。 ZooKeeper无法识别相对路径。 znode的路径必须是绝对路径 每个Znode除了存储数据以外,还有维护一些状态信息。 Znode 特性 Znode类型 ZooKeeper主要有两种节点类型,也可以说是三种。持久节点,临时节点。第三个是顺序节点,顺序节点也可以说是刚才那两种节点。 持久节点和顺序节点都可以是顺序节点。 注意节点的类型是在创建的时候就设置好的。 持久节点。ZooKeeper中最常见的一种节点类型,创建之后一直存在服务器上,知道有删除操作来主动清楚这个节点 临时节点,与客户端会话绑定在一起。 客户端会话失效,节点自动清理。(网络突然坏掉不算会话失效) 顺序节点,在节点创建的时候,ZooKeeper自动给节点名分配一个序列号。例如/path/to/znode-0000000001,一般是10位数字,序号之外的位以0填充。 节点状态 每一个Znode都有对应的stat结构,和文件系统类似。stat状态主要包含下面的信息: cZxid. 节点被创建时候的事务ID mZxid 节点最后一次被修改时候的事务ID pZxid 该节点的子节点最后一次被修改时的事务ID。子节点删除或添加才会影响pZxid ctime 节点被创建的时间 mtime 节点被修改的世界 dataVersion 这个节点数据改变的次数 cversion 子节点被改变的次数 aclVersion 节点的ACL(访问控制列表被改变的次数) ephemeralOwner 创建该临时节点的 session ID。如果是持久节点,设置为0 dataLength 数据内容长度 numChildren 当前节点子节点的个数 可以使用ls2和stat命令查看ZooKeeper节点下的信息。 命令演示 ZooKeeper的访问控制(ACL) ZooKeeper的数据模型提供了ACL来控制znode节点的访问。如果一个客户端符合ACL控制,那么就可以对其进行访问,否则将无法操作。 Zookeeper支持可配置的认证机制。它利用一个三元组来定义客户端的访问权限: (scheme:expression, perms) 。其中: Schema 代表权限控制模式,分别为 World 任何人 Auth 不需要ID Digest 用户名和密码方式的认证 IP Address IP地址方式的认证 perms(权限),ZooKeeper支持如下权限 CREATE: 创建子节点 READ: 获取子节点与自身节点的数据信息 WRITE:在Znode节点上写数据 DELETE:删除子节点 ADMIN:设置ACL权限 贴上如下图,在下次使用ZooKeeper的时候更明白,这次我们主要说明一些ZooKeeper理论方面的知识,具体编程的实现下次再说。 ACL图 权限模式和授权对象的关系: IP: 通常是IP地址或是IP端,例如"192.168.1.2"或"192.168.1.1/24" Degist: 自定义,通常是"username:BASE64(SHA-1(username:password))" World:只有一个ID,“anyone” Super: 与Degist模式一致 注意: Znode的Acl只是针对某个节点,不会作用到它的子节点上 任何连接到ZooKeeper的客户端都可以使用exist操作,exist是不需要权限的。 ZooKeeper的Watcher ZooKeeper中引入了Watcher机制来实现分布式通知功能,ZooKeeper允许客户端像服务端注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。 有如下的Watcher事件类型可能出现: NodeChildrenChanged: zNode的子节点创建或删除的时候 NodeCreated: 新的Znode节点被创建的时候 NodeDataChanged: Znode节点的数据改变了的时候 NodeDeleted: Znode节点被删除的时候。 关于Watcher内部实现机制,下次可以通过分析其源码进行更详细的说明 最后 这次主要介绍了一些ZooKeeper内部的基本概念,理论部分较多,若无理论的基础实施接下来的操作也不太方便。 接下来我会写下: ZooKeeper 客户端编程 ZooKeeper Watcher监听器原理分析 参考 《从Paxos到ZooKeeper-分布式一致性原理与实践》 《Apache ZooKeeper Essential》 ZooKeeper Overview

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

大数据的技术生态

大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的。你可以把它比作一个厨房所以需要的各种工具。锅碗瓢盆,各有各的用处,互相之间又有重合。你可以用汤锅直接当碗吃饭喝汤,你可以用小刀或者刨子去皮。但是每个工具有自己的特性,虽然奇怪的组合也能工作,但是未必是最佳选择。 大数据,首先你要能存的下大数据。 传统的文件系统是单机的,不能横跨不同的机器。HDFS(Hadoo上。你作为用户,不需要知道这些,就好比在单机上你不关心文件分散在什么磁道什么扇区一样。HDFS为你管理这些数据。p Distributed FileSystem)的设计本质上是为了大量的数据能横跨成百上千台机器,但是你看到的是一个文件系统而不是很多文件系统。比如你说我要获取/hdfs/tmp/file1的数据,你引用的是一个文件路径,但是实际的数据存放在很多不同的机器 存的下数据之后,你就开始考虑怎么处理数据。虽然HDFS可以为你整体管理不同机器上的数据,但是这些数据太大了。一台机器读取成T上P的数据(很大的数据哦,比如整个东京热有史以来所有高清电影的大小甚至更大),一台机器慢慢跑也许需要好几天甚至好几周。对于很多公司来说,单机处理是不可忍受的,比如微博要更新24小时热博,它必须在24小时之内跑完这些处理。那么我如果要用很多台机器处理,我就面临了如何分配工作,如果一台机器挂了如何重新启动相应的任务,机器之间如何互相通信交换数据以完成复杂的计算等等。这就是MapReduce / Tez / Spark的功能。MapReduce是第一代计算引擎,Tez和Spark是第二代。MapReduce的设计,采用了很简化的计算模型,只有Map和Reduce两个计算过程(中间用Shuffle串联),用这个模型,已经可以处理大数据领域很大一部分问题了。 那什么是Map什么是Reduce? 考虑如果你要统计一个巨大的文本文件存储在类似HDFS上,你想要知道这个文本里各个词的出现频率。你启动了一个MapReduce程序。Map阶段,几百台机器同时读取这个文件的各个部分,分别把各自读到的部分分别统计出词频,产生类似(hello, 12100次),(world,15214次)等等这样的Pair(我这里把Map和Combine放在一起说以便简化);这几百台机器各自都产生了如上的集合,然后又有几百台机器启动Reduce处理。Reducer机器A将从Mapper机器收到所有以A开头的统计结果,机器B将收到B开头的词汇统计结果(当然实际上不会真的以字母开头做依据,而是用函数产生Hash值以避免数据串化。因为类似X开头的词肯定比其他要少得多,而你不希望数据处理各个机器的工作量相差悬殊)。然后这些Reducer将再次汇总,(hello,12100)+(hello,12311)+(hello,345881)= (hello,370292)。每个Reducer都如上处理,你就得到了整个文件的词频结果。 这看似是个很简单的模型,但很多算法都可以用这个模型描述了。 Map+Reduce的简单模型很黄很暴力,虽然好用,但是很笨重。第二代的Tez和Spark除了内存Cache之类的新feature,本质上来说,是让Map/Reduce模型更通用,让Map和Reduce之间的界限更模糊,数据交换更灵活,更少的磁盘读写,以便更方便地描述复杂算法,取得更高的吞吐量。 有了MapReduce,Tez和Spark之后,程序员发现,MapReduce的程序写起来真麻烦。他们希望简化这个过程。这就好比你有了汇编语言,虽然你几乎什么都能干了,但是你还是觉得繁琐。你希望有个更高层更抽象的语言层来描述算法和数据处理流程。于是就有了Pig和Hive。Pig是接近脚本方式去描述MapReduce,Hive则用的是SQL。它们把脚本和SQL语言翻译成MapReduce程序,丢给计算引擎去计算,而你就从繁琐的MapReduce程序中解脱出来,用更简单更直观的语言去写程序了。 有了Hive之后,人们发现SQL对比Java有巨大的优势。一个是它太容易写了。刚才词频的东西,用SQL描述就只有一两行,MapReduce写起来大约要几十上百行。而更重要的是,非计算机背景的用户终于感受到了爱:我也会写SQL!于是数据分析人员终于从乞求工程师帮忙的窘境解脱出来,工程师也从写奇怪的一次性的处理程序中解脱出来。大家都开心了。Hive逐渐成长成了大数据仓库的核心组件。甚至很多公司的流水线作业集完全是用SQL描述,因为易写易改,一看就懂,容易维护。 自从数据分析人员开始用Hive分析数据之后,它们发现,Hive在MapReduce上跑,真鸡巴慢!流水线作业集也许没啥关系,比如24小时更新的推荐,反正24小时内跑完就算了。但是数据分析,人们总是希望能跑更快一些。比如我希望看过去一个小时内多少人在充气娃娃页面驻足,分别停留了多久,对于一个巨型网站海量数据下,这个处理过程也许要花几十分钟甚至很多小时。而这个分析也许只是你万里长征的第一步,你还要看多少人浏览了跳蛋多少人看了拉赫曼尼诺夫的CD,以便跟老板汇报,我们的用户是猥琐男闷骚女更多还是文艺青年/少女更多。你无法忍受等待的折磨,只能跟帅帅的工程师蝈蝈说,快,快,再快一点! 于是Impala,Presto,Drill诞生了(当然还有无数非著名的交互SQL引擎,就不一一列举了)。三个系统的核心理念是,MapReduce引擎太慢,因为它太通用,太强壮,太保守,我们SQL需要更轻量,更激进地获取资源,更专门地对SQL做优化,而且不需要那么多容错性保证(因为系统出错了大不了重新启动任务,如果整个处理时间更短的话,比如几分钟之内)。这些系统让用户更快速地处理SQL任务,牺牲了通用性稳定性等特性。如果说MapReduce是大砍刀,砍啥都不怕,那上面三个就是剔骨刀,灵巧锋利,但是不能搞太大太硬的东西。 这些系统,说实话,一直没有达到人们期望的流行度。因为这时候又两个异类被造出来了。他们是Hive on Tez / Spark和SparkSQL。它们的设计理念是,MapReduce慢,但是如果我用新一代通用计算引擎Tez或者Spark来跑SQL,那我就能跑的更快。而且用户不需要维护两套系统。这就好比如果你厨房小,人又懒,对吃的精细程度要求有限,那你可以买个电饭煲,能蒸能煲能烧,省了好多厨具。 上面的介绍,基本就是一个数据仓库的构架了。底层HDFS,上面跑MapReduce/Tez/Spark,在上面跑Hive,Pig。或者HDFS上直接跑Impala,Drill,Presto。这解决了中低速数据处理的要求。 那如果我要更高速的处理呢? 如果我是一个类似微博的公司,我希望显示不是24小时热博,我想看一个不断变化的热播榜,更新延迟在一分钟之内,上面的手段都将无法胜任。于是又一种计算模型被开发出来,这就是Streaming(流)计算。Storm是最流行的流计算平台。流计算的思路是,如果要达到更实时的更新,我何不在数据流进来的时候就处理了?比如还是词频统计的例子,我的数据流是一个一个的词,我就让他们一边流过我就一边开始统计了。流计算很牛逼,基本无延迟,但是它的短处是,不灵活,你想要统计的东西必须预先知道,毕竟数据流过就没了,你没算的东西就无法补算了。因此它是个很好的东西,但是无法替代上面数据仓库和批处理系统。 还有一个有些独立的模块是KV Store,比如Cassandra,HBase,MongoDB以及很多很多很多很多其他的(多到无法想象)。所以KV Store就是说,我有一堆键值,我能很快速滴获取与这个Key绑定的数据。比如我用身份证号,能取到你的身份数据。这个动作用MapReduce也能完成,但是很可能要扫描整个数据集。而KV Store专用来处理这个操作,所有存和取都专门为此优化了。从几个P的数据中查找一个身份证号,也许只要零点几秒。这让大数据公司的一些专门操作被大大优化了。比如我网页上有个根据订单号查找订单内容的页面,而整个网站的订单数量无法单机数据库存储,我就会考虑用KV Store来存。KV Store的理念是,基本无法处理复杂的计算,大多没法JOIN,也许没法聚合,没有强一致性保证(不同数据分布在不同机器上,你每次读取也许会读到不同的结果,也无法处理类似银行转账那样的强一致性要求的操作)。但是丫就是快。极快。 每个不同的KV Store设计都有不同取舍,有些更快,有些容量更高,有些可以支持更复杂的操作。必有一款适合你。 除此之外,还有一些更特制的系统/组件,比如Mahout是分布式机器学习库,Protobuf是数据交换的编码和库,ZooKeeper是高一致性的分布存取协同系统,等等。 有了这么多乱七八糟的工具,都在同一个集群上运转,大家需要互相尊重有序工作。所以另外一个重要组件是,调度系统。现在最流行的是Yarn。你可以把他看作中央管理,好比你妈在厨房监工,哎,你妹妹切菜切完了,你可以把刀拿去杀鸡了。只要大家都服从你妈分配,那大家都能愉快滴烧菜。 你可以认为,大数据生态圈就是一个厨房工具生态圈。为了做不同的菜,中国菜,日本菜,法国菜,你需要各种不同的工具。而且客人的需求正在复杂化,你的厨具不断被发明,也没有一个万用的厨具可以处理所有情况,因此它会变的越来越复杂。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

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等操作系统。

用户登录
用户注册