前言
数据库中的数据如何采集到es的索引库呢?手动添加肯定是不可能的,数据量庞大的话可以使用logstash这款工具来进行数据的采集,这里记录一下logstash的简单用法。
1、logstash介绍
Logstash是一个轻量级、开源的服务器端数据处理管道,允许您从各种来源收集数据,进行动态转换,并将数据发送到您希望的目标。它最常用作Elasticsearch的数据管道,Elasticsearch 是一个开源分析和搜索引擎。由于它与 Elasticsearch 紧密集成,具备强大的日志处理功能并提供 200 多个预构建的开源插件来帮助您轻松地索引数据,因此 Logstash 是将数据加载到 Elasticsearch 的常用工具。
2、logstash的优点
- 轻松加载非结构化数据
Logstash 让您能够轻松接收来自多种数据源 (包括系统日志、网站日志和应用程序服务器日志) 的非结构化数据。 - 预构建的筛选条件
Logstash可以提供预构建的筛选条件,因此您可以随时转换常见的数据类型、在Elasticsearch中对其编制索引并开始查询,而无需构建自定义数据转换管道。 - 灵活的插件架构
Github 上已经发布了 200 多个插件,因此您很有可能利用他人构建的插件来自定义自己的数据管道。但如果插件没有符合您的要求,您可以轻松地自行创建一个。
3、logstash的使用
(1)下载
从官网下载logstash,这里下载6.2.1版本,和elasticsearch版本一样。解压后的文件夹内容如下:
bin目录下是一些可执行文件:
config目录下是一些配置文件:
其他目录这里就略过了。
(2)安装logstash-input-jdbc
logstash-input-jdbc 是ruby开发的,先下载ruby并安装。Logstash5.x以上版本本身自带有logstash-input-jdbc,6.x版本本身不带logstash-input-jdbc插件,需要手动安装,安装好以后查看:
(3)创建模板文件
Logstash的工作是从MySQL中读取数据,向ES中创建索引,这里需要提前创建mapping的模板文件以便logstash使用。这里有2个模板文件,因为等一下准备创建2个索引库。
xc_course_template.json如下:
{
"mappings" : {
"xc_course" : {
"_source" : {
"excludes" : [ "teachplan", "description", "content" ]
},
"properties" : {
"content" : {
"analyzer" : "ik_max_word",
"type" : "text"
},
"description" : {
"copy_to" : [ "content" ],
"type" : "text"
},
"grade" : {
"type" : "keyword"
},
"id" : {
"type" : "keyword"
},
"mt" : {
"type" : "keyword"
},
"name" : {
"type" : "text",
"analyzer" : "ik_max_word"
},
"users" : {
"index" : false,
"type" : "text"
},
"charge" : {
"type" : "keyword"
},
"valid" : {
"type" : "keyword"
},
"pic" : {
"index" : false,
"type" : "keyword"
},
"qq" : {
"index" : false,
"type" : "keyword"
},
"price" : {
"type" : "float"
},
"price_old" : {
"type" : "float"
},
"st" : {
"type" : "keyword"
},
"status" : {
"type" : "keyword"
},
"studymodel" : {
"type" : "keyword"
},
"teachmode" : {
"type" : "keyword"
},
"teachplan" : {
"copy_to" : [ "content" ],
"type" : "text"
},
"expires" : {
"type" : "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"pub_time" : {
"type" : "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"start_time" : {
"type" : "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"end_time" : {
"type" : "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
},
"template" : "xc_course"
}
xc_course_media_template.json如下:
{
"mappings":{
"doc":{
"properties":{
"courseid":{
"type":"keyword"
},
"teachplan_id":{
"type":"keyword"
},
"media_id":{
"type":"keyword"
},
"media_url":{
"index":false,
"type":"text"
},
"media_fileoriginalname":{
"index":false,
"type":"text"
}
}
}
},
"template":"xc_course_media"
}
这两个json格式的模板其实都和索引库的映射是对应的。
(4)conf配置文件
xc_course_template.json对应的配置文件为mysql.conf,内容如下:
input {
stdin {
}
jdbc {
# 连接的数据源
jdbc_connection_string => "jdbc:mysql://rm-m5e130nm7h37n6v982o.mysql.rds.aliyuncs.com:3306/xc_course?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC"
# 用户名
jdbc_user => "xxxxxxx"
# 密码
jdbc_password => xxxxxx
# 数据库连接驱动包的位置
jdbc_driver_library => "C:/dev/mysql/mysql-connector-java-8.0.12.jar"
# 连接驱动
jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
#要执行的sql文件
#statement_filepath => "/conf/course.sql"
statement => "select * from course_pub where timestamp > date_add(:sql_last_value,INTERVAL 8 HOUR)"
#定时配置
schedule => "* * * * *"
record_last_run => true
last_run_metadata_path => "C:/dev/elasticsearch/logstash-6.2.1/config/logstash_metadata"
}
}
output {
elasticsearch {
#ES的ip地址和端口
hosts => "121.42.xxx.xxx:9200"
#hosts => ["121.42.xxx.xxx:9200","121.42.xxx.xxx:9201]
#ES索引库名称
index => "xc_course"
#类型
document_type => "doc"
#指定主键
document_id => "%{id}"
#模板文件位置
template =>"C:/dev/elasticsearch/logstash-6.2.1/config/xc_course_template.json"
template_name =>"xc_course"
template_overwrite =>"true"
}
stdout {
#日志输出
codec => json_lines
}
}
这个配置文件要采集的是这张表的数据:
其中有一个timestamp字段:
这个是logstash采集数据所需要的。
上面的配置文件中有一行:
last_run_metadata_path => "C:/dev/elasticsearch/logstash-6.2.1/config/logstash_metadata"
需要在config目录下创建一个logstash_metadata文件,里面是一个时间戳,这个时间戳必须在数据表中最早记录时间的前面,也就是必须要早于2018-04-27 22:57:24。
logstash_metadata如下:
--- 2018-04-26 11:50:00.881000000 Z
xc_course_media_template.json对应的配置文件为mysql_media.conf,内容如下:
input {
stdin {
}
jdbc {
jdbc_connection_string => "jdbc:mysql://rm-m5e130nm7h37n6v982o.mysql.rds.aliyuncs.com:3306/xc_course?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC"
jdbc_user => "xxxxxx"
jdbc_password => xxxxxxx
jdbc_driver_library => "C:/dev/mysql/mysql-connector-java-8.0.12.jar"
# the name of the driver class for mysql
jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
#要执行的sql文件
#statement_filepath => "/conf/course.sql"
statement => "select * from teachplan_media_pub where timestamp > date_add(:sql_last_value,INTERVAL 8 HOUR)"
#定时配置
schedule => "* * * * *"
record_last_run => true
last_run_metadata_path => "C:/dev/elasticsearch/logstash-6.2.1/config/media_metadata"
}
}
output {
elasticsearch {
#ES的ip地址和端口
hosts => "121.42.xxxx.xxxxx:9200"
#hosts => ["121.42.xxxx.xxxx:9200","121.42.xxx.xxxx:9201]
#ES索引库名称
index => "xc_course_media"
document_type => "doc"
document_id => "%{teachplan_id}"
template =>"C:/dev/elasticsearch/logstash-6.2.1/config/xc_course_media_template.json"
template_name =>"xc_course_media"
template_overwrite =>"true"
}
stdout {
#日志输出
codec => json_lines
}
}
这个配置文件要采集的是这张表的数据:
其中也有个timestamp的字段:
在config目录下创建media_metadata文件,内容如下:
--- 2020-12-08 11:50:00.877000000 Z
这个时间戳也必须小于表中最早记录时间的时间戳。
(5)创建索引库
使用head插件创建两个索引库:
映射如下:
(6)数据采集
进入到logstash的bin目录,右键此处打开命令,输入:
logstash.bat -f ..\config\mysql.conf
这是加载mysql.conf配置文件,点击回车:
采集完毕,刷新es节点,查看head:
一共采集到12条数据,然后查看数据表:
也是12条,没问题。
还需要启动一个logstash实例,命令:
logstash.bat -f ../config/mysql_media.conf --path.data=/data2/
采集完毕,head查看:
采集到8条数据,查看数据表:
也是8条数据,没问题。
这是总的。需要说明一个问题,就是单实例logstash的话,它会将data文件夹作为输出目录:
默认的,所以启动单实例logstash时无需指定输出目录,它默认到data目录了,如果是多实例,采集多张数据表,那么在启动的时候必须指定输出目录,如下:
logstash.bat -f ../config/mysql_media.conf --path.data=/data2/
这里指定到了data2目录,这个目录是我创建的。
其实这个目录应该创建在logstash的根目录的,我是创建在c盘根目录,这里就不管了。
4、总结
使用logstash可以将数据很快的从数据源中采集到elasticsearch索引库中,非常方便,每当数据表新增或更新时,只要时间戳变了,那么logstash就会自动将新增或修改的数据采集到索引库。但是也有个问题,如果数据表中删除了一条数据,索引库是不会删除的,还会保留,就是说添加和修改会同步数据,可是删除不会同步,怎么解决这个问题,暂时不知道。