elasticsearch配合mysql實現全文搜索


之前用了sphinx,發現很多東西很久都沒更新過了,之前只是知道有elasticsearch這個東西,還以為是java才能用,所以一直沒有去了解過,也許sphinx慢慢會被淘汰了吧。

前置條件:需要安裝jdk,並配置了 JAVA_HOME。

 

需要下載的東西

Elasticsearch:

https://www.elastic.co/products/elasticsearch

Logstash:

https://www.elastic.co/products/logstash

mysql-connector:

https://dev.mysql.com/downloads/connector/j/5.1.html

 

另外:可以安裝 kibana,有更友好的數據展示。

elasticsearch、logstash、kibana 的安裝在 mac 下可以 brew install

 

中文搜索需要安裝中文分詞插件(需要自己去github下載對應的版本 https://github.com/medcl/elasticsearch-analysis-ik/releases):

 

bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v5.5.1/elasticsearch-analysis-ik-5.5.1.zip

 

 

logstash 和 mysql-connector 是用來實現同步 mysql 數據到 elasticsearch 的。

logstash 配置:https://github.com/elastic/logstash/issues/3429

logstash 需要安裝 logstash-input-jdbc 插件:(這一步可能會卡很久,可能的原因是,這個插件使用ruby開發,安裝過程需要下載 gem,但是國外的源太慢。)

logstash/bin/plugin install logstash-input-jdbc

 

logstash 的配置使用查看:https://github.com/elastic/logstash/issues/3429

下面是本機測試配置:

input {
  jdbc {
    jdbc_driver_library => "/usr/local/elasticsearch/plugins/logstash/mysql-connector-java-5.1.44-bin.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://192.168.0.200:3306/vegent?characterEncoding=UTF-8&useSSL=false"
    jdbc_user => "test"
    jdbc_password => "test"
    statement => "SELECT * FROM vegent"
    jdbc_paging_enabled => "true"
    jdbc_page_size => "50000"
    schedule => "* * * * *"
  }
}

filter {
   json {
        source => "message"
        remove_field => ["message"]
    }
}

output {
  stdout {
    codec => rubydebug
  }
  elasticsearch {
    hosts => "192.168.0.200"
    index => "vegent"
  }        
} 

 

2018-06-02 更新:

上面的配置挖了個坑,因為沒有限制條件,而且指定了 schedule,所以會一直插入重復索引。

網上有說加以下條件就可以了(沒有實踐,不指定是否可行):

 WHERE id > :sql_last_value

 

啟動Logstash:logstash -f logstash-mysql.conf ,這個logstash-mysql.conf 就是上面的配置。

查看elasticsearch是否同步數據成功:curl '192.168.0.200:9200/_cat/indices?v',如果看到大小在增長則說明同步成功了。

 

附:解決 gem 下載慢的問題(使用淘寶源)

1、gem sources --add https://ruby.taobao.org/ --remove https://rubygems.org/

2、gem sources -l,確保只有 ruby.taobao.org,

如果 還是顯示 https://rubygems.org/ 進入 home的 .gemrc 文件
sudo vim ~/.gemrc
手動刪除 https://rubygems.org/

3、修改Gemfile的數據源地址,這個 Gemfile 位於 logstash 目錄下,修改 source 的值 為: "https://ruby.taobao.org",修改  Gemfile.jruby-1.9.lock, 找到 remote 修改它的值為: https://ruby.taobao.org (可能有幾個 remote 出現,修改后面是 url 那個,替換掉 url)。

4、安裝 logstash-input-jdbc,按上面的命令。

5、關於同步的問題,上面設置了一分鍾一次,並且無條件同步,實際上是可以只同步那些更新過的數據的,這里還沒來得及做深入研究。而且上面的配置還有個問題是,只做插入,而不是更新原有數據,這樣其實並不是我們想要的結果。

 

更新:sql 語句里面可以配置只同步更新過的數據,但是這個更新需要我們去定義,好比如,數據庫有一個 update_time 字段,我們更新的時候更新該字段(timestamp類型),這樣我們可以把 sql 語句寫為 "SELECT * FROM vegent where update_time > :sql_last_value",這個 sql_last_value 在這個時候會是上一次執行該 sql 的時間戳,這樣也就實現了更新操作。另外還有一個問題是,elasticsearch 和 logstash 默認使用 UTC 時間戳,這樣如果我們保存的是 PRC 時區的時間戳,這樣就會有問題,因為這樣 logstash 的同步語句中的時間戳是 -8:00 的,所以,還要在配置文件中加上:jdbc_default_timezone => "UTC",最后如下:

最后發現這樣雖然 sql 語句時間戳正常了,但是建立的索引里面的時間戳還是 UTC 的時間戳。

最后把 UTC 改為 PRC,最后都正常了,還是和上面一樣的情況,索引里面的 @timestamp 還是 UTC 的時間戳。

google 了一下,發現這個好像是不能配置的。這樣怎么辦呢,也許可以保存 UTC 的時間戳吧,取數據的時候再轉 PRC 。(后面證實了這個猜想有點多余,還是應該使用 UTC)

上圖鏈接:https://discuss.elastic.co/t/how-to-set-timestamp-timezone/28401

另外一個猜想是:其實這個@timestamp 對我們的同步更新數據沒影響,后來想想發現也是,其實沒影響:

 上圖中, :sql_last_value 是我們上一次進行 sql 查詢的時間。而不是我之前以為的索引里面的 @timestamp 字段,想想也對,如果索引有 100w 數據,那么我應該取那一條記錄的 @timestamp 作為 :sql_last_value 呢?

 

所以結論還是,jdbc_default_timezone 使用 UTC 就可以了。有個需要注意的問題是 時間戳字段要使用 mysql 的timestamp。

 

jdbc {
    jdbc_driver_library => "/home/vagrant/logstash/mysql-connector-java-5.1.44-bin.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://192.168.0.200:3306/test?characterEncoding=UTF-8&useSSL=false"
    jdbc_user => "test"
    jdbc_password => "test"
    jdbc_default_timezone => "UTC"
    statement => "SELECT * FROM test where update_time > :sql_last_value"
    jdbc_paging_enabled => "true"
    jdbc_page_size => "50000"
    schedule => "* * * * *"
  }

 

查詢例子:

curl 'localhost:9200/vegent/_search?pretty=true'  -d '
{
  "query" : { "match" : { "type" : "冬瓜" }}
}'

輸出(一部分):

查詢 type 字段包含了 "冬瓜" 的所有記錄。vegent 是索引的名稱。?pretty=true 是指定友好輸出格式。

返回結果的 took字段表示該操作的耗時(單位為毫秒),timed_out字段表示是否超時,hits字段表示命中的記錄,里面子字段的含義如下。
  total:返回記錄數,本例是487893條。
  max_score:最高的匹配程度,本例是5.598418。
  hits:返回的記錄組成的數組。

 

logstash 文檔地址:https://www.elastic.co/guide/en/logstash/index.html

 

其他問題:

1、無法遠程連接,默認只允許本機連接,可以修改配置文件 elasticsearch/config/elasticsearch.yml

# Set the bind address to a specific IP (IPv4 or IPv6):
#
#network.host: 192.168.0.1
transport.host: localhost
transport.tcp.port: 9300
http.port: 9200
network.host: 0.0.0.0

2、上面的 "同步",並不是真正的同步,當有新數據的時候,上面做的只是把新數據繼續加到索引里面,而不是根據對應的 id 去刪除原來的數據,這些需要自己做其他操作,目前還沒做深入了解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM