logstash实现oracle到elastsearch的数据迁移
关键内容
- 增量抽取的处理方式
- 嵌套索引的处理方式
配置文件
input {
jdbc {
# oracle 数据库链接
jdbc_connection_string => "jdbc:oracle:thin:@127.0.0.1:1521/orcl"
# 驱动jar
jdbc_driver_library => "./oracle-ojdbc6-11.2.0.3.0.jar"
# 驱动类名
jdbc_driver_class => "oracle.jdbc.OracleDriver"
# 用户名和密码
jdbc_user => "sys"
jdbc_password => "sys"
# 开启增量模式
use_column_value => true
# 增量追踪字段
tracking_column => "dt_update"
# 增量字段类型:支持时间戳和数字 两种类型
tracking_column_type => "timestamp"
# 开启记录上一次锚点
record_last_run => true
# 上一次锚点存放位置
last_run_metadata_path => "./last_run.yml"
# 执行的sql
statement_filepath => "./statement.sql"
# 设置监听间隔 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新
schedule => "* * * * *"
# 字段转小写
lowercase_column_names => true
}
}
filter {
json {
source => "message"
}
mutate {
add_field=>{"[school][id]"=>"%{sc_id}"}
add_field=>{"[school][=schoolName]"=>"%{sc_school_name}"}
}
java_uuid {
target => "uuid"
}
}
output {
if[if_valid] == "1" {
elasticsearch {
# ES的IP地址及端口
hosts => ["127.0.0.1:9200"]
# 索引名称
index => "test_001"
# 需要关联的数据库中有有一个id字段,对应类型中的id
document_id => "%{uuid}"
document_type => "log"
}
}
stdout {
# JSON格式输出
codec => json_lines
}
}
执行sql的编写方式1
select
s.id as id,
s.student_name as student_name,
sc.id as sc_id,
sc.school_name as school_name,
s.dt_update as dt_update,
'1' as if_valid
from
student s
left join school sc
where
dt_update >= :sql_last_value
union
select
null,
null,
null,
null,
:sql_last_value + 1 as dt_update,
'0' as if_valid
from
dual
配置说明
关于增量的处理说明
数据断层
按区间增量抽取数据时,当数据不连贯出现断层时查询结果未空,dt_update不会变化,导致抽取失败。
解决方式
使用union在结果集中追加一条控制数据,避免空结果集的情况发生,并且可设置dt_update默认值,达到控制区间长短的效果。
另外添加if_valid字段,区分业务数据和控制数据,在output中使用if判断避免控制数据入库。
关于嵌套索引的处理说明
嵌套索引结构
mapping:{
student:{
id:{},
student_name:{}
school:{
id:{},
schoolName:{}
}
}
}
处理方式
使用mutate.add_field添加字段,使用占位符设定数据来源。
额外问题
当数据为空时,会使用把占位语法当做值来存储,而且遇到数据类型不一致时还会报错。
处理方法
使用if ![field] 先判定是否存在,存在再映射。if要写在mutate外层,语法繁琐暂为找到其他方式处理