据业内预测,2012年二维码市场规模将达到300亿元,到了2015年,二维码市场将超过1000亿元,会有一万家公司进入二维码行业。
二维码,区别于常见的条形码(一维码),是用特定的几何图形按一定规律在平面(水平、垂直二维方向上)记录数据信息,看上去像一个由双色图形相 间组成的方形迷宫。二维码信息容量大,比普通条码信息容量约高几十倍。同时,二维码误码率不超过千万分之一,比普通条码低很多。另外,二维码编码范围广, 可把图片、声音、文字、签字、指纹等可数字化的信息进行编码,易制作,成本低,持久耐用。
目前在日、韩等国家,二维码应用已非常普遍,普及率高达96%以上。早在2006年,国内就开始二维码的商业应用,但由于当时智能手机在并不普 及,第一轮的二维码产业并没有真正形成。2012年成为了中国的二维码元年,据统计,目前全国每月扫码量超过1.6亿次,移动运营商、IT巨头已经抢得先机。
如此神速发展的二维码,究竟可以应用在哪些方面呢?二维码的应用,可以分为主读和被读,被读类应用是以手机等存储二维码作为电子交易或支付的凭 证,可用于电子商务、消费打折等。主读类应用是以安装识读二维码软件的手持工具(包括手机),识读各种载体上的二维码,可用于防伪溯源、执法检查等。下面 初步枚举了二维码的20项应用模式。
1. 网上购物,一扫即得
国内的二维码购物最早起源于一号店。目前国内一些大城市的地铁通道里,已经有二维码商品墙,消费者可以边等地铁边逛超市,看中 哪个扫描哪个,然后通过手机支付,直接下单。如果是宅在家里,家里的米、面、油、沐浴露用完了,只要拿起包装,对着商品的二维码一扫,马上可以查到哪里在 促销、价格是多少,一目了然。而且,通过二维码购物,产品的二维码直接标示了产品的身份证,扫描后调出的产品真实有效,保障了购物安全。将来,二维码加上 O2O(网上到网下),实体店将变成网购体验店。因此,实体店可能更多的是要设在顾客方便的地方如公交站甚至是居民区,而不是商业中心。
2. 消费打折,有码为证
凭二维码可享受消费打折,是目前业内应用最广泛的方式。比如,商家通过短信方式将电子优惠券、电子票发送到顾客手机上,顾客进 行消费时,只要向商家展示手机上的二维码优惠券,并通过商家的识读终端扫码、验证,就可以得到优惠。去年7月,海南蕉农在香蕉滞销时,与淘宝合作进行网上 团购促销,网友在网上预订,网下凭手机二维码提货,成功化解香蕉危机。今年9月,在成都春熙路上的钟表文化节中,依波表举办了限时扫码活动,在规定的时间 内在现场扫描二维码折扣,顾客就能以折扣价买走手表。目前,腾讯也推出了针对IPhone和安卓的微信会员卡,会员只需用手机扫描商家的二维码,就能获得 一张存储于微信中的电子会员卡,享受折扣服务。
3. 二维码付款,简单便捷
近日,支付宝公司宣布推出二维码收款业务,所有支付宝用户均可免费领取“向我付款”的二维码,消费者只需打开手机客户端的扫 码功能,拍下二维码, 即可跳转至付款页面,付款成功后,收款人会收到短信及客户端通知。在福州,有一家华威出租车公司开通了支付宝,打车到目的地后,顾客拿出手机,对车内的二 维码车贴扫描,手机自动跳转到支付页面,然后按照计价器上的车费输入金额,整个付款过程只要20多秒。在星巴克,可以把预付卡和手机绑定,通过扫二维码可 以快捷支付,不用再排长队付款。
4. 资讯阅读,实现延伸
过去,报纸、电视以及其他媒体上的内容,限于媒体介质的特性,是静态的,无法延伸阅读,但是,二维码出现以后,颠覆了这种界 限,实现了跨媒体阅读。比如,在报纸上某则新闻旁边放一个二维码,读者扫描后可以阅读新闻的更多信息,如采访录音、视频录像、图片动漫等。如《骑车游北京》一书便设置了二维码,过手机扫描即可快速登录书中所述网址,可以实现图书、手机上网的时时互动。另外,户外广告、单页广告都可以加印二维码,感兴趣的客户只要用手机一扫,即可快速了解更详细内容,甚至与广告主互动。
5. 二维码管理生产,质量监控有保障
条码在产品制造过程中应用已非常普遍。二维码因为可以存储更多信息,因此,在产品制造过程应用更为深入。比如,在 汽车制造中,DPM二维码(直接零部件标刻二维码,可用针式打标机、激光打标机、喷码机甚至化学蚀刻)技术现已在美国汽车行业得到广泛应用,美国汽车制造 业协会(AIAG)还专门制订了相关标准,从发动机的钢体、钢盖、曲轴、连杆、凸轮轴到变速箱的阀体、阀座、阀盖,再到离合器的关键零部件及电子点火器和 安全气囊。从而使得生产加工质量得以全程跟踪,同时由于跟踪了生产过程中的加工设备,使得其原生产线变成了柔性生产线,可生产多品种产品,并为MES(制 造执行系统)管理的实现提供了完整数据平台。
6. 食品采用二维码溯源,吃得放心
将食品的生产和物流信息加载在二维码里,可实现对食品追踪溯源,消费者只需用手机一扫,就能查询食品从生产到销售的 所有流程。在青岛,肉类蔬菜二维码追溯体系已在利群集团投入使用,市民用手机扫描肉菜的二维码标签,即可显示肉菜的流通过程和食品安全信息。在武汉,中百仓储的蔬菜包装上,除了单价、总量、总价等信息外,还有二维码,扫描后可以追溯蔬菜生产、流通环节的各种信息,如,施了几次肥,打了几次农药、何时采摘、 怎么运输。
7. 二维码电子票务,实现验票、调控一体化
火车票上加入二维码,大家已经知道。由此还可以延伸,景点门票、展会门票、演出门票、飞机票、电影票等等都 可以通过二维码都能实现完全的电子化。比如,用户通过网络购票,完成网上支付,手机即可以收到二维码电子票,用户可以自行打印或保存在手机上作为入场凭 证,验票者只需通过设备识读二维码,即可快速验票,大大降低票务耗材和人工成本。在苏州拙政园、虎丘景区,由税务部门统一监制的二维码电子门票,一票一 码,用后作废。而且,景点当天出售的所有门票都要先激活,即只有从售票处售出的门票才能通关入园。并且激活是有时效的,也利于控制人数,避免黄金周的爆 棚。今年5月17日,在重庆武隆仙女山景区,使用二维码电子票,还可以享受5折优惠。
8. 二维码管理交通参与者,能够强化监控
二维码在交通管理中可应用在管理车辆本身的信息、行车证、驾驶证、年审保险、电子眼等等。比如,采用印有二维 码的行车证,将有关车辆的基本信息,包括车驾号、发动机号、车型、颜色等车辆信息转化保存在二维码中,交警在查车时,就不需要再呼叫总台协助了,直接扫描 车辆的二维码即可。以二维码为基本信息载体,还可以建立全国性的车辆监控网络。
9. 证照应用二维码,有利于防伪防盗版
在日、韩等国家,个人名片普遍采用二维码。传统纸质名片携带、存储都非常不方便,而在名片上加印二维码,客户拿 到名片以后,用手机直接一扫描,便可将名片上的姓名、联系方式、电子邮件、公司地址等存入到手机中,并且还可以直接调用手机功能,拨打电话,发送电子邮件 等。目前,国内已有此类应用,如银河、灵动二维码等公司。其实,举一反三,身份证、护照、驾驶证、军官证等证照资料均可以加入二维码,不但利于查证,关键利于防伪。
10. 会议签到二维码,简单高效低成本
目前,很多大型会议由于来宾众多,签到非常繁琐,花费很多时间,也很容易有会虫混入其中,混吃混喝混礼品。如果采用二维码签到以后,主办方向参会人员发送二维码电子邀请票、邀请函,来宾签到时,只需一扫描验证通过即可完成会议签到,整个签到过程无纸化、低碳环保 、高效便捷、省时省力。省去了过去传统中签名、填表、会后再整理信息的麻烦,可大大提高了签到的速度和效率。
11. 执法部门采用二维码,有利于快速反应
最近,广州番禺区的管理部门启用了“出租屋智能手机巡查系统”,出租屋管理员在上门巡查时,用智能手机读取门 牌上的二维码,即可及时、准确获取该户址的相关信息。同理,如果在商品、检验物品上附上二维码,政府执法部门人员则可以通过专用移动执法终端进行各类执法 检查,及时记录物品、企业的违法行为,并且可以保证数据传输的高度安全性和保密性,有利于政府主管部门提高监管,规范市场秩序,提高执法效率,增强执法部门快速反应能力。
12. 防伪隐形二维码,无法轻易复制
上个世纪90年代,国内的商品激光打标防伪曾经风云一时,但现在非常普遍不再具有独特性了。目前,荧光粉等印刷技术 的发展,一些重要物品开始使用隐形二维码,美国的科研人员也正在试图把这些隐形编码应用到玻璃、塑料胶片、纸质产品、银行票据上。这些隐形二维码用肉眼是 看不到的,必须通过红外激光照射才能进行扫描验证。由于该技术生产过程比较复杂,造假者无法轻易复制。目前,此类二维码需要商家提供红外激光扫射设备,然 后再让智能手机扫描验证,或者使用安装有红外激光摄像头的智能手机才能验证。推而广之,一些商业情报、经济情报、政治情报、军事情报等机密资料均可以通过 这种方式加密。
13. 高端商品用二维码互动营销,有助于打击山寨
世界著名葡萄酒之一的新西兰南极星葡萄酒,掀起了葡萄酒业应用二维码技术的新风潮,以南极星 Invivo黑皮诺葡萄酒为例,只要用智能手机扫描产品背标上的二维码,就能立即显示出该产品的信息详情链接,点击链接,可以看到该产品的原产地、生产年 份、葡萄品种、酒精度、产品介绍、获奖荣誉等信息。消费者在选购葡萄酒时能够更加轻松,全面的了解产品的各项信息,可以更好地与品牌互动,让购买变得简单 有趣,而且可以准确辨识真伪,打击山寨。
14. 传情达意,二维码引领传情Style
近日,中国邮电大学一个男生,以二维码为载体向女友传递情意,在明信片上手绘二维码 “我爱你”,火了一把。如此的“传情style”引发了网友追捧。其实,这个二维码形成并不复杂,先将信息在线生成二维码,然后将图片放大后打印出来,最 后将二维码绘制至明信片上。利用二维码传达情意,确实是一个技术性的Style,有高科技含量但绝对实用,通过二维码表达一定比传统的文字更能打动对方的 心。目前都市里一些时尚的咖啡店里,顾客扫描一下饮料杯上的二维码,还可以下载好听的铃声或音乐。
15. 二维码点餐,个性化客户服务到家了
如果你是一个餐饮店的老顾客,在二维码时代,你将能享受更加个性化的服务。比如,你到达一家餐饮店,用餐饮店的 设备扫描一下手机上的二维码,立即就可顺利地点下自己“最爱”菜品,还可以获得今日优惠信息,如果有VIP折扣券、代金券等,系统可以自动为你计算应付金 额。或者,你用手机扫描菜谱上的二维码,即可随时把点单传递到服务台或厨房,不需要服务员现场点单。用餐完毕,可以通过手机对菜品和服务进行评价,餐饮系统将自动为你积分。
16. 公交二维码,成为城市的移动地图
2010 年,杭州公交和杭州移动联合推出公共出行二维码查询系统,这是二维码技术在公交领域的首次应用,该系统在全市公交车站、公共自行车站布设二维码,市民扫描 二维码即可看到一张所在区域的地图,随时获取周边景点、餐饮、娱乐、道路、公交信息和换乘信息,甚至可以马上查询到你乘坐的公交车离站点还有多远,或者还 有几分钟可到终点站。因此,有了它,就像随身带了张城市地图,吃喝玩乐了然于心。
17. 招聘二维码,求职者可用手机来应聘
今年11月,在银川市举办的2012年冬季人才招聘会上,“二维码企业墙”吸引了众多求职者,使用手机上的“宁 夏12580求职通”客户端扫描二维码,会自动连接移动WIFI网络,求职者就能通过手机方便快捷的详细了解用工单位、岗位信息,并经由客户端投递简历。 这些内容都是储存在求职通平台上,求职者刷二维码的过程实际上是利用手机调取平台上的信息,简单高效,当场就可以完成查询、应聘。
18. 二维码进入医院,挂号、导诊、就医一条龙
对于患者而言,最烦心的莫过于挂号。采用二维码,患者可以通过手机终端预约挂号,凭二维码在预约时间前往 医院直接取号,减少了排队挂号、候诊时间。二维码服务不仅解决了挂号的问题,而且,二维码结合到看病、支付等环节后,可以实现看病、付款、取药一条龙服 务,不再让患者重复排队。另外,还能对医风医德进行评价,医患双方就能够加强沟通了解。目前,很多城市的大医院都至少已经采用了条码,相比以前,医疗信息 化水平大大提高,医院运转的效率也大大提高了。
19. 二维码旅游监督和导游,提高旅游服务的质量
前段时间,央视曝光了北京的一些旅游车宰客现象,这样的问题在一些景区总是屡禁不止。最近,上海的旅游 部门看中了二维码在旅游监督方面的优势,虹口区旅游部门设想,为辖区内旅行社运营的大巴车加装彩色二维码,游客用手机扫描二维码后,便能获悉自己所搭乘车 辆的运营资质,是否黑车,是否接受年检,有没有肇事记录等信息。烟台、莱芜、威海等旅游部门纷纷推出二维码地图,如烟台二维码旅游囊括了烟台十大特色休闲 之旅,市民和游客领取地图后,只要用智能手机对上面的二维码一拍就能看到详细的旅游景点、线路介绍,加油站、休息区、停车场等信息。
20. 二维码墓碑,无限怀念到永恒
目前,大城市地价飞涨,“死不起”已经成为一种社会问题。如何能够缩小墓碑和墓地,减少活人的负担呢?最近,英国一家 葬礼公司的了新创意,推出了二维码墓碑,在逝者的墓碑上增加一个二维码,参与祭奠的亲友用手机拍下这个二维码,就能导航到逝者在网站上的个人主页,看到他的音容笑貌、活动剪影、朋友的怀念等,亲人还可以对逝者的个人网页进行更新。怀念不再受制时间、空间限制,可谓无限怀念到永远了。
如果继续列举,二维码的应用方式还有很多,比如二维码导览,在展品上贴上二维码铭牌,参观者拍下二维码后,耳贴手机就能听到展品的语音介绍。还有二维码婚柬,将二维码发到亲朋好友手机上,对方即可直接连接到网页上查看邀请函内容,确认是否出席。
据业内预测,2012年二维码市场规模将达到300亿元,到了2015年,二维码市场将超过1000亿元,会有一万家公司进入二维码行业。可以说,二维码将成为融合移动互联网、电子商务、云计算等领域的下一个金矿产业。
Author:Lishu
Date: 2013-10-23
Weibo: @maggic_rabbit
最近接了一个project要使用R Hadoop,这才零零散散开始学习R和Hadoop,在这里记录下我学习和安装过程中遇到的问题和解决办法。我搭建的环境是14台server,全部安装Ubuntu Server 12. 04 LTS,关于系统重装这里就不赘述了。我的目标是搭建一个14台机器的Hadoop cluster,并装上R Hadoop。
1. Hadoop 的安装
关于Hadoop有太多open resource可以利用,这里我用的是O‘Reilly出版的 Hadoop: The Definitive Guide, 3rd Edition. 这本书应该有相应的中文版,正如书名所说,这是最官方最全面的guide,里面基本上对Hadoop方方面面都有讲解。
关于Hadoop的安装,请参考书的Appendix A 和Chapter 9. 或者这个tutorial.
Running Hadoop on Ubuntu Linux (Single-Node Cluster)
Running
Hadoop on Ubuntu Linux (Multi-Node Cluster)
具体步骤如下:
1.预安装
每台机器都需要Java和SSH,对于每台机器都需要做以下事情:
- 预装Java:
$ sudo apt-get install openjdk-7-jdk
或查看Java版本:
$ java -version java version "1.7.0_25" OpenJDK Runtime Environment (Ice(IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.04.2) OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)
- 安装设置SSH:
$ sudo apt-get install ssh $ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa # 生成无密码的RSA key $ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys # 添加 public key 到 authorized_keys 以允许访问 $ ssh localhost # 测试是否装成功理论上来说应该在每台机器上都生成一个RSA key,然后把 public key 添加到其它机器的 authorized_keys,这里为简化这个过程,我在每台机器上都使用了同样的RSA key pair, 即大家都用相同的钥匙去开相同的锁,但是这样是存在安全隐患的。
- 设置 /etc/hosts:
127.0.0.1 localhost #127.0.1.1 serv20 10.11.8.27 serv07 10.11.8.34 serv08 10.11.8.42 serv09 10.11.8.44 serv10 10.11.8.48 serv11 10.11.8.47 serv12 10.11.8.49 serv13 10.11.8.51 serv14 10.11.8.52 serv15 10.11.8.55 serv16 10.11.8.53 serv17 10.11.8.36 serv18 10.11.8.54 serv19 10.11.8.56 serv20注意,我的14台机器 hostname 叫 serv07~20, 这里以 serv20 为例,添加每台机子的IP,并必须注释掉原本的 127.0.1.1, 否则在运行Hadoop时会出现类似这样的错误:
2013-09-03 15:29:04,374 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: serv20/127.0.1.1:54310. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS) 2013-09-03 15:29:05,375 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: serv20/127.0.1.1:54310. Already tried 1 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS) 2013-09-03 15:29:06,376 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: serv20/127.0.1.1:54310. Already tried 2 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS) 2013-09-03 15:29:07,376 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: serv20/127.0.1.1:54310. Already tried 3 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS) 2013-09-03 15:29:08,377 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: serv20/127.0.1.1:54310. Already tried 4 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS) 2013-09-03 15:29:09,377 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: serv20/127.0.1.1:54310. Already tried 5 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1 SECONDS)
如果设置正确,你应该能从每台机器上直接用 hostname SSH:
$ ssh serv19 # instead of ssh 10.11.8.54
2. 安装设置Hadoop
在 Apache Hadoop Releases 下载所需Hadoop版本,我使用的是Hadoop 1.2.1 (stable).
- 解压:
$ tar xzf hadoop-1.2.1.tar.gz
- 设置环境变量:
$ export HADOOP_HOME=/home/hadoop/hadoop-1.2.1 # 这里我的用户名叫hadoop $ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64 $ export PATH=$PATH:$HADOOP_HOME/bin注意,这里想 permanent 设置的话需要在~/.bashrc里面修改,这是个 shell startup file,通常都在 user home directory 下面。如果 home directory 没有的话可以从 root 拷贝过来:
$ sudo cp /root/.bashrc ~
修改完 .bashrc 文件需要重新加载,或者重新登陆:
$ source ~/.bashrc
- 设置 conf/hadoop-env.sh ,添加以下行:
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64export HADOOP_OPTS=-Djava.net.preferIPv4Stack=true # disable IPv6
注意,虽然环境变量里已经设置过 JAVA_HOME, 在Hadoop里还需要再设置一下,否则会找不到 java.
- 设置 conf/core-site.xml:
<configuration> <property> <name>hadoop.tmp.dir</name> <value>/data/hadoop</value> </property> <property> <name>fs.default.name</name> <value>hdfs://serv20:54310</value></property></configuration>
注意,这里我的serv20是我设定的namenode,serv20需要被替换成你想设定成namenode的 hostname / IP address。
* property 的 default value 和 description 参考core-default.
另外,这里的hadoop.tmp.dir必须是已经存在的,所以在此之前需要 mkdir 以下 directory 以备后用:
$ mkdir -p /data $ mkdir -p /data/hadoop $ mkdir -p /data/hadoop/dfs $ mkdir -p /data/hadoop/dfs/data $ mkdir -p /data/hadoop/dfs/local $ mkdir -p /data/hadoop/dfs/name $ mkdir -p /data/hadoop/dfs/namesecondary $ mkdir -p /tmp/hadoop/mapred $ mkdir -p /tmp/hadoop/mapred/local $ chown -R hadoop:hadoop /data $ chown -R hadoop:hadoop /tmp/hadoop
- 设置conf/mapred-site.xml:
<configuration> <property> <name>mapred.job.tracker</name> <value>serv20:54311</value> </property> <property> <name>mapred.local.dir</name> <value>/data/hadoop/dfs/local</value> </property> <property> <name>mapred.child.java.opts</name> <value>-Xmx512m</value> </property> <property> <name>mapred.system.dir</name> <value>/tmp/hadoop/mapred/local</value> </property> <property> <name>mapred.tasktracker.map.tasks.maximum</name> <value>4</value> </property> <property> <name>mapred.tasktacker.reduce.tasks.maximum</name> <value>4</value> </property> </configuration>
注意,这里我设定的 jobtracker 也是serv20, 但是 namenode 和 jobtracker 并不一定非得是同一台机子,我后面会提到。
* property 的 default value 和 description 参考mapred-default.
- 设置conf/hdfs-site.xml:
<configuration> <property> <name>dfs.replication</name> <value>3</value> </property> <property> <name>fs.checkpoint.dir</name> <value>/data/hadoop/dfs/namesecondary</value> </property> <property> <name>fs.chechpoint.size</name> <value>1048580</value> </property> <property> <name>dfs.http.address</name> <value>hdfs://serv19:50070</value> </property> <property> <name>dfs.name.dir</name> <value>/data/hadoop/dfs/name</value> </property> <property> <name>dfs.data.dir</name> <value>/data/hadoop/dfs/data</value> </property> <property> <name>dfs.permissions.superusergroup</name> <value>hadoop</value> </property> </configuration>
注意,这里我设定了secondarynamenode为serv19.
*property 的 default value 和 description 参考hdfs-default.
到这里为止上面所有的安装和设置都需要在每台机器上进行(设置对每台机器都是一样的),其实完全可以写一个 shell script 完成所有的安装,再 scp 这些 conf 文件到各个机子指定位置,这样比较省时间,但是前提是每台机子的环境都是一样的。
- 设置conf/masters (master only):
这里有几个概念需要注意, Namenode 是 HDFS 里的概念,即跑
bin/start-dfs.sh 的机器; JobTracker 是 MapReduce 里的概念,即跑 bin/start-mapred.sh 的机器。一般情况下 Namenode 和 Jobtracker 都在同一台机器上跑,这台机器被称为 master,其它跑 Datanode 和 TaskTracker 的机器称为 slave. 这里我的 master 是serv20, 其他机器都是 slave。
但是这里conf/masters定义的却不是上述意义的 master, 而是 SecondaryNamenode. 这里我设置的SecondaryNamenode 是 serv19, 所以在 serv20 (master) 上做如下设置:
serv19注意,只需设置 master 上的 conf/masters, 不需要设置 slave 上的。
- 设置conf/slaves (master only):
该文件列出 所有的 slave host, 每行一个。该文件也只需要在 master 上设置。
serv20 serv19 serv18 serv17 serv16 serv15 serv14 serv13 serv12 serv11 serv10 serv09 serv08 serv07
这里serv20也被列为 slave, 意味着 serv20 同时是 master 和 slave.
3. 格式化HDFS (namenode)
在 Namenode 上格式化 HDFS, 即我的 serv20 上。理论上每次上述设置文件有变动时都需要重新格式化HDFS.
hadoop@serv20:~$ hadoop namenode -format
如果已经跑了上述命令仍然得到类似下面的错误:
13/05/23 04:11:37 ERROR namenode.FSNamesystem: FSNamesystem initialization failed. java.io.IOException: NameNode is not formatted. at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverTransitionRead(FSImage.java:330) at org.apache.hadoop.hdfs.server.namenode.FSDirectory.loadFSImage(FSDirectory.java:100) at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.initialize(FSNamesystem.java:411)
那么试试下面命令:
hadoop@serv20:~$ hadoop namenode -format -force
如果得到类似下面错误
2013-10-22 14:16:33,269 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: java.io.IOException: Incompatible namespaceIDs in /data/hadoop/dfs/data: namenode namespaceID = 2142266875; datanode namespaceID = 894925905 at org.apache.hadoop.hdfs.server.datanode.DataStorage.doTransition(DataStorage.java:232) at org.apache.hadoop.hdfs.server.datanode.DataStorage.recoverTransitionRead(DataStorage.java:147) at org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(DataNode.java:414) at org.apache.hadoop.hdfs.server.datanode.DataNode.<init>(DataNode.java:321) at org.apache.hadoop.hdfs.server.datanode.DataNode.makeInstance(DataNode.java:1712) at org.apache.hadoop.hdfs.server.datanode.DataNode.instantiateDataNode(DataNode.java:1651) at org.apache.hadoop.hdfs.server.datanode.DataNode.createDataNode(DataNode.java:1669) at org.apache.hadoop.hdfs.server.datanode.DataNode.secureMain(DataNode.java:1795) at org.apache.hadoop.hdfs.server.datanode.DataNode.main(DataNode.java:1812) 2013-10-22 14:16:33,270 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: SHUTDOWN_MSG: /************************************************************ SHUTDOWN_MSG: Shutting down DataNode at serv07/127.0.1.1 ************************************************************/
说明 Datanode 的 namespaceID 和 Namenode 的不一致,这可能是重新 format namenode导致的。在 hdfs-site 里定义的 dfs.data.dir 目录下找 VERSION 文件,这里我定义的是 /data/hadoop/dfs/data, 那么用下面命令修改 VERSION 文件:
$ vim /data/hadoop/dfs/data/current/VERSION
#Tue Oct 22 14:49:40 CDT 2013 namespaceID=894925905 -> 改成 2142266875 storageID=DS-1631780027-10.11.8.27-50010-1380139765131 cTime=0 storageType=DATA_NODE layoutVersion=-41
如果得到类似下面错误
2013-07-05 14:04:40,557 INFO org.apache.hadoop.ipc.Server: Stopping server on 50010 2013-07-05 14:04:40,564 ERROR org.apache.hadoop.hdfs.server.namenode.NameNode: org.apache.hadoop.hdfs.server.common. InconsistentFSStateException: Directory /tmp/haloop/dfs/name is in an inconsistent state: storage directory does not exist or is not accessible. at org.apache.hadoop.hdfs.server.namenode.FSImage.recoverTransitionRead(FSImage.java:290) at org.apache.hadoop.hdfs.server.namenode.FSDirectory.loadFSImage(FSDirectory.java:87) at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.initialize(FSNamesystem.java:311) at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.(FSNamesystem.java:292) at org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(NameNode.java:201) at org.apache.hadoop.hdfs.server.namenode.NameNode.(NameNode.java:279) at org.apache.hadoop.hdfs.server.namenode.NameNode.createNameNode(NameNode.java:956) at org.apache.hadoop.hdfs.server.namenode.NameNode.main(NameNode.java:965) 2013-07-05 14:04:40,572 INFO org.apache.hadoop.hdfs.server.namenode.NameNode: SHUTDOWN_MSG: /********************************** SHUTDOWN_MSG: Shutting down NameNode at elmorsy/127.0.1.1 **********************************/
这个错误是说设定的namenode directory inconsistent, 像这里设定的/tmp就是 inconsistent 的, 它可能会更新或被删除,所以最后我是用了 /data/hadoop/dfs/name。这个问题也可能出现在 SecondaryNamenode 上。
4. 运行Hadoop
运行 Hadoop 有两个步骤, 即运行 HDFS 和 运行 MapReduce:
$ bin/start-dfs.sh $ bin/start-mapred.sh
这里我的 Namenode 和 Jobtracker 是用一台机子,所以可以用下面命令:
$ bin/start-all.sh其实看这个 script 里面内容也就是分别运行了上面两句。
要查看每台机子是否正常运行可以用 jps (需要先安装):
hadoop@serv20:~$ jps 13121 JobTracker 29872 Jps 13434 TaskTracker 12937 DataNode 12634 NameNode
hadoop@serv19:~$ jps 17291 TaskTracker 17051 SecondaryNameNode 16793 DataNode 27317 Jps
hadoop@serv18:~$ jps 13764 Jps 16157 DataNode 16386 TaskTracker
这里 serv20 是master同时也是slave,所以上面运行了 Namenode, JobTracker, Datanode, TaskTracker.
serv19 是 SecondaryNamenode 和 slave, 所以上面运行了 SecondaryNamenode, Datanode, TaskTracker.
serv18 只是 slave,所以上面只有 Datanode, TaskTracker.
5. 调试 Hadoop 程序
- 要查看 Hadoop WebUI, 参考下表:
更多请参看:hadoop default ports quick reference
Daemon Default Port Configuration Parameter HDFS Namenode 50070 dfs.http.address Datanodes 50075 dfs.datanode.http.address Secondarynamenode 50090 dfs.secondary.http.address Backup/Checkpoint node? 50105 dfs.backup.http.address MR Jobracker 50030 mapred.job.tracker.http.address Tasktrackers 50060 mapred.task.tracker.http.address ? Replaces secondarynamenode in 0.21.
- 要查看 Hadoop 日志,
- On the jobtracker:
HADOOP_HOME/logs /hadoop-username-jobtracker-hostname.log* => daemon logs /job_*.xml => job configuration XML logs /history /*_conf.xml => job configuration logs < everything else > => job statistics logs
HADOOP_HOME/logs /hadoop-username-namenode-hostname.log* => daemon logs
HADOOP_HOME/logs /hadoop-username-secondarynamenode-hostname.log* => daemon logs
HADOOP_HOME/logs /hadoop-username-datanode-hostname.log* => daemon logs
HADOOP_HOME/logs /hadoop-username-tasktacker-hostname.log* => daemon logs /userlogs /attempt_* /stderr => standard error logs /stdout => standard out logs /syslog => log4j logs
更多Hadoop command 请参考
commands manual.
- WordCount
详情请参看:wordcount v1.0
2. R的安装
R的安装可以用 apt-get 完成:
$ sudo apt-get install r-base
查看 R 版本信息:
$ R --version R version 2.14.1 (2011-12-22) Copyright (C) 2011 The R Foundation for Statistical Computing ISBN 3-900051-07-0 Platform: x86_64-pc-linux-gnu (64-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under the terms of the GNU General Public License version 2. For more information about these matters see http://www.gnu.org/licenses/.
这里安装的是R 2.14, 目前最新的版本是 R 3.0, 要安装最新版本,需更新 apt source list:
$ sudo apt-get remove r-base-core # Uninstall old R $ sudo vim /etc/apt/sources.list # Adding deb to sources.list # 添加这一行 deb http://cran.r-project.org/bin/linux/ubuntu precise/ # precise is your ubuntu name (may be different) $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9 # Add key to sign CRAN packages $ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install r-base
Ubuntu release name 参考这里.
再查看版本:
$ R --version R version 3.0.2 (2013-09-25) -- "Frisbee Sailing" Copyright (C) 2013 The R Foundation for Statistical Computing Platform: x86_64-pc-linux-gnu (64-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under the terms of the GNU General Public License versions 2 or 3. For more information about these matters see http://www.gnu.org/licenses/.
到这里R就安装好了,鉴于我使用的是Ubuntu server,所以这里所说的 R 是 command line, 不是 RStudio, 也不是 Revolution R.
3. R Hadoop的安装
所谓的 RHadoop 安装并不是一个另外的单独的 software,而是 R package: rhdfs, rmr2, rhbase.
从名字不难推断每个包的用途,rhdfs 是对应 HDFS 的 R interface, rmr2 是对应 MapReduce, rhbase 是对应 HBase. 这里我没有用到 HBase, 所以暂时先不谈 rhbase 的安装,以后如果要用再补上。
- 预装依赖库
$ sudo apt-get install git libboost-dev libboost-test-dev libboost-program-options-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev
- 设置 Java 配置
$ sudo R CMD javareconf
注意这里需要root权限,否则会得到 Permission Denied.
- 设置环境变量
同前面提到的一样,有两种方式,直接 export 和修改 .bashrc 文件。
export HADOOP_CMD=$HADOOP_HOME/bin/hadoop export HADOOP_STREAMING=$HADOOP_HOME/contrib/streaming/hadoop-streaming-1.2.1.jar export LD_LIBRARY_PATH=/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server
另一种方式是在 R 里面设置:
> Sys.setenv("HADOOP_CMD"="/home/hadoop/hadoop-1.2.1/bin/hadoop") > Sys.setenv("HADOOP_STREAMING"="/home/hadoop/hadoop-1.2.1/contrib/streaming/hadoop-streaming-1.2.1.jar") > Sys.setenv("LD_LIBRARY_PATH"="/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/server")这里需要注意的是权限问题,如果修改的是hadoop user 的 .bashrc 文件或者以 hadoop 身份export, 这些环境变量就只对 hadoop user 有用,但是下面一个步骤需要 root 权限,所以可能需要重新在 R 里重新设置一下。检查 R 是否设置了这些环境变量,用下面命令:
> Sys.getenv("HADOOP_CMD")
- 预装R依赖库
这里需要以 root 权限启动R:
$ sudo R > install.packages(c("rJava", "Rcpp", "RJSONIO", "bitops", "digest", "functional", "stringr", "plyr", "reshape2"))这样这些包就被安装到默认的 R 路径下: /usr/lib/R/library/
若不是这样,R 会提示是否使用 personal library:
> install.packages("Rcpp") Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) Warning in install.packages("Rcpp") : 'lib = "/usr/local/lib/R/site-library"' is not writable Would you like to use a personal library instead? (y/n) y Would you like to create a personal library ~/R/x86_64-pc-linux-gnu-library/3.0 to install packages into? (y/n)
如上面显示的,如果使用 personal library, 它会新建一个 R directory 在你的 $HOME. 这样是可以成功安装并加载这个包的:
> library(rmr2) Loading required package: Rcpp Loading required package: RJSONIO Loading required package: bitops Loading required package: digest Loading required package: functional Loading required package: stringr Loading required package: plyr Loading required package: reshape2但是我发现之后运行RHadoop的时候会出现类似下面错误(能在 WebUI 看到):
java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 1 at org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:362) at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:576) at org.apache.hadoop.streaming.PipeMapper.close(PipeMapper.java:135) at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:57) at org.apache.hadoop.streaming.PipeMapRunner.run(PipeMapRunner.java:36) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:436) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:372) at org.apache.hadoop.mapred.Child$4.run(Child.java:255) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1149) at org.apache.hadoop.mapred.Child.main(Child.java:249)
或者在 command line里看到类似这样的提示:
13/08/21 18:30:25 ERROR streaming.StreamJob: Job not Successful! Streaming Command Failed! Error in mr(map = map, reduce = reduce, combine = combine, in.folder = if (is.list(input)) { : hadoop streaming failed with error code 1
这两个提示都只是 general 的 Hadoop 提示和 Java 提示,并没有明确表示原因。错误原因需要从上述 takstracker log strerr里去找:
$ vim $HADOOP_HOME/logs/userlogs/job_201310221441_0002/attempt_201310221441_0002_m_000000_1/stderr Error in loadNamespace(name) : there is no package called ‘Rcpp’ Calls: <Anonymous> ... tryCatch -> tryCatchList -> tryCatchOne -> <Anonymous> Execution halted java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 1 at org.apache.hadoop.streaming.PipeMapRed.waitOutputThreads(PipeMapRed.java:362) at org.apache.hadoop.streaming.PipeMapRed.mapRedFinished(PipeMapRed.java:576) at org.apache.hadoop.streaming.PipeMapper.close(PipeMapper.java:135) at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:57) at org.apache.hadoop.streaming.PipeMapRunner.run(PipeMapRunner.java:36) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:436) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:372) at org.apache.hadoop.mapred.Child$4.run(Child.java:255) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1149) at org.apache.hadoop.mapred.Child.main(Child.java:249)原因是这个包装在了personal directory, R知道到哪里去找这个包,但是Hadoop只会在默认的R system directory 即/usr/local/lib/R/下面去找。一个简单的解决办法就是把该包从 personal library 拷贝到 system directory.
- 安装 rmr2,rhdfs
由于这三个库不能在CRAN中找到,所以需要自己下载。
https://github.com/RevolutionAnalytics/RHadoop/wiki
下载好后用下面命令安装:
> install.packages('/home/hadoop/rmr2_2.3.0.tar.gz',repo=NULL,type="source") > install.packages('/home/hadoop/rhdfs_1.0.7.tar.gz',repo=NULL,type="source")这里如果上面都是以root运行R, 那么安装不会有问题,可是当运行RHadoop的时候会出现Permission Denied错误:
org.apache.hadoop.security.AccessControlException: Permission denied: user=root, access=WRITE, inode="": hadoop:supergroup:rwxr-xr-x那是因为root并不是我的hadoop cluster 的user, 解决办法有两个,要么修改 hadoop 权限设置,在conf/hdfs-site.xml里添加下面
<property> <name>dfs.permissions</name> <value>false</value> </property>要么以 hadoop 运行R, 可是这样又会出现这样错误:
> library(rhdfs) Loading required package: rJava Error : .onLoad failed in loadNamespace() for 'rJava', details: call: dyn.load(file, DLLpath = DLLpath, ...) error: unable to load shared object '/usr/lib/R/site-library/rJava/libs/rJava.so': libjvm.so: cannot open shared object file: No such file or directory Error: package ‘rJava’ could not be loaded这是因为我之前没有设置 LD_LIBRARY_PATH 指向 rJava.so,如果按照我前面写的设置了LD_LIBRARY_PATH就不会出现这个问题了.
如果看到下面错误:
> library("rhdfs") Error : .onLoad failed in loadNamespace() for 'rhdfs', details: call: fun(libname, pkgname) error: Environment variable HADOOP_CMD must be set before loading package rhdfs Error: package/namespace load failed for ‘rhdfs’说明当前R user 没有设置 HADOOP_CMD,就是我前面讲到的如果sudo R, 那么user是root, 而我前面只设置了hadoop的环境变量。
如果load rmr2和rhdfs都没有问题,那么RHadoop就算安装成功了。
- 运行RHadoop 程序
> library(rmr2) Loading required package: Rcpp Loading required package: RJSONIO Loading required package: bitops Loading required package: digest Loading required package: functional Loading required package: stringr Loading required package: plyr Loading required package: reshape2 > library(rhdfs) Loading required package: rJava HADOOP_CMD=/home/hadoop/hadoop-1.2.1/bin/hadoop Be sure to run hdfs.init() > map <- function(k,lines) { + words.list <- strsplit(lines, '\\s') + words <- unlist(words.list) + return( keyval(words, 1) ) + } > reduce <- function(word, counts) { + keyval(word, sum(counts)) + } > wordcount <- function (input, output=NULL) { + mapreduce(input=input, output=output, input.format="text", map=map, reduce=reduce) + } > hdfs.data <- '/user/hadoop/input' > hdfs.out <- '/user/hadoop/output' > out <- wordcount(hdfs.data, hdfs.out) packageJobJar: [/tmp/RtmpbgF5IT/rmr-local-env6eb71e7e6c51, /tmp/RtmpbgF5IT/rmr-global-env6eb74c4d3f75, /tmp/RtmpbgF5IT/rmr-streaming-map6eb75e339403, /tmp/RtmpbgF5IT/rmr-streaming-reduce6eb711a6cae0, /data/hadoop/hadoop-unjar7453012150899590081/] [] /tmp/streamjob5631425967008143655.jar tmpDir=null 13/10/23 10:31:26 INFO util.NativeCodeLoader: Loaded the native-hadoop library 13/10/23 10:31:26 WARN snappy.LoadSnappy: Snappy native library not loaded 13/10/23 10:31:26 INFO mapred.FileInputFormat: Total input paths to process : 3 13/10/23 10:31:26 INFO streaming.StreamJob: getLocalDirs(): [/data/hadoop/dfs/local] 13/10/23 10:31:26 INFO streaming.StreamJob: Running job: job_201310221441_0004 13/10/23 10:31:26 INFO streaming.StreamJob: To kill this job, run: 13/10/23 10:31:26 INFO streaming.StreamJob: /home/hadoop/hadoop-1.2.1/libexec/../bin/hadoop job -Dmapred.job.tracker=serv20:54311 -kill job_201310221441_0004 13/10/23 10:31:26 INFO streaming.StreamJob: Tracking URL: http://serv20:50030/jobdetails.jsp?jobid=job_201310221441_0004 13/10/23 10:31:27 INFO streaming.StreamJob: map 0% reduce 0% 13/10/23 10:31:32 INFO streaming.StreamJob: map 33% reduce 0% 13/10/23 10:31:33 INFO streaming.StreamJob: map 67% reduce 0% 13/10/23 10:31:34 INFO streaming.StreamJob: map 100% reduce 0% 13/10/23 10:31:39 INFO streaming.StreamJob: map 100% reduce 33% 13/10/23 10:31:42 INFO streaming.StreamJob: map 100% reduce 82% 13/10/23 10:31:45 INFO streaming.StreamJob: map 100% reduce 94% 13/10/23 10:31:48 INFO streaming.StreamJob: map 100% reduce 100% 13/10/23 10:31:51 INFO streaming.StreamJob: Job complete: job_201310221441_0004 13/10/23 10:31:51 INFO streaming.StreamJob: Output: /user/hadoop/output > results <- from.dfs(out) > results.df <- as.data.frame(results, stringsAsFactors=F) > colnames(results.df) <- c('word', 'count') > head(results.df) word count 1 17259 2 % 2 3 & 21 4 ( 1 5 ) 3 6 * 90