使用solrj进行DIH操作
背景说明:在一个项目中需要将Mongodb中的数据导入到solr中完成搜索。在solr中Mysql数据库有对应的DIH包,可以通过配置sql语句完成数据的导入。Mongodb下也有开源的工具用来实现数据的导入。看了下文档,感觉这个工具对数据的定制性不高,并且是python的,不是很满足项目需求。最后决定使用solrj来完成数据的导入。
一、 遇到的问题
1. 全量数据很大,在全量或者增量时无法一次性将数据全部获取: 对数据进行分页获取。(关于两种分页获取数据的性能问题,后面会单独介绍)
2. 全量在更新数据时,需要将之前的老数据clean掉,增量则不需要: clean其实就是删除所有数据。
3. 由于使用了分页获取数据,全量的clean操作必须是在全量开始之前完成,并且为了保证在做全量过程中,之前的老数据不会丢失,删除全部数据的操作对应的commit==false,且在整个全量过程中commit==false, 在最后完成全量后,再进行commit。
4.增量操作和全量操作是通过配置不同的trigger完成的,比如增量每隔五分钟执行一次,全量则一天执行一次。如果没有对任务进行控制,可能会造成 全量和增量同时在做。刚才说了,全量操作的整个过程,commit==false, 所以对增量和全量的任务必须加互斥锁。
二、相关的实现
- package com.meizu.galaxy2.solr;
- import org.apache.log4j.Logger;
- import org.apache.solr.client.solrj.SolrQuery;
- import org.apache.solr.client.solrj.SolrServerException;
- import org.apache.solr.client.solrj.impl.CloudSolrClient;
- import org.apache.solr.client.solrj.request.UpdateRequest;
- import org.apache.solr.common.SolrInputDocument;
- import org.apache.solr.common.params.ModifiableSolrParams;
- import java.io.IOException;
- import java.lang.reflect.Field;
- import java.util.List;
- /**
- * Created by ltao on 2015-7-16.
- */
- public class CloudSolrDIHClient {
- private static final Logger logger = Logger.getLogger(CloudSolrDIHClient.class);
- private static final String ID_FILED_NAME = "id";
- private CloudSolrClient solrClient;
- private static final int BATCH_SIZE=500;
- private String defaultCollection;
- public CloudSolrDIHClient(String zkHost, String zkNodePath, int zkClientTimeout, int zkConnectTimeout, String defaultCollection) {
- if (!zkHost.startsWith("zookeeper")) {
- logger.error("zk host must start with zookeeper://");
- return;
- } else {
- String hosts = zkHost.substring(12);
- hosts = hosts + zkNodePath;
- solrClient = new org.apache.solr.client.solrj.impl.CloudSolrClient(hosts);
- solrClient.setZkClientTimeout(zkClientTimeout);
- solrClient.setZkConnectTimeout(zkConnectTimeout);
- this.defaultCollection = defaultCollection;
- }
- }
- public void connect() throws Exception {
- solrClient.connect();
- }
- public void addDoc(SolrInputDocument doc) {
- if (this.defaultCollection != null) {
- this.addDoc(defaultCollection, doc);
- } else {
- logger.error("default collection should not be null");
- }
- }
- public void addDoc(String collection, SolrInputDocument doc) {
- try {
- solrClient.add(collection, doc);
- } catch (Exception e) {
- logger.error("add Doc occurs an error,collection:" + collection + ",doc_id:" + doc.getFieldValue(ID_FILED_NAME), e);
- }
- }
- public void addDocs(List<SolrInputDocument> docs) {
- if (this.defaultCollection != null) {
- this.addDocs(defaultCollection, docs);
- } else {
- logger.error("default collection should not be null");
- }
- }
- public void addDocs(String collection, List<SolrInputDocument> docs) {
- if(docs!=null && docs.size()>0) {
- int size=docs.size();
- if(size<=BATCH_SIZE) {
- try {
- solrClient.add(collection, docs);
- } catch (Exception e) {
- logger.error("add Docs occurs an error,collection:" + collection, e);
- }
- }
- else
- {
- int end=size>BATCH_SIZE? BATCH_SIZE:size;
- int start=0;
- while(true)
- {
- List<SolrInputDocument> subList=docs.subList(start,end);
- try {
- solrClient.add(collection, subList);
- } catch (Exception e) {
- logger.error("add Docs occurs an error,collection:" + collection, e);
- }
- if(end==size)
- {
- break;
- }
- start=start+BATCH_SIZE;
- end=(end+BATCH_SIZE);
- if(end>size)
- {
- end=size;
- }
- }
- }
- }
- }
- public void deleteDocByIds(List<String> ids) {
- if (this.defaultCollection != null) {
- this.deleteDocByIds(defaultCollection, ids);
- }
- }
- public void deleteDocByIds(String collection, List<String> ids) {
- try {
- solrClient.deleteById(collection,ids);
- } catch (Exception e) {
- logger.error("delete Docs occurs an error,collection:" + collection ,e);
- }
- }
- public void deleteDocById(String collection, String id) {
- try {
- solrClient.deleteById(collection, id);
- } catch (Exception e) {
- logger.error("delete Doc occurs an error,collection:" + collection + ",doc_id:" + id, e);
- }
- }
- public void deleteDocById(String id) {
- if (this.defaultCollection != null) {
- this.deleteDocById(defaultCollection, id);
- } else {
- logger.error("default collection should not be null");
- }
- }
- public void addBean(String collection, Object obj) {
- try {
- solrClient.addBean(collection, obj);
- } catch (Exception e) {
- String id = null;
- try {
- Field idFiled = obj.getClass().getDeclaredField(ID_FILED_NAME);
- if (idFiled != null) {
- idFiled.setAccessible(true);
- Object idFiledValue = idFiled.get(obj);
- id = idFiledValue != null ? idFiledValue.toString() : "";
- }
- } catch (Exception e1) {
- logger.error("get id field occurs an error", e1);
- }
- logger.error("add bean occurs an error,collection:" + collection + ",bean_id:" + id, e);
- }
- }
- public void addBean(Object obj) throws SolrServerException, IOException {
- if (this.defaultCollection != null) {
- this.addBean(defaultCollection, obj);
- } else {
- logger.error("default collection should not be null");
- }
- }
- public void addBeans(List<Object> objs) throws SolrServerException, IOException {
- if (this.defaultCollection != null) {
- this.addBean(defaultCollection, objs);
- } else {
- logger.error("default collection should not be null");
- }
- }
- public void addBeans(String collection, List<Object> objs) {
- if(objs!=null && objs.size()>0) {
- int size=objs.size();
- if(size<=BATCH_SIZE) {
- try {
- solrClient.addBeans(collection, objs);
- } catch (Exception e) {
- logger.error("addBeans occurs an error,collection:" + collection, e);
- }
- }
- else
- {
- int end=size>BATCH_SIZE? BATCH_SIZE:size;
- int start=0;
- while(true)
- {
- List<Object> subList=objs.subList(start,end);
- try {
- solrClient.addBeans(collection, subList);
- } catch (Exception e) {
- logger.error("addBeans occurs an error,collection:" + collection, e);
- }
- if(end==size)
- {
- break;
- }
- start=start+BATCH_SIZE;
- end=(end+BATCH_SIZE);
- if(end>size)
- {
- end=size;
- }
- }
- }
- }
- }
- public void commit() throws SolrServerException, IOException {
- this.commit(defaultCollection);
- }
- public void commit(String collection) throws SolrServerException, IOException {
- solrClient.commit(collection);
- }
- public void clean(Boolean clean) throws SolrServerException, IOException {
- this.clean(defaultCollection, clean);
- }
- public void clean(String collection, Boolean clean) throws SolrServerException, IOException {
- UpdateRequest updateRequest = new UpdateRequest();
- updateRequest.setParam("stream.body", "<delete><query>*:*</query></delete>");
- updateRequest.setParam("commit", Boolean.toString(clean));
- solrClient.request(updateRequest, collection);
- }
- public void close() throws IOException {
- if (solrClient != null) {
- solrClient.close();
- }
- }
- }
上面是对solrclient的简单封装:增加、删除、clean
全量和增量进行加锁互斥
- private static Lock lock = new ReentrantLock();
- public void importDelta() {
- boolean hasGetLock = false;
- try {
- hasGetLock = lock.tryLock();
- if (hasGetLock) {
- logger.info("start import delta hotel data ");
- long start = System.currentTimeMillis();
- hotelService.importDelta();
- long end = System.currentTimeMillis();
- logger.info("finish import delta hotel data ,spend " + (end - start) + " ms");
- }
- } finally {
- if (hasGetLock) {
- lock.unlock();
- }
- }
- }
- public void importAll() {
- try {
- lock.lock();
- logger.info("start import all hotel data ");
- long start = System.currentTimeMillis();
- hotelService.importAll();
- long end = System.currentTimeMillis();
- logger.info("finish import all hotel data ,spend " + (end - start) + " ms");
- } finally {
- lock.unlock();
- }
- }
- public DataImportService getHotelService() {
- return hotelService;
- }
这里用了Lock的tryLock,tryLock()会尝试获取锁,如果当前锁已被使用,则放弃该次获取锁操作。lock()则会阻塞,直到获取到锁。这样可以较大概率的保证全量一定能够执行。(如果增量一直都在运行,可能会造成全量一直阻塞,在实际运行中不会遇到这种情况;或者在某种机缘巧合下,增量一个接一个的获取到了锁,全量则一直阻塞,个人觉得应该可以使用公平锁解决刚才的这个问题,不过其实没必要)。
使用solrj进行DIH操作的更多相关文章
- solr的客户端操作:使用solrj进行curd操作
导入相关的jar包 <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-s ...
- solr+mongo-connector+mongdb+tomcat集成
话题:solr安装 一.下载solr 本例采用4.10.3版本. Solr所有版本下载地址:http://archive.apache.org/dist/lucene/solr/ 下载完成后,解压的目 ...
- Solr DataImportHandler 配置
DIH主要用于从数据库抓取数据并创建索引.另外还能够从HTTP(RSS.ATOM)拉数据. 相关概念: Datasource:数据源,包含获取数据必需的信息:数据位置(url).数据库driver.登 ...
- Solrj和Solr DIH索引效率对比分析
测试软件环境: 1.16G windows7 x64 32core cpu . 2.jdk 1.7 tomcat 6.x solr 4.8 数据库软件环境: 1.16G windows7 x64 ...
- 使用solrj操作solr索引库
(solrj)初次使用solr的开发人员总是很郁闷,不知道如何去操作solr索引库,以为只能用<五分钟solr4.5教程(搭建.运行)>中讲到的用xml文件的形式提交数据到索引库,其实没有 ...
- 使用solrj操作solr索引库,solr是lucene服务器
客户端开发 Solrj 客户端开发 Solrj Solr是搭建好的lucene服务器 当然不可能完全满足一般的业务需求 可能 要针对各种的架构和业务调整 这里就需要用到Solrj了 Solrj是Sol ...
- 利用SolrJ操作solr API完成index操作
使用SolrJ操作Solr会比利用httpClient来操作Solr要简单.SolrJ是封装了httpClient方法,来操作solr的API的.SolrJ底层还是通过使用httpClient中的方法 ...
- Solr 14 - SolrJ操作SolrCloud集群 (Solr的Java API)
目录 1 pom.xml文件的配置 2 SolrJ操作SolrCloud 1 pom.xml文件的配置 项目的pom.xml依赖信息请参照: Solr 09 - SolrJ操作Solr单机服务 (So ...
- Solr 09 - SolrJ操作Solr单机服务 (Solr的Java API)
目录 1 SolrJ是什么 2 SolrJ对索引的CRUD操作 2.1 创建Maven工程(打包方式选择为jar) 2.2 配置pom.xml文件, 加入SolrJ的依赖 2.3 添加和修改索引 2. ...
随机推荐
- Nginx高性能服务器安装、配置、运维 (2) —— Nginx安装
三.Nginx 安装 使用SecureCRT以Root身份登录阿里云,在安装Nginx前先做好阿里云磁盘挂载 -------------- 挂载磁盘 -------------- 1.df -h #显 ...
- Java并发——线程池Executor框架
线程池 无限制的创建线程 若采用"为每个任务分配一个线程"的方式会存在一些缺陷,尤其是当需要创建大量线程时: 线程生命周期的开销非常高 资源消耗 稳定性 引入线程池 任务是一组逻辑 ...
- R-大数据分析挖掘(4-R爬虫实现)
library("XML") #获取全部的链接 url <- 'http://www.csdn.net/tag/' i_url_parse<-htmlParse(ur ...
- (转)使用OpenVPN的一些注意事项
原文地址:http://www.365mini.com/page/16.htm 本文介绍的只是OpenVPN连接或使用过程中的一些注意事项,如果你尚未下载安装OpenVPN,你可以点击查看OpenVP ...
- JavaScript中的Date
Date 对象用于处理日期和时间. var myDate=new Date() Date 对象会自动把当前日期和时间保存为其初始值. Date常用方法有: myDate.getYear(); //获取 ...
- ASP.NET的GET和POST方式的区别归纳总结
表单提交中,ASP.NET的Get和Post方式的区别归纳如下 几点: 1. get是从服务器上获取数据,post是向服务器传送数据. 2. get是把参数数据队列加到提交表单的ACTION属性所指 ...
- Java---Hibernate>>Can't create table './xxx/#sql-b2c_1a.frm' (errno: xxx)解决方法
通用方案:删除相关表,重新生成. 1.关联表之间数据引擎不一致导致: 修改相关表的引擎设定,保持一致. 2.关联表索引字段的引用类型不一样(如A表关联字段是int,B表索引是char): 修改相关表的 ...
- Ubuntu 之旅—— 调整扩展屏分辨率
打开终端输入 xrandr 得到如下信息 Screen 0: minimum 320 x 200, current 2390 x 768, maximum 8192 x 8192 LVDS conne ...
- ubuntu logout 命令
gnome-session-quit 点击打开链接http://askubuntu.com/questions/15795/how-can-you-log-out-via-the-terminal
- php ini_set('display_errors', $value)
正常情况下,在开发模式中,把错误显示出来,方便纠正,但在布署模式中,就得把错误关闭: ini_set('display_errors', 1); // 开启 ini_set('display_erro ...