【虚拟网站源码】【创投网站源码】【互通传奇源码】hdfs底层源码_hdfs源码剖析

时间:2024-12-24 03:40:40 分类:spark+源码打包 来源:小程序源码测试

1.如何更改 datax 以支持hive 的底层 DECIMAL 数据类型?
2.HDFS纠删码
3.Alluxio 客户端源码分析
4.从线上某应用多作业并发创建同一HIVE表分区偶现失败问题聊起-深度剖析下HIVE创建表分区的内部逻辑
5.要成为一名专业的程序员,从零开始需要怎么一步步来比较好,源码源码要把最底层的剖析先学精通吗?(个人认为)求学长

hdfs底层源码_hdfs源码剖析

如何更改 datax 以支持hive 的 DECIMAL 数据类型?

       在处理数据时,我们经常需要将数据从一种数据类型转换为另一种数据类型。底层在数据迁移任务中,源码源码如果涉及到使用datax进行数据迁移,剖析虚拟网站源码且源数据或目标数据中出现了Hive的底层DECIMAL数据类型,那么如何确保数据迁移的源码源码准确性和完整性就成为了一个关键问题。本文将详细介绍如何更改datax以支持Hive的剖析DECIMAL数据类型。

       在JAVA中,底层主要使用float/double和BigDecimal来存储小数。源码源码其中,剖析float和double在不需要完全精确的底层计算结果的场景下,可以提供较高的源码源码运算效率,但当涉及到金融等场景需要精确计算时,剖析必须使用BigDecimal。

       Hive支持多种数字类型数据,如FLOAT、DOUBLE、DECIMAL和NUMERIC。DECIMAL数据类型是后加入的,允许设置精度和标度,适用于需要高度精确计算的场景。

       若要使datax支持Hive的DECIMAL数据类型,关键在于修改datax源码,增强其对DECIMAL数据的读取和写入能力。主要通过以下几个步骤:

       1. **修改HDFS Reader**:在处理Hive ORC文件时,需要修改HDFS Reader插件中的相关类和方法,如DFSUtil#transportOneRecord。通过该步骤,创投网站源码确保能正确读取到ORC文件中的DECIMAL字段。datax的Double类型可以通过其内部的rawData字段存储数据的原始内容,支持Java.math.BigDecimal和Java.lang.Double,因此可以实现不修改HDFS Reader代码,直接读取并处理DECIMAL数据的目标。配置作业时,将Hive的DECIMAL字段指定为datax的Double类型,HDFS Reader在底层调用Hive相关API读取ORC文件中的DECIMAL字段,将其隐式转换为Double类型。datax的Double类型支持Java.math.BigDecimal和Java.lang.Double,确保后续写入操作的精度。

       2. **修改HDFS Writer**:为了支持写入数据到Hive ORC文件中的DECIMAL字段,同样需要在HDFS Writer插件中进行相应的代码修改。修改后的代码确保能够将datax的Double字段正确写入到Hive ORC文件中的DECIMAL字段。使用方法com.alibaba.datax.common.element.DoubleColumn#asBigDecimal,基于DoubleColumn底层rawData存储的原始数据内容,将字段值转换为合适的外部数据类型。这一过程不会损失数据精度。

       综上所述,通过修改datax的HDFS Reader和Writer插件,实现对Hive DECIMAL数据类型的读取和写入支持,确保数据迁移过程的准确性和完整性,从而满足复杂数据迁移场景的需求。

HDFS纠删码

           å‰¯æœ¬æ˜¯æ˜‚贵的--在HDFS中默认的3副本机制有%的存储空间和其它的资源(比如:网络带宽)开销。然而,相对于低 I/O 活动的暖数据集和冷数据集,在正常的操作期间对其额外的副本很少访问,但是仍然消耗与第一副本相同数量的资源。

            å› æ­¤ï¼Œä¸€ä¸ªè‡ªç„¶çš„改进是使用纠删码(Erasure Coding)替代副本机制,它使用更少的存储空间提供相同的容错级别,一个典型的纠删码设置,会使得存储空间的开销不超过%;一个EC文件的副本因子是无意义的,它一直保持为1,并且不能通过命令 -setrep修改EC的副本因子的值。

            ç£ç›˜é˜µåˆ—(RAID)是在存储系统中,使用EC最出名的。RAID使用条 带的方式实现的EC,它提供逻辑上序列的数据(比如文件)到更小的单元(比如比特、字节、或块),并存储连续的单元到不同的磁盘上。在本指南的其余部分,这种条带分布单元被称为条带单元(或者单元),对于每一个条带原始数据单元,计算并存储一定数量的奇偶校验单元,这个过程叫做编码。通过对剩余的数据和奇偶校验单元解码计算,可以恢复任意条带单元的错误。

            å°†EC和HDFS集成可以提高存储效率,然而同样提供传统的基于副本机制的HDFS持久化部署,例如:3副本的文件有6个块,将会消耗 6*3 = 个块的磁盘空间,但是使用EC(6个数据,3个校验)部署,他将只消耗9个块的磁盘空间。

            åœ¨EC的环境中,条带有若干主要的优点,首先,它能在线EC(使用EC的格式直接写数据),避免转换阶段,直接节省存储空间。在线EC通过并行利用多磁盘主轴增强I/O性能;这在高性能的网络的集群中尤其需要。其次,它自然的分发小文件到多个DataNodes,消除了将多个文件绑定到一个编码组的需要,这会很大的简化文件的操作,比如删除、配额汇报和在联邦集群中不同的Namespace之间迁移数据等。在典型的HDFS集群中,小文件占总存储空间3/4以上的消耗,为了更好的支持小文件,在第一阶段工作中,HDFS支持条带的EC。在未来,HDFS也会支持连续的EC布局,查看设计文档,更多的信息在issue HDFS- 中讨论。

             条带的HDFS文件是由逻辑上的块组构成,每个块组包含一定数量的内部块,为了减少额外的块对NameNode内存消耗,提出了新的分层块命名协议,块组的ID可以从它的内部块的任意 ID 中推断出来,这允许块组级别的管理,而不是块级别的。

             客户端读写路径被增强,可以并行处理一个块组的多个内部块;在输出/写入路径, DFSStripedOutputStream 用于管理一组数据流,每个数据流对应一个DataNode,该DataNode在当前块组中存储一个内部块,这些数据流大多是异步工作;协调器负责操作整个块组,包括结束当前的块组、分配新的块组等等。在输入 / 读路径, DFSStripedInputStream 将请求的逻辑字节范围的数据转换为存储在DataNodes上的内部块的范围,然后并行的发布读请求,在出现故障时,它发出额外的读请求用于解码。

             DataNode会运行一个额外的 ErasureCodingWorker (ECWorker) 任务用于后台恢复失败的EC块,当NameNode检测到一个失败的EC块,它会选择一个DataNode去做恢复的工作,恢复任务通过心跳响应传递至DataNode,这个过程类似于副本块重新复制失败的数据块,重建失败的块有3个主要的任务:

             使用专用的线程池并行的读取输入数据,基于EC策略,它将所有的读请求调度到所有的源节点,并且只读取最小数据量的输入块数用于重构。

             从输入数据中解码出新的数据块和奇偶校验块,所有丢失的数据块和校验块一起解码。

             解码完成后,恢复的数据块被传输到目标DataNode节点。

             为了使纠删码策略适合异构的工作方式,我们允许HDFS集群上的文件和目录具有不同的副本和纠删码策略,纠删码策略封装了如何编码/解码文件,每一个策略由以下信息部分定义:

             这个包括在EC组(比如:6+3)中数据块和校验块的数量,以及编解码器算法(比如: Reed-Solomon, XOR )

            è¿™å†³å®šäº†æ¡å¸¦è¯»å†™çš„粒度,包括缓冲区大小和编码工作。

           ç­–略被命名为数据块数量-校验块数量-块单元的大小,当前支持6种内置策略:RS-3-2-k, RS-6-3-k, RS--4-k, RS-LEGACY-6-3-k, XOR-2-1-k å’ŒREPLICATION。

            REPLICATION是一种特殊的策略,它只能被设置在目录上,强制目录采用3副本策略,而不是继承它的祖先的纠删码策略,该策略使3副本目录与纠删码目录交叉成为可能。

            REPLICATION ç­–略是一直启用的,而其它的内置策略在默认的情况下是禁用的。

            ç±»ä¼¼äºŽHDFS存储策略,纠删码策略是设置在目录上的,当一个文件被创建,它继承离它最近的祖先目录的EC策略。

            ç›®å½•çº§åˆ«çš„EC策略只影响在该目录下创建的新文件,一旦一个文件已经被创建,它的纠删码策略可以被查询,但是不能改变,如果一个纠删码文件被重命名到一个不同的EC策略的目录中,该文件会保留它之前存在的EC策略,转换一个文件到不同的EC策略需要重写它的数据,重写数据是通过拷贝文件(比如:通过distcp)而不是重命名文件。

            æˆ‘们允许用户通过XML文件的方式去定义它们自己的EC策略,该XML文件必须要有下面的3部分:

                1) layoutversion:  表示EC策略文件格式的版本。

                2) schemas: 这个包括所有用户定义的EC约束

                3) policies:  这个包括所有用户定义的EC策略,每个策略由schema id和条带单元的大小(cellsize)构成,

            åœ¨hadoop conf目录中有一个名称叫 user_ec_policies.xml.template的样本EC策略的XML文件。

            因特尔 ISA-L 代表因特尔智能存储加速库, ISA-L 是为存储应用程序优化的底层函数开源的集合,它包括在 AVX 和 AVX2 指令集上快速的块  Reed-Solomon 类型的纠删码优化,HDFS纠删码可以利用ISA-L去加速编解码计算,ISA-L支持大多数开源的操作系统,包括linux和windows,ISA-L默认是不启动的,有关如何启动ISA-L,请看下面的说明。

            çº åˆ ç åœ¨é›†ç¾¤çš„CPU和网络方面提出了额外的要求。

            ç¼–码和解码工作会消耗HDFS客户端和DataNodes上额外的CPU。

            çº åˆ ç æ–‡ä»¶ä¹Ÿåˆ†å¸ƒåœ¨æœºæž¶ä¹‹é—´ï¼Œç”¨äºŽæœºæž¶å®¹é”™ï¼Œè¿™æ„å‘³ç€å½“读取和写入条带文件,大多数操作是在机架外的,因此,网络对分带宽非常重要的。

            å¯¹äºŽæœºæž¶å®¹é”™æ¥è¯´ï¼Œè‡³å°‘拥有与配置的EC条带宽度相同的机架数量也是很重要的,对于EC策略RS (6,3),这意味着至少要有9个机架,理想的情况下要有或者个机架用于处理计划内和计划外的停机。对于机架数量少于条带宽度的集群,HDFS不能维护机架容错,但是仍然会分散条带文件到多个节点为了节点级别的容错。

            é»˜è®¤æƒ…况下,所有内置的纠删码策略是被禁用的,但是定义在参数dfs.namenode.ec.system.default.policy中的除外,该策略在默认情况下是启用的。集群管理员可以根据集群的大小和希望的容错属性使用命令hdfs ec [-enablePolicy -policy <policyName>]启用一组策略;例如,对于一个拥有9个机架的集群,类似RS--4-k è¿™æ ·çš„策略不能达到机架级别的容错,而策略RS-6-3-k æˆ–者RS-3-2-k更适合。如果管理员只关心节点级别的容错,在至少有个DataNodes的集群中策略RS--4-k也是适合的。

            ç³»ç»Ÿé»˜è®¤çš„EC策略可以通过参数‘dfs.namenode.ec.system.default.policy’ 来配置,在这种配置下,当命令 â€˜-setPolicy’没有指定策略名称的参数时,默认的策略将会被使用。

            é»˜è®¤æƒ…况下,参数 â€˜dfs.namenode.ec.system.default.policy’ 的值为“RS-6-3-k”,使用Reed-Solomon和XOR实现的编解码器可以使用客户端和DataNode节点指定如下的关键字配置:io.erasurecode.codec.rs.rawcoders用来指定默认的RS编解码器,io.erasurecode.codec.rs-legacy.rawcoders用于指定legacy RS编解码器,io.erasurecode.codec.xor.rawcoders用于指定XOR编解码器;用户也可以使用类似关键字io.erasurecode.codec.self-defined-codec.rawcoders来配置自定义的编解码器。这些关键字的值是带有回退机制的编码器名称的列表。这些编解码器工厂以指定的配置的值有序的被加载,直到一个编解码器被成功的加载,默认的RS和XOR编解码器配置更喜欢本地实现,而不是纯java实现;RS-LEGACY没有本地编解码器实现,因此默认的只能是纯java的实现;所有这些编解码器都有纯java的实现;对于默认的RS编解码器,它也有一个本地实现,利用英特尔 ISA-L库提高编解码器性能;对于XOR编解码器,也支持利用英特尔 ISA-L库提升编解码的性能的本地实现;请参阅“Enable Intel ISA-L”获取更详细的信息。默认的RSLegacy的实现是纯java的,默认的RS和XOR是使用了因特尔ISA-L库本地实现的,在DataNodes上的纠删码后台恢复工作也可以使用下面的参数被调优:

             1) dfs.datanode.ec.reconstruction.stripedread.timeout.millis --条带读取超时时间,默认值 ms

             2) dfs.datanode.ec.reconstruction.stripedread.buffer.size --读取服务的缓存大小,默认值 K

             3) dfs.datanode.ec.reconstruction.threads -- DataNode用于后台重构工作的线程数量,默认值 8 个线程

             4) dfs.datanode.ec.reconstruction.xmits.weight -- 与副本块恢复 相比,EC后台恢复任务使用的xmits 的相对权重,默认值0.5,设置它的值为0去禁用计算EC恢复任务的权重,也就是说,EC任务总是1 xmits。通过计算出读数据流的数量和写数据流的数量的最大值来计算出纠删码恢复任务的xmits。例如,如果一个EC恢复任务需要从6个节点读取数据,往2个节点写入数据,它拥有的 xmits 是max(6, 2) * 0.5 = 3,复制文件的恢复任务总是计算为1xmit,NameNode利用dfs.namenode.replication.max-streams减去DataNode上总的xmitsInProgress(合并来自副本文件和EC文件的xmits) ï¼Œä»¥ä¾¿è°ƒåº¦æ¢å¤ä»»åŠ¡åˆ°è¿™ä¸ªDataNode。

            HDFS利用因特尔ISA-L库去提高默认的RS本地实现的编解码器的编解码计算速度,开启并使用英特尔ISA-L库,需要3步:

                1)构建ISA-L库,请参阅官方的网站 â€œ /org/isa-l/ ” 获取详情信息。

                2)构建带有ISA-L支持的Hadoop,请参阅源码中BUILDING.txt文件中的 â€œBuild instructions for Hadoop”中的“Intel ISA-L build options”部分。

                3)使用-Dbundle.isal拷贝 isal.lib ç›®å½•ä¸­çš„内容到最终的tar文件中。

            ä½¿ç”¨è¯¥tar文件部署Hadoop,确保ISA-L是在HDFS客户端和DataNodes端是可用的。为了验证ISA-L能够被Hadoop正确的检测到,运行命令  hadoop checknative来验证。

            HDFS提供了EC的子命令用于执行纠删码相关的管理命令。

            hdfs ec [generic options] [-setPolicy -path <path> [-policy <policyName>] [-replicate]] [-getPolicy -path <path>] [-unsetPolicy -path <path>] [-listPolicies] [-addPolicies -policyFile <file>] [-listCodecs] [-enablePolicy -policy <policyName>] [-disablePolicy -policy <policyName>] [-help [cmd ...]]

           ä¸‹é¢æ˜¯å…³äºŽæ¯ä¸ªå‘½ä»¤çš„详情:

            [-setPolicy -path <path> [-policy <policyName>] [-replicate]]

            åœ¨æŒ‡å®šçš„目录的路径上设置纠删码策略。

            path:HDFS中的目录,这是一个强制的参数,设置一个策略只影响新创建的文件,不影响已经存在的文件。

            policyName:在这个目录下的文件上使用的纠删码策略,如果配置了参数‘dfs.namenode.ec.system.default.policy’,这个参数可以被省略,这时路径的EC策略将会被设置成配置文件中的默认值。

            -replicate:在目录上应用指定的REPLICATION策略,强制目录采用3副本复制方案。

            -replicate å’Œ-policy <policyName>是可选的参数,它们不能同时被指定。

            [-getPolicy -path <path>]

            èŽ·å–在指定路径上目录或者文件的纠删码策略的详情。

            [-unsetPolicy -path <path>]

            å–消之前使用setPolicy åœ¨ç›®å½•ä¸Šè®¾ç½®çš„纠删码策略。如果目录是从祖先中继承的纠删码策略,unsetPolicy æ˜¯ä¸€ä¸ªç©ºæ“ä½œï¼Œå³åœ¨æ²¡æœ‰æ˜Žç¡®è®¾ç½®ç­–略的目录上取消策略将不会返回错误。

            [-listPolicies ]

            åˆ—出所有在HDFS中注册的纠删码策略,只有启用的策略才能使用setPolicy å‘½ä»¤ã€‚

            [-addPolicies -policyFile <file>]

            æ·»åŠ ä¸€ä¸ªçº åˆ ç ç­–略的列表,请参阅模板策略文件etc/hadoop/user_ec_policies.xml.template,最大的条带单元大小被定义在属性 â€˜dfs.namenode.ec.policies.max.cellsize’ 中,默认值是4MB,当前的HDFS中总共允许用户添加个策略,被添加的策略ID的范围是~,如果已经有个策略被添加,再添加策略将会失败。

            [-listCodecs]

            èŽ·å–系统中支持的纠删码编解码器和coder列表。一个coder是一个编解码器的实现,一个编解码器可以有不同的实现,因此会有不同的coder,编解码器的coders采用后备的顺序被列出。

            [-removePolicy -policy <policyName>]

            ç§»é™¤ä¸€ä¸ªçº åˆ ç ç­–略。

            [-enablePolicy -policy <policyName>]

            å¯ç”¨ä¸€ä¸ªçº åˆ ç ç­–ç•¥

            [-disablePolicy -policy <policyName>]

            ç¦ç”¨ä¸€ä¸ªçº åˆ ç ç­–略。

            ç”±äºŽå¤§é‡çš„技术挑战,在纠删码文件上不支持某些HDFS的写操作,比如hflush, hsync å’Œappend操作。

            åœ¨çº åˆ ç æ–‡ä»¶ä¸Šä½¿ç”¨append()将会抛出IOException。

            åœ¨DFSStripedOutputStream ä¸Šæ‰§è¡Œhflush() å’Œhsync()是空操作,因此,在纠删码文件上调用hflush() æˆ–者hsync()不能保证数据被持久化。

            å®¢æˆ·ç«¯å¯ä»¥ä½¿ç”¨ StreamCapabilities  æä¾›çš„API去查询一个OutputStream æ˜¯å¦æ”¯æŒhflush() å’Œhsync(),如果客户端渴望数据通过hflush() å’Œhsync()持久化,当前的补救措施是在非纠删码目录中创建3副本文件,或则使用FSDataOutputStreamBuilder#replicate()提供的API在纠删码目录中创建3副本文件。

Alluxio 客户端源码分析

       Alluxio是一个用于云分析和人工智能的开源数据编排技术,作为分布式文件系统,采用与HDFS相似的主从架构。系统中包含一个或多个Master节点存储集群元数据信息,以及Worker节点管理缓存的数据块。本文将深入分析Alluxio客户端的互通传奇源码实现。

       创建客户端逻辑在类alluxio.client.file.FileSystem中,简单示例代码如下。

       客户端初始化包括调用FileSystem.Context.create创建客户端对象的上下文,在此过程中需要初始化客户端以创建与Master和Worker连接的连接池。若启用了配置alluxio.user.metrics.collection.enabled,将启动后台守护线程定时与Master节点进行心跳传输监控指标信息。同时,客户端初始化时还会创建负责重新初始化的后台线程,定期从Master拉取配置文件的哈希值,若Master节点配置发生变化,则重新初始化客户端,期间阻塞所有请求直到重新初始化完成。

       创建具有缓存功能的客户端在客户端初始化后,调用FileSystem.Factory.create进行客户端创建。客户端实现分为BaseFileSystem、MetadataCachingBaseFileSystem和LocalCacheFileSystem三种,其中MetadataCachingBaseFileSystem和LocalCacheFileSystem对BaseFileSystem进行封装,提供元数据和数据缓存功能。BaseFileSystem的调用主要分为三大类:纯元数据操作、读取文件操作和写入文件操作。针对元数据操作,直接调用对应GRPC接口(例如listStatus)。接下来,将介绍客户端如何与Master节点进行通信以及读取和写入的流程。

       客户端需要先通过MasterInquireClient接口获取主节点地址,当前有三种实现:PollingMasterInquireClient、SingleMasterInquireClient和ZkMasterInquireClient。其中,PollingMasterInquireClient是群控源码搭建针对嵌入式日志模式下选择主节点的实现类,SingleMasterInquireClient用于选择单节点Master节点,ZkMasterInquireClient用于Zookeeper模式下的主节点选择。因为Alluxio中只有主节点启动GRPC服务,其他节点连接客户端会断开,PollingMasterInquireClient会依次轮询所有主节点,直到找到可以连接的节点。之后,客户端记录该主节点,如果无法连接主节点,则重新调用PollingMasterInquireClient过程以连接新的主节点。

       数据读取流程始于BaseFileSystem.openFile函数,首先通过getStatus向Master节点获取文件元数据,然后检查文件是否为目录或未写入完成等条件,若出现异常则抛出异常。寻找合适的Worker节点根据getStatus获取的文件信息中包含所有块的信息,通过偏移量计算当前所需读取的块编号,并寻找最接近客户端并持有该块的Worker节点,从该节点读取数据。判断最接近客户端的Worker逻辑位于BlockLocationUtils.nearest,考虑使用domain socket进行短路读取时的Worker节点地址一致性。根据配置项alluxio.worker.data.server.domain.socket.address,判断每个Worker使用的domain socket路径是否一致。如果没有使用域名socket信息寻找到最近的Worker节点,则根据配置项alluxio.user.ufs.block.read.location.policy选择一个Worker节点进行读取。若客户端和数据块在同一节点上,则通过短路读取直接从本地文件系统读取数据,否则通过与Worker节点建立GRPC通信读取文件。

       如果无法通过短路读取数据,客户端会回退到使用GRPC连接与选中的试用试客源码Worker节点通信。首先判断是否可以通过domain socket连接Worker节点,优先选择使用domain socket方式。创建基于GRPC的块输入流代码位于BlockInStream.createGrpcBlockInStream。通过GRPC进行连接时,每次读取一个chunk大小并缓存chunk,减少RPC调用次数提高性能,chunk大小由配置alluxio.user.network.reader.chunk.size.bytes决定。

       读取数据块完成后或出现异常终止,Worker节点会自动释放针对该块的写入锁。读取异常处理策略是记录失败的Worker节点,尝试从其他Worker节点读取,直到达到重试次数上限或没有可用的Worker节点。

       若无法通过本地Worker节点读取数据,则客户端尝试发起异步缓存请求。若启用了配置alluxio.user.file.passive.cache.enabled且存在本地Worker节点,则向本地Worker节点发起异步缓存请求,否则向负责读取该块数据的Worker节点发起请求。

       数据写入流程首先向Master节点发送CreateFile请求,Master验证请求合法性并返回新文件的基本信息。根据不同的写入类型,进行不同操作。如果是THROUGH或CACHE_THROUGH等需要直接写入底层文件系统的写入类型,则选择一个Worker节点处理写入到UFS的数据。对于MUST_CACHE、CACHE_THROUGH、ASYNC_THROUGH等需要缓存数据到Worker节点上的写入类型,则打开另一个流负责将每个写入的块缓存到不同的Worker上。写入worker缓存块流程类似于读取流程,若写入的Worker与客户端在同一个主机上,则使用短路写直接将块数据写入Worker本地,无需通过网络发送到Worker上。数据完成写入后,客户端向Master节点发送completeFile请求,表示文件已写入完成。

       写入失败时,取消当前流以及所有使用过的输出流,删除所有缓存的块和底层存储中的数据,与读取流程不同,写入失败后不进行重试。

       零拷贝实现用于优化写入和读取流程中WriteRequest和ReadResponse消息体积大的问题,通过配置alluxio.user.streaming.zerocopy.enabled开启零拷贝特性。Alluxio通过实现了GRPC的MethodDescriptor.Marshaller和Drainable接口来实现GRPC零拷贝特性。MethodDescriptor.Marshaller负责对消息序列化和反序列化的抽象,用于自定义消息序列化和反序列化行为。Drainable扩展java.io.InputStream,提供将所有内容转移到OutputStream的方法,避免数据拷贝,优化内容直接写入OutputStream的过程。

       总结,阅读客户端代码有助于了解Alluxio体系结构,明白读取和写入数据时的数据流向。深入理解Alluxio客户端实现对于后续阅读其他Alluxio代码非常有帮助。

从线上某应用多作业并发创建同一HIVE表分区偶现失败问题聊起-深度剖析下HIVE创建表分区的内部逻辑

       在大数据领域,早期版本的原生HIVE由于缺乏锁和事务机制,不支持并发写操作。多作业并发创建同一表分区或写数据到同一表分区时,易遇报错或数据不一致问题。HIVE1.X版本开始加强事务和锁支持,大幅降低并发写问题。实践中,避免同一表分区的并发写以确保应用一致性。本文分享线上多作业并发写同一表分区时报错问题,提供解决方法。

       公司内部使用数据同步工具datago,用于增强datax并自动清理表分区、创建表分区。在使用星环TDH平台时,某客户生产环境在多分片并发采集时,datago作业运行失败。问题偶发,需查明底层原因及优化措施。具体报错为HDFS目录不存在。

       问题出现在datago采集作业初始化阶段,涉及自动清理旧文件和自动创建表分区配置。异常堆栈与datago源码分析揭示问题原因。解决策略需避免并发创建同一表分区,并避免创建时list分区目录文件。由于无法调整HIVE表分区创建逻辑,需在自动创建表分区上进行调整。

       本文深入剖析HIVE创建表分区内部逻辑,提供解决问题的思路。对HIVE源码感兴趣者可进一步探索相关方法。

要成为一名专业的程序员,从零开始需要怎么一步步来比较好,要把最底层的先学精通吗?(个人认为)求学长

       前言

       你是否觉得自己从学校毕业的时候只做过小玩具一样的程序?走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发,作业项目都看不出有什么实际作用,不如从工作中的需求出发)

       建议:

       不要乱买书,不要乱追新技术新名词,基础的东西经过很长时间积累而且还会在未来至少年通用。

       回顾一下历史,看看历史上时间线上技术的发展,你才能明白明天会是什么样。

       一定要动手,例子不管多么简单,建议至少自己手敲一遍看看是否理解了里头的细枝末节。

       一定要学会思考,思考为什么要这样,而不是那样。还要举一反三地思考。

       注:你也许会很奇怪为什么下面的东西很偏Unix/Linux,这是因为我觉得Windows下的编程可能会在未来很没有前途,原因如下:

       现在的用户界面几乎被两个东西主宰了,1)Web,2)移动设备iOS或Android。Windows的图形界面不吃香了。

       越来越多的企业在用成本低性能高的Linux和各种开源技术来构架其系统,Windows的成本太高了。

       微软的东西变得太快了,很不持久,他们完全是在玩弄程序员。详情参见《Windows编程革命史》

       所以,我个人认为以后的趋势是前端是Web+移动,后端是Linux+开源。开发这边基本上没Windows什么事。

       启蒙入门

       1、 学习一门脚本语言,例如Python/Ruby

       可以让你摆脱对底层语言的恐惧感,脚本语言可以让你很快开发出能用得上的小程序。实践项目:

       处理文本文件,或者csv (关键词 python csv, python open, python sys) 读一个本地文件,逐行处理(例如 word count,或者处理log)

       遍历本地文件系统 (sys, os, path),例如写一个程序统计一个目录下所有文件大小并按各种条件排序并保存结果

       跟数据库打交道 (python sqlite),写一个小脚本统计数据库里条目数量

       学会用各种print之类简单粗暴的方式进行调试

       学会用Google (phrase, domain, use reader to follow tech blogs)

       为什么要学脚本语言,因为他们实在是太方便了,很多时候我们需要写点小工具或是脚本来帮我们解决问题,你就会发现正规的编程语言太难用了。

       2、 用熟一种程序员的编辑器(不是IDE) 和一些基本工具

       Vim / Emacs / Notepad++,学会如何配置代码补全,外观,外部命令等。

       Source Insight (或 ctag)

       使用这些东西不是为了Cool,而是这些编辑器在查看、修改代码/配置文章/日志会更快更有效率。

       3、 熟悉Unix/Linux Shell和常见的命令行

       如果你用windows,至少学会用虚拟机里的linux, vmware player是免费的,装个Ubuntu吧

       一定要少用少用图形界面。

       学会使用man来查看帮助

       文件系统结构和基本操作 ls/chmod/chown/rm/find/ln/cat/mount/mkdir/tar/gzip …

       学会使用一些文本操作命令 sed/awk/grep/tail/less/more …

       学会使用一些管理命令 ps/top/lsof/netstat/kill/tcpdump/iptables/dd…

       了解/etc目录下的各种配置文章,学会查看/var/log下的系统日志,以及/proc下的系统运行信息

       了解正则表达式,使用正则表达式来查找文件。

       对于程序员来说Unix/Linux比Windows简单多了。(参看我四年前CSDN的博文《其实Unix很简单》)学会使用Unix/Linux你会发现图形界面在某些时候实在是太难用了,相当地相当地降低工作效率。

       4、 学习Web基础(HTML/CSS/JS) + 服务器端技术 (LAMP)

       未来必然是Web的世界,学习WEB基础的最佳网站是W3School。

       学习HTML基本语法

       学习CSS如何选中HTML元素并应用一些基本样式(关键词:box model)

       学会用 Firefox + Firebug 或 chrome 查看你觉得很炫的网页结构,并动态修改。

       学习使用Javascript操纵HTML元件。理解DOM和动态网页(Dynamic HTML: The Definitive Reference, 3rd Edition - O'Reilly Media) 网上有免费的章节,足够用了。或参看 DOM 。

       学会用 Firefox + Firebug 或 chrome 调试Javascript代码(设置断点,查看变量,性能,控制台等)

       在一台机器上配置Apache 或 Nginx

       学习PHP,让后台PHP和前台HTML进行数据交互,对服务器相应浏览器请求形成初步认识。实现一个表单提交和反显的功能。

       把PHP连接本地或者远程数据库 MySQL(MySQL 和 SQL现学现用够了)

       跟完一个名校的网络编程课程(例如:(升级版为Kyoto Cabinet)、Flare、MongoDB、CouchDB、Cassandra、Voldemort等。