Solr + Hadoop = Big Data Love
FROM:http://architects.dzone.com/articles/solr-hadoop-big-data-love
许多人使用Hadoop的开源项目来处理大数据的大数据集,因为它是一个伟大的解决方案可扩展,可靠的数据处理工作流程。Hadoop是目前最流行 的大数据处理系统,与企业使用数千台服务器上的数据存储和处理PB级的大规模集群。
Nutch的开源网络爬虫项目于2006年出现以来,Hadoop已种植在各方面都可以想象-用户,开发相关的项目(又名“Hadoop生态系统”)。
在大致相同的时间开始,Solr的开源项目已经成为地球上最广泛使用的搜索解决方案。Solr的包装API级别的索引和搜索功能的Lucene的一个RESTful API,GUI,和很多有用的管理和数据集成功能。
结合这两个开源项目的有趣的事情是,你可以使用Hadoop处理数据,然后为它在Solr。而且我们不是在谈论刚刚自由文本搜索Solr的,可以作为一个 key-value存储(即NoSQL数据库),通过其支持范围查询。
即使一台服务器上,可以很容易地处理Solr的数以百万计的记录(“文件”在Lucene的行话)。更妙的是,Solr的现在支持通过新的,尖端的的SolrCloud功能的分片和复制。
背景
我大约五年前开始使用Hadoop和Solr的Krugle的代码搜索启动,我在2005年共同创立的,作为关键件。
那时候,Hadoop的仍然是我们用来提取信息的开源项目Nutch的网络爬虫的一部分。和Solr是新鲜出烤箱,刚刚被发布为开放源代码由CNET。
在Bixo Labs 我们使用的Hadoop,Solr的,层叠, 亨利马乌,和许多其他开源技术来创建自定义的数据处理工作流程。该网站是一个常见的来源,我们的输入数据,这是我们抓取使用的Bixo开源项目。
存在的问题
在网页抓取,抓取的状态包含的东西通常被称为“爬行DB”。对于广泛的抓取,这是数十亿条记录的一些作品,因为你需要一个条目为每个已知的URL。每一个“纪录”的网址为关键,并包含重要的状态信息,如时间和结果的最后请求。
如Nutch和Bixo的基于Hadoop的爬虫抓取DB通常保持在一个平面文件,其中每个文件是一个Hadoop SequenceFile“。这些都只是填充数组的键/值对象序列化。
有时候我们需要去捅这个数据,这里就是简单的平面文件结构产生了一个问题。有没有简单的方式运行,对数据的查询,但我们不能将其存储在传统的数据库,因为数十亿条记录+ RDBMS ==痛苦和苦难。
这里是可伸缩的NoSQL解决方案闪耀。例如,目前Nutch的项目是重新理抓取DB层,让堵在HBase中。其他选项包括卡桑德拉的人员,MongoDB,CouchDB的,等
但较小的数据集上进行简单的分析和探索,基于Solr的解决方案的工作原理,并更容易配置。另外,你会得到有用的和令人惊讶的有趣的功能,如面,空间查询,范围查询,自由格式的文本搜索,和很多其他的好东西免费。
构建
那么究竟是什么将这样一个Hadoop + Solr的系统是什么样子?
正如前面提到的,在这个例子中,我们输入的数据来自一个网络爬虫Bixo的CrawlDB,一个条目为每个已知的URL。但输入的数据可以很容易的日志文件,或从传统的RDBMS记录,或另一个数据处理流程的输出。
关键的一点是,我们要输入数据,拿一把(可选)也得用它成一个有用的格式,然后生成一个Lucene索引,我们通过访问Solr的。
Hadoop的
对于外行的Hadoop实现了一个分布式文件系统(又名“HDFS)和执行层支持的map-reduce编程模型。
通常情况下,数据加载和转化在地图阶段,然后结合/保存在reduce阶段。在我们的例子中,map阶段读在Hadoop压缩SequenceFiles的包含我们的网站抓取的状态,并降低相位写出来的Lucene索引。
这篇文章的重点是如何写的Hadoop的map-reduce工作,但我想告诉你的代码,实现工作的胆量。请注意,这不是典型的Hadoop键/值操作的代码,这是痛苦的编写,调试和维护。相反,我们使用的级联,这是一个开源的工作流规划和数据处理的API,创建Hadoop作业较短,比较有代表性的代码。
下面的代码片段读取从HDFS的反序列化和管道的那些记录,并将它们存储使用的LuceneScheme,这反过来又作为Lucene的索引文件记录保存到一个接收器(输出)。
Tap source = new Hfs(new SequenceFile(CRAWLDB_FIELDS), inputDir); Pipe urlPipe = new Pipe("crawldb urls"); urlPipe = new Each(urlPipe, new ExtractDomain()); Tap sink = new Hfs(new LuceneScheme(SOLR_FIELDS, STORE_SETTINGS, INDEX_SETTINGS, StandardAnalyzer.class, MAX_FIELD_LENGTH), outputDir, true); FlowConnector fc = new FlowConnector(); fc.connect(source, sink, urlPipe).complete();
我们定义CRAWLDB_FIELDS和SOLR_FIELDS,输入和输出数据元素的集合,使用的名称,如“URL”和“状态”。我们利用Lucene的计划,我们已经创建级联,它可以让我们轻松地从层叠的世界观(记录字段)映射到Lucene的索引(文件字段)。我们没有直接支持级联计划Solr的(那不是很方便吗?),但我们可以做的,因为我们现在可以做简单的分析这个例子。
我们索引的所有字段,这样我们就可以对他们进行查询。只有状态消息包含正常的英文文本,让我们来分析(即,突破到使用空格和其他标记分隔符的文本)是唯一一个。此外,拉ExtractDomain操作域的URL字段,建立一个新的Solr场只包含域。这将使我们能够做查询的域名的URL,以及完整的URL。
我们也可以选择应用自定义分析仪的URL,它分解成几个部分(即,协议,域名,端口,路径,查询参数),本来是可以单独查询。
运行在Hadoop作业
为了简化和支付你去,这是很难被击败亚马逊的EC2弹性MapReduce提供运行Hadoop作业。您可以轻松地旋转起来的50台服务器的集群,运行作业,保存结果,并将其关闭 - 所有,而无需购买硬件或IT支持支付。
创建和配置Hadoop集群的方法有很多,对于我们来说,我们很熟悉(修改)EC2的Hadoop的脚本,你可以找到在Bixo分布。一步一步的指令可在http://openbixo.org/documentation/running-bixo-in-ec2/
这篇文章的代码是通过GitHub上http://github.com/bixolabs/hadoop2solr中。该网页上显示的README包含一步一步的指示,建设和运行工作。
作业完成后,我们将复制指数的Hadoop分布式文件系统(HDFS),到Hadoop集群的主服务器,然后杀死我们使用一个从属。现在已经准备好我们的Solr服务器被配置为Hadoop的主。
Solr的
Solr的方面的东西,我们需要创建一个模式匹配索引,我们正在产生。我们的schema.xml文件的关键部分是我们定义的字段。
1 <fields> 2 3 <field name="url" type="string" indexed="true" stored="true" /> 4 5 <field name="domain" type="string" indexed="true" stored="false" /> 6 7 <field name="status" type="string" indexed="true" stored="true" /> 8 9 <field name="statustime" type="string" indexed="true" stored="true" /> 10 11 <field name="statusmsg" type="simpletext" indexed="true" stored="true" /> 12 13 </fields>
一旦我们有了这个定义,所有剩下的就是建立一个服务器,我们就可以使用。为了简单起见,我们将使用单一的EC2实例在亚马逊的云(m1.large),我们使用我们的主人为Hadoop作业,运行简单的Solr搜索服务器依赖于提供嵌入式Jetty web应用容器。
类似Hadoop的工作,一步一步的指示的hadoop2solr项目在GitHub上的自述文件中。但简而言之,我们将复制并解压缩的Solr 1.4.1设置EC2的服务器上,做我们的自定义Solr的配置相同,创建一个符号链接的索引,然后开始运行:
给它一个尝试
现在到了有趣的部分。因为我们开辟了默认码头Solr的(8983)这EC2实例上使用的端口,我们可以直接访问Solr的方便的管理控制台指向我们浏览器在http:// <ec2-public-name>的,8983/solr/admin
% cd solr
% java -Dsolr.solr.home=../solr-conf -Dsolr.data.dir=../solr-data -jar start.jar
从这里我们可以运行Solr的查询:
我们也可以使用curl谈通过HTTP请求到服务器:
curl http://<ec2-public-name>:8983/solr/select/?q=-status%3AFETCHED+and+-status%3AUNFETCHED
默认情况下是XML响应。下面是一个例子上述要求,在那里我们发现了2,546场比赛,94ms的响应。
现在,这里就是我的发现惊人的。索引82万个文档,相当懦弱箱(EC2 m1.large = 2个虚拟内核)上运行,获取典型响应时间为一个简单的查询,如“状态:”只有400毫秒,要找到9M文件。即使是一个复杂的查询(如状态不牵强,不未获得)只需要6秒。
缩放
很显然,我们可以使用比较强大的盒子。如果我们切换到的东西像m1.xlarge(15GB内存,4个虚拟内核),那么我们很可能会向上200M“记录”在我们的Solr索引处理,仍然可以得到合理的响应时间。
如果我们想扩展到超过一个盒子,也有一些解决方案。即使开箱Solr的支持分片,你的HTTP请求可以指定多个服务器并行使用。
最近,Solr的主干有支持SolrCloud。这使用的ZooKeeper 开源项目简化协调多个Solr服务器。
最后,凯塔 开源项目支持Lucene的分布式搜索,许多分布式搜索尚未被添加到SolrCloud生产质量所需的功能。
总结
结合了Hadoop和Solr可以很容易地紧缩大量的数据,然后迅速提供一个快速,灵活的搜索和查询API的结果通过。由于Solr的支持查询的风格的请求,这是适合作为在许多情况下,一个NoSQL替代传统的数据库,特别是当数据的大小超过一个典型的RDBMS什么是合理。
Solr的,你应该知道的,特别是有一定的局限性:
·更新索引最好作为批处理作业。个人可以更新记录,但每个提交(更新索引)生成一个新的Lucene段,这将影响性能。
·当前支持复制,故障转移和其他属性,你会希望在生产级的解决方案尚未有在SolrCloud。如果这对你很重要,而不是考虑凯塔。
·许多SQL查询不能很容易地映射到Solr的查询。
这篇文章的代码是通过GitHub上http://github.com/bixolabs/hadoop2solr中。该网页上显示的README包含额外的技术细节。