简单实用的同步工具,实现mysql数据库中数据定期同步到elasticsearch,只需简单的配置,便能达到非凡的效果。
主要配置在spring/xml目录下面的四个xml文件中
git clone [email protected]:hainan-bigdata/elasticsearch-mysql.git
cd elasticsearch-mysql
mvn clean package
java -jar target/elasticsearch-mysql-0.0.1-SNAPSHOT.jar
$ curl -XGET "127.0.0.1:9200/data/comment/_search?pretty"
{
"took" : 34,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 39,
"max_score" : 1.0,
"hits" : [
{
"_index" : "data",
"_type" : "comment",
...
为了提供同步的效率和对数据库的压力,建议在配置是都采用增量同步的方式,前提是数据表中有设置与时间相关的字段,根据该字段每次同步只会同步新的数据,而不是把已经同步过的字段再同步一遍。
<bean class="cn.net.communion.sync.entity.JobInfo"
p:name="job2"
p:index="data"
p:type="comment"
p:cron="0/10 * * * * ?"
p:sql="select id,comment from tbl_comment where time > ?"
p:params="sys.lastTime2"
p:paramTypes="12"/>
在job2的配置中设置sql的条件为 time > ? ,而 ? 指的是 sys.lastTime2 ,这样每次同步都只会上次同步后更新的数据,sys.lastTime2 的名称可以随意更改,但是不要出现重复,每次同步完以后, 将开始同步的时间会为value, sys.lastTime2 作为 key 更新到sys.properties文件中。
sys.properties文件内容举例
#last job finish at
#Wed Dec 21 15:08:10 CST 2016
sys.lastTime2=2016-12-21T15\:08\:10.003
sys.lastTime1=2016-12-21T15\:08\:10.002
因此,要想实现全量同步也非常简单,只需将sys.properties文件删除即可, 当程序没有检测到sys.properties文件,便会将所有的数据同步到elasticsearch中。
采用quartz实现任务调度,最小的粒度可以到秒级,涉及quartz相关的代码主要在JobScheduler.java和Listener.java两个文件中
JobScheduler部分代码片段
public JobScheduler pushJobs(Collection<JobInfo> infos) {
infos.forEach(info -> {
JobDetail job = newJob(Task.class).withIdentity(info.getName(), "jobs").build();
job.getJobDataMap().put("jobInfo", info);
CronTrigger trigger = newTrigger().withIdentity(info.getName(), "triggers")
.withSchedule(cronSchedule(info.getCron())).build();
try {
scheduler.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
});
return this;
}
public boolean isRunning(String jobKey) {
try {
for (JobExecutionContext context : scheduler.getCurrentlyExecutingJobs()) {
if (context.getJobDetail().getKey().getName().equals(jobKey)) {
return true;
}
}
} catch (SchedulerException e) {
logger.info("get jobs status failed");
e.printStackTrace();
}
return false;
}
public void start() throws SchedulerException {
scheduler.start();
}
代码说明:
Listener部分代码片段
@Override
public void jobToBeExecuted(JobExecutionContext context) {
String jobKey = context.getJobDetail().getKey().getName();
boolean isCancel = JobScheduler.getInstance().isRunning(jobKey);
context.getJobDetail().getJobDataMap().put("cancel", isCancel);
}
代码说明: