ElasticSearch + Logstash進行資料庫同步

fallinjava發表於2019-04-01

介紹

在我們使用mysql和elasticsearch結合使用的時候,可能會有一些同步的需求,想要資料庫和elasticsearch同步的方式其實有很多。

可以使用canal,它主要是監聽mysql的binlog 日誌,可以監聽資料的一些變化,如果資料發生了變化我們需要做什麼邏輯,這些都是可以人為實現的,它是將自己模擬成一個slave節點,當master節點的資料發生變化是,它能夠看到資料的變化。但是缺點也很明顯,由於是java實現的,所以比較重,還需要使用zookeeper等叢集管理工具來管理canal節點,所以本文暫時不介紹這種方式。

本文主要介紹使用Logstash JDBC的方式來實現同步,這個方式同步比較簡單。當然它有一些缺點,就是有點耗記憶體(記憶體大就當我沒說?)。

最終效果展示

  1. 先看下ElasticSearch的資料, 這要好分辨效果,從響應結果可以看到現在有id為1,2,3的三條資料。 執行查詢語句
GET /myapp/_search
{
  "_source": "id"
}
複製程式碼

響應結果

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "2",
        "_score": 1,
        "_source": {
          "id": 2
        }
      },
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "1",
        "_score": 1,
        "_source": {
          "id": 1
        }
      },
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "3",
        "_score": 1,
        "_source": {
          "id": 3
        }
      }
    ]
  }
}
複製程式碼
  1. 現在我們來修改增加一條資料,看看es資料的變化 這裡是資料庫現在的資料, 可以看到裡面有3條記錄。
mysql> select * from user;
+------+----------+-------------+------------+-------+------------+---------+
| id   | name     | phone       | password   | title | content    | article |
+------+----------+-------------+------------+-------+------------+---------+
|    1 | zhnagsan | 181222      | 123123     | ???   | ??????     | ???IE   |
|    2 | lishi    | 181222113   | 232123123  | 23??? | 234??????  | 4???IE  |
|    3 | wangwu   | 18111214204 | 1337547531 | ????? | lc content | Java    |
+------+----------+-------------+------------+-------+------------+---------+
3 rows in set (0.00 sec)
mysql>
複製程式碼

現在我們執行一個sql向裡面新增一條資料

mysql> insert into user (id, name, phone, password, title, content, article) values (4, "lc", "123456789", "123456789", "測試", "測試內容", "Java") 
Query OK, 1 row affected (0.00 sec)
mysql>
複製程式碼
  1. 在次執行查詢語句,看看es的資料變化,可以看到已經多了一條id為4的資料了,中間這個同步預設會有1分鐘的延遲。 執行搜尋
GET /myapp/_search
{
  "_source": "id"
}
複製程式碼

響應結果

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 1,
    "hits": [
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "2",
        "_score": 1,
        "_source": {
          "id": 2
        }
      },
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "4",
        "_score": 1,
        "_source": {
          "id": 4
        }
      },
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "1",
        "_score": 1,
        "_source": {
          "id": 1
        }
      },
      {
        "_index": "myapp",
        "_type": "doc",
        "_id": "3",
        "_score": 1,
        "_source": {
          "id": 3
        }
      }
    ]
  }
}
複製程式碼

環境

Virtual machine:VMware 11.0.2 Operator System:CentOS release 6.9 (Final) ElasticSearch:6.4.0 Kibana版本:6.4.0 LogStash版本:6.6.1 JDK版本:1.8.0_181 MySQL版本: 5.1.73(這個版本是用yum直接安裝的,其實這個教程和mysql版本沒有多大關係,因為到時候是使用jdbc的驅動包來連線資料庫的) logstash jdbc驅動包版本 5.1.46

獲取需要的環境

本文暫時只提供下載地址(暫時偷個大懶 ?,安裝順序是按照連結排列順序),logstash會給予詳細使用說明,它是不需要安裝的是需要解壓就行了。

Virtual machine:VMware 11.0.2

Operator System:CentOS release 6.9 (Final)

JDK版本:1.8.0_181

ElasticSearch:6.4.0

Kibana版本:6.4.0

Logstash版本:6.6.1

logStash驅動包

使用logstash

如果環境都安裝好了可以看下面的了,沒安裝好也可以看?

logstash 介紹

Logstash是一個開源資料收集引擎,具有實時管道功能。Logstash可以動態地將來自不同資料來源的資料統一起來,並將資料標準化到你所選擇的目的地。

ElasticSearch + Logstash進行資料庫同步

集中、轉換和儲存你的資料

Logstash是一個開源的伺服器端資料處理管道,可以同時從多個資料來源獲取資料,並對其進行轉換,然後將其傳送到你最喜歡的“儲存”。(當然,我們最喜歡的是Elasticsearch)

輸入:採集各種樣式、大小和來源的資料

資料往往以各種各樣的形式,或分散或集中地存在於很多系統中。Logstash 支援各種輸入選擇 ,可以在同一時間從眾多常用來源捕捉事件。能夠以連續的流式傳輸方式,輕鬆地從您的日誌、指標、Web 應用、資料儲存以及各種 AWS 服務採集資料。

ElasticSearch + Logstash進行資料庫同步

過濾器:實時解析和轉換資料

資料從源傳輸到儲存庫的過程中,Logstash 過濾器能夠解析各個事件,識別已命名的欄位以構建結構,並將它們轉換成通用格式,以便更輕鬆、更快速地分析和實現商業價值。 Logstash 能夠動態地轉換和解析資料,不受格式或複雜度的影響:

  1. 利用 Grok 從非結構化資料中派生出結構
  2. 從 IP 地址破譯出地理座標
  3. 將 PII 資料匿名化,完全排除敏感欄位
  4. 整體處理不受資料來源、格式或架構的影響
    ElasticSearch + Logstash進行資料庫同步

輸出:選擇你的儲存,匯出你的資料

儘管 Elasticsearch 是我們的首選輸出方向,能夠為我們的搜尋和分析帶來無限可能,但它並非唯一選擇。Logstash 提供眾多輸出選擇,您可以將資料傳送到您要指定的地方,並且能夠靈活地解鎖眾多下游用例。

ElasticSearch + Logstash進行資料庫同步

安裝logstash

ElasticSearch + Logstash進行資料庫同步
首先,讓我們通過最基本的Logstash管道來測試一下剛才安裝的Logstash Logstash管道有兩個必需的元素,輸入和輸出,以及一個可選元素過濾器。輸入外掛從資料來源那裡消費資料,過濾器外掛根據你的期望修改資料,輸出外掛將資料寫入目的地。
ElasticSearch + Logstash進行資料庫同步

接下來,從命令列輸入如下命令

bin/logstash -e 'input { stdin {} } output { stdout {} }'
選項 -e 的意思是允許你從命令列指定配置
複製程式碼

當啟動完成時,會等待你的輸入,你可以輸入hello world試試,它會給你一下資訊的回饋。

ElasticSearch + Logstash進行資料庫同步

使用logstash進行Mysql和ElasticSearch的同步

準備JDBC驅動包

  1. 首先,將我們剛才給予的下載連結裡面的jdbc驅動包放到logstash目錄裡面來

    ElasticSearch + Logstash進行資料庫同步

  2. 解壓這個檔案

[root@localhost logstash-6.6.1]# unzip mysql-connector-java-5.1.46.zip
複製程式碼

ElasticSearch + Logstash進行資料庫同步

生成mysqlsyn.conf檔案

  1. 進入config目錄,建立檔案mysqlsyn.conf
    ElasticSearch + Logstash進行資料庫同步
  2. 使用vim編輯器開啟這個檔案,並向裡面新增以下內容,並且儲存退出。
	input {
			jdbc {
			 		# jdbc驅動包位置
					jdbc_driver_library => "/mnt/logstash-6.6.1/mysql-connector-java-5.1.46/mysql-connector-java-5.1.46-bin.jar"
					# 要使用的驅動包類,有過java開發經驗的應該很熟悉這個了,不同的資料庫呼叫的類不一樣。
					jdbc_driver_class => "com.mysql.jdbc.Driver"
					 # myqsl資料庫的連線資訊
					jdbc_connection_string => "jdbc:mysql://0.0.0.0:3306/myapp"
					 # mysql使用者
					jdbc_user => "root"
					 # mysql密碼
					jdbc_password => "root"
					# 定時任務, 多久執行一次查詢, 預設一分鐘,如果想要沒有延遲,可以使用 schedule => "* * * * * *"
					schedule => "* * * * *"
					 # 你要執行的語句
					statement => "select * from user"
			}
	}

	output {
			# 將資料輸出到ElasticSearch中
			  elasticsearch {
			  		# es ip加埠
					hosts => ["0.0.0.0:9200"]
					# es文件索引
					index => "myusreinfo"
					# es文件資料的id,%{id}代表的是用資料庫裡面記錄的id作為文件的id
					document_id => "%{id}"
	  }
	}
複製程式碼

啟動logstash進行同步

上面我們已經生成了這個mysqlsyn.conf這個檔案,接下來我們就使用logstash來進行資料同步吧,同步之前先看下我們的資料庫的user表的資料。

  1. 檢視mysql資料, 能夠看到我們還是隻有剛開始的4條資料

    ElasticSearch + Logstash進行資料庫同步

  2. 檢查ElasticSearch是否有myusreinfo這個索引,可以從圖中看到我們只有myapp這個索引。

    ElasticSearch + Logstash進行資料庫同步

  3. 帶上配置檔案啟動logstash

[root@localhost logstash-6.6.1]# ./bin/logstash -f config/mysqlsyn.conf
-f 指定配置檔案啟動
複製程式碼

啟動成功,並且已經在同步資料了,這個同步預設是每分鐘執行一次,可以看到5分鐘執行了5次

ElasticSearch + Logstash進行資料庫同步

檢查同步效果

  1. 上面已經啟動了同步,現在我們去看看ElasticSearch裡面的是否有資料,從圖中可以看到myusrinfo已經同步到es裡面了,並且可以看到docs.count的數量就是我們剛才資料庫裡面資料的數量。

    ElasticSearch + Logstash進行資料庫同步

  2. 我們像資料庫裡面增加一條資料,然後看下ElasticSearch的資料是否會改變

    ElasticSearch + Logstash進行資料庫同步

  3. 檢視ElasticSearch裡面是否有剛才新增的資料, 從圖中可以看到已經有5條資料了

    ElasticSearch + Logstash進行資料庫同步

  4. 先看ElasticSearch裡面id為5的資料,可以看到name為yinya

    ElasticSearch + Logstash進行資料庫同步

  5. 資料庫修改一條id為5的資料,看看ElasticSearch的資料變化

    ElasticSearch + Logstash進行資料庫同步

  6. 檢視ElasticSearch裡面資料是否已經更改,可以看到資料已經更改了

    ElasticSearch + Logstash進行資料庫同步

  7. 刪除兩條資料看看ElasticSearch資料的變化, 刪除了id為1和2的兩條資料

    ElasticSearch + Logstash進行資料庫同步

  8. 檢視ElasticSearch裡面資料是否已經更改, 然而資料並沒有變

    ElasticSearch + Logstash進行資料庫同步

對delete操作的實時同步潑冷水

到目前為止,所有google,stackoverflow,elastic.co,github上面搜尋的外掛和實時同步的資訊,告訴我們:目前同步delete還沒有好的解決方案。 折中的解決方案如下: 方案探討:discuss.elastic.co/t/delete-el…

stackoverflow.com/questions/3…

  1. 方案一 在原有的mysql資料庫表中,新增一個欄位status, 預設值為ok,如果要刪除資料,實則用update操作,status改為deleted, 這樣,就能同步到es中。es中以status狀態值區分該行資料是否存在。deleted代表已刪除,ok代表正常。

  2. 方案二 使用go elasticsearch 外掛實現同步。

相關文章