介紹
在我們使用mysql和elasticsearch結合使用的時候,可能會有一些同步的需求,想要資料庫和elasticsearch同步的方式其實有很多。
可以使用canal,它主要是監聽mysql的binlog 日誌,可以監聽資料的一些變化,如果資料發生了變化我們需要做什麼邏輯,這些都是可以人為實現的,它是將自己模擬成一個slave節點,當master節點的資料發生變化是,它能夠看到資料的變化。但是缺點也很明顯,由於是java實現的,所以比較重,還需要使用zookeeper等叢集管理工具來管理canal節點,所以本文暫時不介紹這種方式。
本文主要介紹使用Logstash JDBC的方式來實現同步,這個方式同步比較簡單。當然它有一些缺點,就是有點耗記憶體(記憶體大就當我沒說?)。
最終效果展示
- 先看下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
}
}
]
}
}
複製程式碼
- 現在我們來修改增加一條資料,看看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>
複製程式碼
- 在次執行查詢語句,看看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會給予詳細使用說明,它是不需要安裝的是需要解壓就行了。
Operator System:CentOS release 6.9 (Final)
使用logstash
如果環境都安裝好了可以看下面的了,沒安裝好也可以看?
logstash 介紹
Logstash是一個開源資料收集引擎,具有實時管道功能。Logstash可以動態地將來自不同資料來源的資料統一起來,並將資料標準化到你所選擇的目的地。
集中、轉換和儲存你的資料
Logstash是一個開源的伺服器端資料處理管道,可以同時從多個資料來源獲取資料,並對其進行轉換,然後將其傳送到你最喜歡的“儲存”。(當然,我們最喜歡的是Elasticsearch)
輸入:採集各種樣式、大小和來源的資料
資料往往以各種各樣的形式,或分散或集中地存在於很多系統中。Logstash 支援各種輸入選擇 ,可以在同一時間從眾多常用來源捕捉事件。能夠以連續的流式傳輸方式,輕鬆地從您的日誌、指標、Web 應用、資料儲存以及各種 AWS 服務採集資料。
過濾器:實時解析和轉換資料
資料從源傳輸到儲存庫的過程中,Logstash 過濾器能夠解析各個事件,識別已命名的欄位以構建結構,並將它們轉換成通用格式,以便更輕鬆、更快速地分析和實現商業價值。 Logstash 能夠動態地轉換和解析資料,不受格式或複雜度的影響:
- 利用 Grok 從非結構化資料中派生出結構
- 從 IP 地址破譯出地理座標
- 將 PII 資料匿名化,完全排除敏感欄位
- 整體處理不受資料來源、格式或架構的影響
輸出:選擇你的儲存,匯出你的資料
儘管 Elasticsearch 是我們的首選輸出方向,能夠為我們的搜尋和分析帶來無限可能,但它並非唯一選擇。Logstash 提供眾多輸出選擇,您可以將資料傳送到您要指定的地方,並且能夠靈活地解鎖眾多下游用例。
安裝logstash
首先,讓我們通過最基本的Logstash管道來測試一下剛才安裝的Logstash Logstash管道有兩個必需的元素,輸入和輸出,以及一個可選元素過濾器。輸入外掛從資料來源那裡消費資料,過濾器外掛根據你的期望修改資料,輸出外掛將資料寫入目的地。接下來,從命令列輸入如下命令
bin/logstash -e 'input { stdin {} } output { stdout {} }'
選項 -e 的意思是允許你從命令列指定配置
複製程式碼
當啟動完成時,會等待你的輸入,你可以輸入hello world
試試,它會給你一下資訊的回饋。
使用logstash進行Mysql和ElasticSearch的同步
準備JDBC驅動包
-
首先,將我們剛才給予的下載連結裡面的jdbc驅動包放到logstash目錄裡面來
-
解壓這個檔案
[root@localhost logstash-6.6.1]# unzip mysql-connector-java-5.1.46.zip
複製程式碼
生成mysqlsyn.conf檔案
- 進入config目錄,建立檔案mysqlsyn.conf
- 使用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表的資料。
-
檢視mysql資料, 能夠看到我們還是隻有剛開始的4條資料
-
檢查ElasticSearch是否有
myusreinfo
這個索引,可以從圖中看到我們只有myapp
這個索引。 -
帶上配置檔案啟動logstash
[root@localhost logstash-6.6.1]# ./bin/logstash -f config/mysqlsyn.conf
-f 指定配置檔案啟動
複製程式碼
啟動成功,並且已經在同步資料了,這個同步預設是每分鐘執行一次,可以看到5分鐘執行了5次
檢查同步效果
-
上面已經啟動了同步,現在我們去看看ElasticSearch裡面的是否有資料,從圖中可以看到myusrinfo已經同步到es裡面了,並且可以看到
docs.count
的數量就是我們剛才資料庫裡面資料的數量。 -
我們像資料庫裡面增加一條資料,然後看下ElasticSearch的資料是否會改變
-
檢視ElasticSearch裡面是否有剛才新增的資料, 從圖中可以看到已經有5條資料了
-
先看ElasticSearch裡面id為5的資料,可以看到name為
yinya
-
資料庫修改一條id為5的資料,看看ElasticSearch的資料變化
-
檢視ElasticSearch裡面資料是否已經更改,可以看到資料已經更改了
-
刪除兩條資料看看ElasticSearch資料的變化, 刪除了id為1和2的兩條資料
-
檢視ElasticSearch裡面資料是否已經更改, 然而資料並沒有變
對delete操作的實時同步潑冷水
到目前為止,所有google,stackoverflow,elastic.co,github上面搜尋的外掛和實時同步的資訊,告訴我們:目前同步delete還沒有好的解決方案。 折中的解決方案如下: 方案探討:discuss.elastic.co/t/delete-el…
stackoverflow.com/questions/3…
-
方案一 在原有的mysql資料庫表中,新增一個欄位status, 預設值為ok,如果要刪除資料,實則用update操作,status改為deleted, 這樣,就能同步到es中。es中以status狀態值區分該行資料是否存在。deleted代表已刪除,ok代表正常。
-
方案二 使用go elasticsearch 外掛實現同步。
歡迎大家加我微信coding4life,或掃描二維碼,一起討論技術~