短链服务

       发布一个简单的短链服务,也可用于加密。使用方法,dj1211.com:8899/?word=www.youtube.com    word后面参数是链接,随后返回一个链接 www.dj1211.com:8899/88r ,发给别人,自动跳转。

Hadoop-pipes 编译 Native报错问题

近期编译Hadoop native代码发现,由于内核版本升级,导致了编译失败,失败的module是hadoop-pipes。编译的命令式 mvn clean package -Pnative -DskipTests。发现了大量的如下错误

[exec] /usr/bin/c++ -g -Wall -O2 -D_REENTRANT -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fPIC CMakeFiles/pipes-sort.dir/main/native/examples/impl/sort.cc.o -o examples/pipes-sort -rdynamic libhadooppipes.a libhadooputils.a -lssl -lpthread
[exec] /usr/bin/cmake: /usr/lib64/libcrypto.so.10: no version information available (required by /usr/lib64/libssl.so.10)
[exec] /usr/bin/cmake: /usr/lib64/libcrypto.so.10: no version information available (required by /usr/lib64/libssl.so.10)
[exec] /usr/bin/cmake: /usr/lib64/libcrypto.so.10: no version information available (required by /usr/lib64/libssl.so.10)
[exec] /usr/bin/cmake: /usr/lib64/libcrypto.so.10: no version information available (required by /usr/lib64/libssl.so.10)
[exec] make[2]: Leaving directory /data0/jiangyu2/compile/201504/hadoop-tools/hadoop-pipes/target/native'
[exec] make[1]: Leaving directory
/data0/jiangyu2/compile/201504/hadoop-tools/hadoop-pipes/target/native’
[exec] /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../lib64/libssl.so: undefined reference to `OPENSSL_init_library@libcrypto.so.10′

      看了下是缺少libcrypto,为解决这一问题,修改$HADOOP_PIPES/src/CMakeLists.txt,修改后加入一行加入如下即可解决。

target_link_libraries(hadooppipes
${OPENSSL_LIBRARIES}
pthread
+ crypto
)

 

OLAP实践(一) CrushJoin系统介绍

一、系统背景

      最近一段时间,我与同事liangjun(http://blog.csdn.net/hit_hlj_sgy)一直在对OLAP系统进行一些调研、开发以及将相应的系统在Sina weibo数据中的使用进行推广。在这一过程中,我们有一些经验,开发了一些实用的组件或系统,近期会进行一些分享。

      这篇blog主要介绍我们上个月完成的CrushJoin系统,工程名称揭示了它产生的意义,就是尽量减少join操作对集群数据,尤其是某些表进行反复、重复的扫描。它的背景如下:对于weibo中用户数据,每个用户由一个uid对应,同时用户有很多属性,包括他的年龄、省份、注册时间、性别、兴趣、用户活跃度、用户质量等等,经过整理以后发现总共有多达100+的属性,这些属性分布在10几张hive表中。非常重要的一种场景是数据分析师需要对用户的属性进行ad-hoc查询,比如我们想要知道在北京的用户中他的年龄构成如何,或者说我们要分析上海用户中年龄是40-50岁的用户是长期登陆的用户占上海用户中的总量多少。目前为止,现有的做法是根据需要的属性将多个表进行join,join的键为刚才提到的uid。这种方法的问题非常多,首先是ad-hoc查询需要尽快的查询时间,而通过hive转化为mr查询的方式在时间上根本无法做到实时,用户从提交查询到最后获得结果一般都需要十几甚至几十分钟,join的较多时候甚至是以小时为单位才能够查询出来。第二,这种查询都会join用户基础表,每次查询都需要扫描用户基础表将会十分浪费。

      为此,我们希望设计一套系统,能够提供给用户秒级的查询速度,满足用户对任意维度的属性进行join和in操作。这套系统准确的说不能算严格意义上的OLAP系统,因为传统意义上的OLAP分为维度(dimensions)+度量(metrics),要对多种维度进行join,groupby操作,获得相应的度量。这套系统借鉴了OLAP系统中的一些结构,更准确的叫法应该是多维filter系统。


二、相关知识

      下面我们来看一下用于这套系统的基本知识:

      1、bitmap

      bitmap也可称作bitset,是由0或者1构成的bit数组,如下图:

         Crush1

 

      其中每一位都是一个位移(offset),对bitmap的操作有AND,OR,XOR等等,因为所有操作都是按位运算,所以运算速度异常迅速。

 

      如果我们将用户的uid映射为bitmap中的一位,这样我们的count计数就转换为bitmap对应位为1的个数。就比如上图,我们可以计算出具有某种属性的用户为4。如果我们需要获得具有两个及以上的属性和,那么就将对应的bitmap进行按位与(AND)操作即可,如下图

        Crush2

      两个对应属性AND后,可以计算出满足这两个属性的用户数为2,以此类推。

      2、全排序

      我们知道,mapreduce的特性是在reduce端按key排序,但是,这种排序不是全局性的,而使用bitmap需要对全局uid进行排序,所以我们需要进行一次全排序。为此我们估算总共的用户,以及每个reduce需要的用户。这需要两步,首先是分析阶段,需要根据reduce个数,将总共的用户进行采样,确定每个reduce需要处理的uid下限和上限。第二步就是根据第一步的结果,使用TotalOrderPartitioner以及提供采样文件,就可以做到reducer之间有序,reducer内部也是有序的全排序。具体细节可以查询TotalOrderPartitioner,当然这步我们是做了一些修改。


三、系统设计与流程

      我们将所有的bitmap存储在Hbase中,Hbase表的设计为,在全排序获得的UID范围为key, columnFamily为1,column是排序好的属性,其中属性名称与int做了一个映射,所以column是1、2、3….等,value对应了该UID范围reduce计算好的各个属性的bitmap进行序列化的结果。

      Hbase建表的时候我们就根据reduce计算生成的文件设置好region数,这里的region数设置为200个,主要是方便我们查询时候使用Coprocessor,提升查询的并发性和速度。同时,这里需要特别说的是,bitmap的实现有多种,比如java原生的实现,但是如果数据量过大,即使是按位运算数据量也不能忽视,尤其是我每个reduce根据属性个数大概是150+的属性,每个属性生成一个bitmap,并存储在hbase中,数据量非常大。这里我们使用了Roaringbitmap,他的地址是https://github.com/lemire/RoaringBitmap,目前很多开源的OLAP项目都使用它,比如Druid。我们目前测试的效果,根据你的bitmap稀疏程度,RoaringBitmap基本上都能压缩几百甚至上千倍,并且计算更快,非常方便。

系统的流程如下:

                   Crush3

      1、系统每天更新一次,首先使用mr任务,将所有表对应的属性按照全排序,分布到对应的reduce端,reduce端根据属性值对每个属性生成一个bitmap,同时写入HFile中。

      2、HFile生成完成后,将HFile distcp到我们的Hbase集群中,通过bulkload将数据导入

      3、后端是个Jetty Server,用户查询通过Jetty Server,转换为对Hbase的查询,查询使用Coprocessor

      4、Hbase将Coprocessor结果返回给Jetty,Jetty立即将用户数量返回给用户,同时异步的将对应的UIDs写入到一个文件,方便用户查询

 

     经过我们的测试,查询10个属性总共需要600ms,将原先离线的join,转化为实时查询,完成了我们的目的。

2015年6月23日重启失败原因及解决方案

一、现象描述

      2015年6月23日由于NameNode设置的内存快要达到现有元数据使用内存的上限,为了增加内存jvm 参数,对NameNode进行了重启,为了保证业务不受影响,采用了fail over的方式。

      首先切换ns1 nn1为Standby NameNode,然后切换ns1 nn2 为Active NameNode,时间在16:50分左右,之后用户的操作基本正常,随后重启ns1 nn1并将堆内存调至100G,在18:13分左右将ns1 nn2切换为Standby NameNode,将ns1 nn1重新切换为Active NameNode。但是,在这一切换过程中,nn2的切换没有成功,直接被kill掉,随后nn1切换为Active NameNode,但是用户的响应非常慢,jstack后定位了相应的问题后,随后打开了debug日志,发现了大量的如下日志:

      BLOCK* rescanPostponedMisreplicatedBlocks: Re-scanned block ****, result is POSTPONE

      查看了代码路径发现了是每个磁盘的Block Report之后都会扫描这个结构,当时postpone结构里有70万个block,相当于每台机器block report都要扫70万*12(磁盘数)的block,并且还要从blockMap中进行查询,相当费时,甚至一个blockreport要到几秒级别,严重占据了写锁,导致了用户响应极慢。

      为了解决这一问题,我们重启了NameNode和DataNode,每次重启100台DataNode,但是这次遇到的是Java GC 风暴,最后的解决是每次重启25台,起了相当长时间才启动完成。

 

二、问题原因

      出现这一问题不是单一一个原因导致的,是多个因素混杂在一起触发了这一严重的问题。

      (一)POSTPONE问题

       前面已经说明每次Block Report都会扫描postpone结构,如果里面block过多就会导致了响应变慢。Block放入postpone结构的原因如下。

      首先看一下fail over的代码路径和行为:

      1、ns1 fail over到ns2后,ns2会将所有DataNode标记为stale状态,处于stale状态的

      2、处于stale状态storage的blocks无法删除,只能放到postpone结构中,等到DataNode标记不是stale状态后,才会从postpone结构去掉,放到invalidate结构中,等待heartbeat到来删除

Bug1

      3、然而由于代码的问题,fail over后重启的NameNode即nn1需要两次block report才能将datanode storageinfo状态置为正常状态。代码如下:

Bug2

      首先,重启nn后所有的状态都是false,对于DataNode,向NameNode发送心跳后会得到reregister的命令,stale状态改变需要heartbeat进行过一次,同时blockreport进行过一次,然而,reregister首先会进行blockreport,随后才会进行heartbeat,导致了第一次blockreport不会将stale状态恢复,由于我们集群blockreport时间设置为6个小时,这就导致了6个小时postpone不断增加。

      4、POSTPONE block产生的原因

      有如下几个原因产生了POSTPONE:

      (1)balancer导致的,由于balancer过后要invalidate多余的block,但是处于postpone无法删除

      (2)随着Block report的时间由于postpone block过多导致的增长,会有个别DataNode由于心跳汇报原因超时,导致了NameNode replicate对应的blocks,心跳正常后这些blocks就处于POSTPONE队列中

      (3)错误的将之前已经停机的DataNode重启,新加入的blocks基本上都添加到了postpone结构中

      5、除此之外在failover过程中有一次大的删除操作,fail over到nn1后,nn1有大量的BLOCK* processReport: block**** on node**** size**** does not belong to any file. 日志,这条日志是在写锁中,大概将近百万,也会加重占写锁的时间

      (二)Block Report GC Storm问题

      随后在重启NameNode和DataNode的过程中,我们遇到的是另一个问题,被叫做Block Report GC风暴。虽然将NameNode内存设置为100G,但是如果DataNode基本在同一时间内进行BlockReport,势必将新生代很快占满,随后将新生代移入老年代后failed,进行一次非常长的full gc,日志如下:

Bug3

Bug4

      GC时间接近400秒,甚至到500秒,这样的时间会导致dn的block report和hearbeat超时,超时后直接重试引起了接近雪崩效应的现象。

 

三、问题解决

      (一)POSTPONE问题

      引入如下patch,解决postpone问题:

      1、https://issues.apache.org/jira/browse/HDFS-7980IBR在NN重启后没有进入快速加块代码路径

      2、https://issues.apache.org/jira/browse/HDFS-7503blockreport中在锁中如果之前删除大目录,会打大量的日志

      3、https://issues.apache.org/jira/browse/HDFS-6772DataNode reregister逻辑问题导致的content stale 持续两个block report

      4、https://issues.apache.org/jira/browse/HDFS-6425Postpone逻辑移除出BR,而在后台进行

      5、https://issues.apache.org/jira/browse/HDFS-6830blockInfo逻辑问题导致的删除indoe而出现的npe异常

 

     (二)Block Report GC storm问题

     1、根据统计每个磁盘大概5万个块的Block Report时间大概为50msec,一台机器大概0.6s,对于我们1000台机器设置每台机器的随机延时时间为0.6*1000=600s=10min即可

     2、配置ipc.server.read.threadpool.size 为10,是Server rpc reader线程变为10个

     3、配置dfs.namenode.servicerpc-address 将client与NN的rpc请求与DN与NN的请求进行分离,虽然可能对这次没有太多的帮助,但是据其它公司测试,性能大概提升20%

近期值得关注的patch-hdfs层

    最近对namenode做了次failover,简直是惨痛的经历,稍后会补充细节,以下列出hdfs层近期值得关注的patch,如果版本没有达到2.6+,请打如下patch。

 

https://issues.apache.org/jira/browse/HDFS-7980

https://issues.apache.org/jira/browse/HDFS-7503

https://issues.apache.org/jira/browse/HDFS-6833

https://issues.apache.org/jira/browse/HDFS-6772

https://issues.apache.org/jira/browse/HDFS-6425       

https://issues.apache.org/jira/browse/HDFS-6830

       

Kylin安装文档

    最近在接触OLAP相关领域。以下为Kylin安装过程。

    基线版本选用的是0.7.1,github地址是 https://github.com/KylinOLAP/Kylin/tree/0.7.1

    官方安装文档地址是 https://github.com/KylinOLAP/Kylin/wiki/On-Hadoop-CLI-installation.官方binary包地址在首页提供下载。

    Kylin默认使用的是Hadoop 2.2,Hbase 0.98,hive 0.14。binary中打出的jar包全部是基于这些版本。而按照官方安装文档,执行script/package.sh脚本后生成的war包缺少很多页面,所以安装与官方文档略有不同。

    1、下载Kylin源码包,修改pom.xml,将Hadoop版本改为Hadoop 2.4,Hbase改为1.0,Hive改为0.13。

    2、安装npm,在打包过程中会使用

    3、由于Hbase1.0相对于0.98有api改动,会报错,错误为 

Kylin

    修改Kylin代码中的HBaseConnection.class将connection的获取过程改为

    connection =  (ClusterConnection) ConnectionFactory.createConnection(conf); 并修改相应的数据结构。

    4、随后使用script/package.sh打包。打出tomcat部署的war包,位置在/server/target/目录下,将binary包中相应的jar包替换为打出的jar包,主要是以kylin开头的所有jar包

    5、启动tomcat前首先修改hadoop classpath 将$HADOOP_HOME/etc/hadoop/hadoop-env.sh 中capacity jar包去掉,否则kylin启动时会读取hadoop环境,去获取jar包,缺少jar包而无法启动

    6、修改conf/kylin_job_conf.xml,作为任务的通用模板,其中加入rm地址,用于http获取job信息

    <property>

        <name>yarn.resourcemanager.webapp.address</name>

        <value>yz543.hadoop.data.sina.com.cn:9008</value>

    </property>

    7、在跑任务之前需要重新编译hcatalog项目,位置在hive源码包中hcatalog目录下,首先修改hive pom.xml,修改以下两行

    <hadoop-23.version>2.4.0</hadoop-23.version>

    <hbase.hadoop2.version>1.0.0</hbase.hadoop2.version>

    在hcatalog目录下,mvn打包 mvn clean package -DskipTests -Phadoop-2,将hive-catalog*.jar 除了test以外的分发到集群中各个节点,同时分发hive-exec-0.13.0.jar和hive-metastore-0.13.0.jar包。用于mr任务使用。

    8、在Kylin的服务器上加入KYLIN_HOME,PATH等环境变量

    export KYLIN_HOME=/usr/local/Kylin-0.7.1

    export PATH=$KYLIN_HOME/bin:$PATH

    9、需要修改Kylin的启动脚本bin/find-hive-dependency.sh

    10、启动kylin kylin.sh start

    停止kylin  kylin.sh stop

网站改变策略

      最近仍然发现推酷恶意收录我的blog内容,已经发送邮件通知,同时对本blog所有feed禁止,防止向推酷一样臭不要脸的过来偷东西。知识是可以分享的,但是你拿我的东西去卖钱就说不过去了吧。