将MySQL数据库记录通过Logstash同步到ElasticSearch

上一篇文章中(https://www.jianshu.com/p/2ab284351eda)介绍了ELK(ElasticSearch、Logstash、Kibana)的安装了,这里是接上篇文章往下讲。本文使用的ELK版本是8.2.2,数据库用的是MySQL8.0,其他的像Oracle、SQL Server等数据库只要有JDBC驱动程序也可以的。

一、创建数据库表及录入测试记录

在mysql或其他数据库中创建一个test表,字段名和记录如下图:


mysql表

二、用Kibana开发工具,创建索引

kibana首页

在浏览器中输入地址 http://ip地址:5601/ 进入Kibana的管理界面,依次点击上图中的①,②从菜单进入“开发工具”,或者点③直接进入“开发工具”。如下图:
Kibaba开发工具控制台

在上图的控制台左边输入上图的内容,然后点击①位置的绿色的三角形图标执行创建索引及mapping的请求。因为我已经创建成功了,第二次再执行,就报错“资源已存在”了。请求体内容如下:

PUT /mysql-test
{
    "mappings" : {
      "dynamic" : "false",
      "properties" : {
        "addr" : {
          "type" : "text",
          "analyzer" : "ik_max_word",
          "search_analyzer" : "ik_smart"
        },
        "birthday" : {
          "type" : "date",
          "format":"yyyy-MM-dd"
        },
        "create_time" : {
          "type" : "date",
          "format":"yyyy-MM-dd HH:mm:ss"
        },
        "name" : {
          "type" : "text",
          "analyzer" : "ik_max_word",
          "search_analyzer" : "ik_smart"
        }
      }
    }
  }

索引和mapping介绍

ElasticSearch(简称:ES)中的索引感觉是对应一张数据库中的表,mapping相当于字段类型及解析的定义。“PUT”后面的"mysql-test"即为要创建的索引名称,上面的JSON就是这个索引的mapping定义。如果是英文搜索,完全可以不用定义mapping,因为会生成动态的映射;但是对于中文搜索要配置中文分词器,就必须定义mapping了。

分词器介绍

对于数据库中的字符串类型,如果不需要模糊搜索,就设置为“keyword”类型就可以了,如果需要模糊搜索,就设置为“text”类型,再配置分词器。上面的name和addr两个字段都配置分词器,"analyzer" : "ik_max_word", "search_analyzer" : "ik_smart"。ik中文分词器是之前安装的ES插件,它又分为ik_max_word和ik_smart两种。

举例说明一下:“中华人民共和国国歌”用系统默认的分词器会把每个字都拆开,拆成9个单字的关键词,显然这不符合中文的搜索习惯,我不会用“人”或“和”来搜索,这样匹配的结果太多了,不够精确;

如果用"ik_smart"来分词只会得到: "中华人民共和国", "国歌"两个没有交叉的关键词;
用"ik_max_word"来分词就会用各种组合得到更多的关键词:"中华人民共和国","中华人民", "中华", "华人","人民共和国","人民","共和国","共和","国","国歌"。根据你想要更精确还是更多的搜索结果,来选择适合你们的分词器。我们一般是加入文档(文档是ES中的名词,对应数据库中的一行记录;在其他场景中也可能是一个日志文件)到索引的时候用ik_max_word,搜索的关键词用ik_smart来分词。

为什么不用postman

Kibana开发工具和postman的作用差不多,都可以向ES发送http请求调用restful接口,来执行操作。我觉得它比postman更好用,主要是有提示和补全,可以提示URL,搜索接口的字段名也可以自动补全,这样就减少出错、效率更高,还不用写URL前缀和端口更简洁。Kibana主要是用来图形界面来监测、分析、展示ES的,当然如果你喜欢用命令行,可以不用安装,甚至用curl命令也可以。

三、用Logstash同步数据库记录

用数据表的“创建时间”或“最后修改时间”字段来定时查询出要更新或插入的记录,然后用Logstash中的Jdbc input plugin同步到ES中。对于物理删除的记录,是没办法同步的;建议用逻辑删除,比如加is_del字段,这样是可以同步is_del字段到ES中,在ES中查询的时候可以排除is_del=1的文档,或者定期删除这些文档。

下载数据库JDBC驱动程序

我用的是mysql-connector-java-8.0.28.jar,放在了/opt/logstash-8.2.2/lib目录下。没有的话可以去这里下载:https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.28/mysql-connector-java-8.0.28.jar

配置Logstash

在/opt/logstash-8.2.2/config 目录下创建一个jdbc.conf文件,文件内容如下:

input {
    jdbc {
      # 数据库连接字符串
      jdbc_connection_string => "jdbc:mysql://192.168.50.101:3306/testdb?useUnicode=true&characterEncoding=UTF-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8"
      # 数据库登录名
      jdbc_user => "loan"
      # 登录密码
      jdbc_password => "12345678"
      # jdbc驱动程序包路径
      jdbc_driver_library => "/opt/logstash-8.2.2/lib/mysql-connector-java-8.0.28.jar"
      # 驱动程序类名
      jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
      # 是否分页
      jdbc_paging_enabled => "true"
      # 每页几条记录
      jdbc_page_size => "10000"
      # 同步查询语句,:sql_last_value变量为上次同步时间,程序会记录下来,如果第一次同步则为1970-1-1
      # mapping中日期类型字段我定义了格式,为了避免报错,我就在SQL语句中格式化为字符类型
      statement => "SELECT id,NAME,DATE_FORMAT(birthday,'%Y-%m-%d') AS birthday,addr,DATE_FORMAT(create_time,'%Y-%m-%d %H:%i:%s') AS create_time FROM test WHERE create_time>= :sql_last_value "
      # 同步频率,cron表达式,不会的可以百度一下;这样是每分钟执行一次
      schedule => "* * * * *"
      # 时区,一定要配置,不然 :sql_last_value变量会少了8小时
      jdbc_default_timezone => "Asia/Shanghai"
      type => "jdbc"
    }
}
filter {
}
output {
      elasticsearch {
       # ES索引名称
        index => "mysql-test"
       # ES文档ID,配置表的主键字段
        document_id => "%{id}"
    hosts => ["localhost:9200"]
      }
}

启动Logstach同步

上面配置了输入来源自JDBC的查询结果,输出到ES指定的索引中。然后运行Logstach就可以,命令如下:

cd /opt/logstash-8.2.2/bin
./logstash -f config/jdbc.conf &

详细的命令参数可以用-h来查看,比如:./logstash -h ,./elasticsearch -h

查询同步的结果

搜索结果

按上图左边红框中的输入,点击绿色三角形图标,右边显示查询出的两条记录,为了方便展示我收起了一条记录。

四、Java集成开发

至此你大概知道怎样建立一个搜索引擎了,最终的呈现还需要在程序中调用restful接口来获取查询结果。在Java中,你可以使用elasticsearch-rest-high-level-client类库来操作ES的各个接口,具体使用可以参考:https://zhuanlan.zhihu.com/p/143786937 或者官方文档:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.17/java-rest-high-document-index.html

从官方文档看到elasticsearch-rest-high-level-client从7.15版本后,官方就放弃了;推出的新的Java Api Client ,新的API中少了很多接口(比如:集群、安全、管道),只专注在搜索这一块:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/indexing.html。但官方的介绍中又说可以兼容方式同时使用新旧的API

其实我们可以用spring-data-elasticsearch类似,spring封装了之后,使用起来更文件。4.4类库中是同时引用了elasticsearch官方提供新、旧的类库,这样我们就不用关心官方的API版本了,用spring封装的就完事了。


spring-data-elasticsearch 4.4.2

如果你会使用了API调用,完全可以用编码实现代替Logstash数据采集;你甚至可以不用Logstach和Kibana这两个工具,完全用java代码+elasticsearch来实现。如何java编码实现呢?可以看看下一篇文章: https://www.jianshu.com/p/0c1f0de6bd8e

你可能感兴趣的:(将MySQL数据库记录通过Logstash同步到ElasticSearch)