大数据系列-CDH环境中SOLR入数据
1 创建集合
-
SSH远程连接到安装了SOLR的CDH节点。
-
运行solrctl instancedir --generate /solr/test/GX_SH_TL_TGRYXX_2015命令就会生成GX_SH_TL_TGRYXX_2015集合的默认配置。
-
进入/solr/test/GX_SH_TL_TGRYXX_2015/conf目录,先编辑schema.xml配置字段信息,具体网上一搜一片。
-
solrconfig.xml文件中在其他<lib/>后面新增<lib dir="/iflytek/solrJar/" regex=".*\.jar"/>,将oracle驱动等依赖jar放在/iflytek/solrJar/目录下,然后远程拷贝/iflytek/solrJar/到其他SOLR节点。
-
solrconfig.xml文件中在其他< requestHandler />后面新增如下节点。
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
- 在/solr/test/GX_SH_TL_TGRYXX_2015/conf目录下新增文件data-config.xml,主要就是配置数据库信息,和要入的数据的对应的查询语句,其中${}表示参数,每次入数据都需要传入这几个参数,内容示例如下:
<dataConfig>
<dataSource name="jdbc" driver="oracle.jdbc.driver.OracleDriver" url="jdbc:oracle:thin:@10.154.5.11:1521:test1" user="test" password="test" batchSize="10000"/>
<document name="defualt">
<entity pk="ID" name="GX_SH_TL_TGRYXX_2015" query="select ID,XM,SFZH as ZJHM,XB_MC as XB,MZ,TGKKDM AS KKBH,TGKKMC AS KKMC,TGKKSSD AS KKSZDZ,TGSJ,RKSJ AS RYBSJ,CREATEDATE,ETLDATE from ${dataimporter.request.tableName} t where t.etldate>='${dataimporter.request.dateStart}' and t.etldate < '${dataimporter.request.dateEnd}'" >
</entity>
</document>
</dataConfig>
- 运行命令solrctl instancedir --create GX_SH_TL_TGRYXX_2015 /solr/test /GX_SH_TL_TGRYXX_2015,将配置上传到zookeeper中,以后可用命令solrctl instancedir --update GX_SH_TL_TGRYXX_2015 /solr/test /GX_SH_TL_TGRYXX_2015将修改后的配置更新到zookeeper中。
-
用命令solrctl collection --create GX_SH_TL_TGRYXX_2015 -s 3创建集合,GX_SH_TL_TGRYXX_2015是集合名称,当集合名称与前面上传的配置名相同时这里不需要指定配置名称,不同时需要用-c参数指定配置名称,-s 3这个参数指定该集合的分片数,我现在的集群中有3个solr节点,这样就会分片到3个节点上,3个节点数据不是重复的,其中一个节点挂掉时可以加上shards.tolerant=true参数进行查询,数据量只有之前的2/3。
2 手动入数据
通过上述步骤就创建好了集合了,以后要创建其他集合时,可以再solr管理界面看到,如下图:
先去掉Clean的复选框,选择dataconfig中创建的实体,Custom Parameters可以让我们传入自定义参数,我前面创建集合时定义了3个参数,表名和一个时间范围,这样就可以在不修改配置的情况下分片入多个表的数据到一个集合中了。
为什么会定义上面3个参数呢?因为一个SOLR中一个集合一般都对应oracle中多张表(数据量大,分年或分月),一张表中数据量达到几亿时,一次性入进去可能会报快照过旧,这样入进入的数据也无法区分,只能全部重新入,所有这里定义了个时间范围以减小每次入库的数据量避免快照过旧的问题,哪次入库报错就重入哪一次的数据。
如果需要分片入的次数不多的话,可以就在该管理界面人工调整参数入。
3 自动入数据
上面的按时间分片若分片过大就用不到索引,分片过小人工调整参数就不现实了。
于是一般的想法可以写java定时任务,定时检测入库状态,一次入库完成就自动调整参数入下一批数据。
我比较熟悉kettle,我这里使用的是kettle来完成这个工作,不熟悉kettle的就使用java定时任务就行了,存量数据入了还需要持续的入增量数据,这个是必须要有定时任务的。
自动入库每次都要记录日志,便于排查哪次数据入库失败,可以人工单独补进去。
Solr的dataimport有增量入库的方法,但没用过,自己写定时任务可以记录日志到数据库便于监控。
附件2是我正在使用的job,有存量入库和增量入库,我将其中的数据库信息删除了,无法直接运行,仅作参考,看不懂就自己写java吧。
如下两张图是job截图,具体还是用kettle打开看。
图- 1存量入库job示例
图- 2增量入库job示例
-
对应文档和附件:http://pan.baidu.com/s/1kTxptMv
-
附SOLR小知识
-
查询时在Raw Query Parameters对应的文本框中填入collection=collection1,collection2自定义参数,就可以查询多个集合。
-
删除一个查询结果的数据:http://slave3:8983/solr/GX_GA_JJZD_KKXX/update/?stream.body=<delete><query>ETLDATE:[20150106103453 TO 20150116103453]</query></delete>&commit=true
-
当集合分片中有分片损坏时,直接查询要报错,加上shards.tolerant=true参数可以忽略错误分片,只查询好的分片。
-
取消document唯一性检查(Disable unique document check):默认情况下,索引的时候Solr会检查主键是否有重复的,以避免不同的document使用相同的主键。如果你确认你的document不会有重复的主键,将参数allowDups=true加到url上可以取消检查,对于scv文档,使用overwrite=false。
- 根据用途设置字段类型,string类型是不会分词的,想实现如关系数据库的效果时最好用string类型,我就是开始没经验使用了text_general类型,讨了不少麻烦。
-
附Solrctl帮助
[root@slave1 conf]# solrctl --help
usage: /usr/bin/solrctl [options] command [command-arg] [command [command-arg]] ...
Options:
--solr solr_uri
--zk zk_ensemble
--help
--quiet
Commands:
init [--force]
instancedir [--generate path [-schemaless]]
[--create name path]
[--update name path]
[--get name path]
[--delete name]
[--list]
collection [--create name -s <numShards>
[-a Create collection with autoAddReplicas=true]
[-c <collection.configName>]
[-r <replicationFactor>]
[-m <maxShardsPerNode>]
[-n <createNodeSet>]]
[--delete name]
[--reload name]
[--stat name]
[--deletedocs name]
[--list]
core [--create name [-p name=value]...]
[--reload name]
[--unload name]
[--status name]
cluster [--get-solrxml file]
[--put-solrxml file]