Diretório de artigos
1. Preparação
1. Instale elasticSearch+kibana
As versões es e kibana que usamos aqui são 7.4.0
versões.
Instalação do Docker elasticSearch+kibana
2. Instale o MySQL
docker instala mysql-simples e sem pit
3. Instale o Logstash
logstash é um pipeline com capacidade de transmissão de dados em tempo real, responsável por transmitir informações de dados da extremidade de entrada do pipeline para a extremidade de saída do pipeline; ao mesmo tempo, esse pipeline também pode adicionar um filtro no meio de inuput --output de acordo com suas próprias necessidades. Logstash possui dezenas de plug-ins integrados para atender a vários cenários de aplicação.
O plug-in oficial do logstash logstash-input-jdbc
está integrado no logstash (após 5.X), e a sincronização de dados entre mysql e elasticsearch é realizada através do arquivo de configuração.
Ele pode realizar a sincronização de dados completa e incremental dos dados MySQL e pode realizar a sincronização de tempo.
# 拉取logstach
docker pull logstash:8.5.2
2. Sincronização completa
A sincronização completa refere-se à sincronização de todos os dados com es, que geralmente é usada para a primeira sincronização quando es acaba de ser estabelecida.
1. Prepare dados e tabelas MySQL
CREATE TABLE `product` (
`id` int NOT NULL COMMENT 'id',
`name` varchar(255) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
`create_at` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
INSERT INTO `shop`.`product`(`id`, `name`, `price`, `create_at`) VALUES (1, '小米手机', 33.00, '1');
INSERT INTO `shop`.`product`(`id`, `name`, `price`, `create_at`) VALUES (2, '长虹手机', 2222.00, '2');
INSERT INTO `shop`.`product`(`id`, `name`, `price`, `create_at`) VALUES (3, '华为电脑', 3333.00, '3');
INSERT INTO `shop`.`product`(`id`, `name`, `price`, `create_at`) VALUES (4, '小米电脑', 333.30, '4');
2. Carregar mysql-connector-java.jar
Carregue mysql-connector-java-8.0.21.jar para o servidor logstach,
3. Inicie o Logstash
# 编辑logstash.yml
vi /usr/local/logstash/config/logstash.yml
# 内容,需要修改es地址
http.host: "0.0.0.0"
xpack.monitoring.elasticsearch.hosts: [ "http://172.17.0.3:9200" ]
# 自定义网络(可以解决网络不一致的问题)
#docker network create --subnet=172.188.0.0/16 czbkNetwork
# 启动 logstash
docker run --name logstash -v /usr/local/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml -v /usr/local/logstash/config/conf.d/:/usr/share/logstash/pipeline/ -v /root/mysql-connector-java-8.0.21.jar:/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-5.1.48.jar -d d7102f8c625d
# 查看日志
docker logs -f --tail=200 c1d20ebf76c3
4. Modifique o arquivo logstash.conf
cd /usr/local/logstash/config/conf.d
vi logstash.conf
stdin lê eventos da entrada padrão.
Por padrão, cada linha é lida como um evento
input {
stdin {
}
#使用jdbc插件
jdbc {
# mysql数据库驱动
#jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-5.1.48.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
# mysql数据库链接,数据库名
jdbc_connection_string => "jdbc:mysql://172.17.0.2:3306/shop?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true"
# mysql数据库用户名,密码
jdbc_user => "root"
jdbc_password => "root"
# 分页
jdbc_paging_enabled => "true"
# 分页大小
jdbc_page_size => "50000"
# sql语句执行文件,也可直接使用 statement => 'select * from t'
statement_filepath => "/usr/share/logstash/pipeline/sql/full_jdbc.sql"
#statement => " select * from product where id <=100 "
}
}
# 过滤部分(不是必须项)
filter {
json {
source => "message"
remove_field => ["message"]
}
}
# 输出部分
output {
elasticsearch {
# elasticsearch索引名
index => "product"
# elasticsearch的ip和端口号
hosts => ["172.17.0.3:9200"]
# 同步mysql中数据id作为elasticsearch中文档id
document_id => "%{id}"
}
stdout {
codec => json_lines
}
}
5. Modifique o arquivo full_jdbc.sql
mkdir /usr/local/logstash/config/conf.d/sql
cd /usr/local/logstash/config/conf.d/sql
vi full_jdbc.sql
O conteúdo de full_jdbc.sql é o seguinte
SELECT
id,
TRIM( REPLACE ( name, ' ', '' ) ) AS productname,
price
FROM product
6. Abra o Kibana para criar índices e mapas
Perceber! mysql—>logstash—>es
Se o mapeamento criado tiver letras maiúsculas, es será automaticamente convertido para letras minúsculas
e ao visualizar a estrutura de dados do mapeamento, dois campos idênticos (productname e productName) aparecerão,
o que leva ao nosso próprio mapeamento definido Não pode ser usado, e aquele com dados é a minúscula gerada automaticamente por es
PUT product
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"productname": {
"type": "text"
},
"price": {
"type": "double"
}
}
}
}
Se não houver nenhum requisito rígido para mapeamento, a etapa atual poderá ser ignorada e o índice será criado automaticamente.
# 当前在es中是没有数据的
GET product/_search
7. Reinicie o logstash para sincronização completa
# 重启
docker restart c1d20ebf76c3
# 查看日志
docker logs -f --tail=200 c1d20ebf76c3
Verifica-se que os dados no mysql foram sincronizados com o logstash.
8. Pise no poço
(1) Relatório de erros
Resposta de erro do daemon: Não é possível reiniciar o contêiner 3849f947e115: driver falhou ao programar conectividade externa no endpoint logstash (60f5d9678218dc8d19bc8858fb1a195f4ebee294cff23d499a28612019a0ff78): (iptables falhou: iptables --wait -t nat -A DOCKER -p tc p -d 0/0 --dport 4567 -j DNAT --to-destination 172.188.0.77:4567 ! -i br-413b460a0fc8: iptables: Nenhuma cadeia/destino/correspondência com esse nome.
O motivo é: após iniciar o firewalld, o iptables é ativado,
não há cadeia do docker no momento e é adicionado ao iptable após reiniciar o docker
Solução:
systemctl restart docker
3. Sincronização incremental
1. Modifique a configuração incremental
Modifique o arquivo logstash.conf acima
input {
stdin {
}
#使用jdbc插件
jdbc {
# mysql数据库驱动
#jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-5.1.48.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
# mysql数据库链接,数据库名
jdbc_connection_string => "jdbc:mysql://172.188.0.15:3306/shop?characterEncoding=UTF-8&useSSL=false"
# mysql数据库用户名,密码
jdbc_user => "root"
jdbc_password => "root"
# 设置监听间隔 各字段含义(分、时、天、月、年),全部为*默认含义为每分钟更新一次
# /2* * * *表示每隔2分钟执行一次,依次类推
schedule => "* * * * *"
# 分页
jdbc_paging_enabled => "true"
# 分页大小
jdbc_page_size => "50000"
# sql语句执行文件,也可直接使用 statement => 'select * from t'
statement_filepath => "/usr/share/logstash/pipeline/sql/increment_jdbc.sql"
#上一个sql_last_value值的存放文件路径, 必须要在文件中指定字段的初始值
#last_run_metadata_path => "./config/station_parameter.txt"
#设置时区,此处更新sql_last_value查询的时区,sql_last_value还是默认UTC
jdbc_default_timezone => "Asia/Shanghai"
#使用其它字段追踪,而不是用时间
#use_column_value => true
#追踪的字段
#tracking_column => id
tracking_column_type => "timestamp"
}
}
# 过滤部分(不是必须项)
filter {
json {
source => "message"
remove_field => ["message"]
}
}
# 输出部分
output {
elasticsearch {
# elasticsearch索引名
index => "product"
# elasticsearch的ip和端口号
hosts => ["172.188.0.88:9200"]
# 同步mysql中数据id作为elasticsearch中文档id
document_id => "%{id}"
}
stdout {
codec => json_lines
}
}
2. Crie um novo arquivo increment_jdbc.sql
Crie um novo arquivo increment_jdbc.sql no diretório /usr/local/logstash/config/conf.d/sql
cd /usr/local/logstash/config/conf.d/sql
vi increment_jdbc.sql
O conteúdo de increment_jdbc.sql é o seguinte:
Aqui, o sql deve ser consistente com o valor total tanto quanto possível após o Select
SELECT
id,
TRIM( REPLACE ( product_name, ' ', '' ) ) AS productname,
price
FROM product where update_time > :sql_last_value
3. Reinicie o contêiner
# 启动
docker restart 容器id
4. Teste
Depois que um dado for inserido no banco de dados, ele será automaticamente sincronizado com es
5. Princípio de sincronização
#进入容器
docker exec -it 4f95a47f12de /bin/bash
#查看记录点
cat /usr/share/logstash/.logstash_jdbc_last_run
last_run_metadata_path=>“/usr/share/logstash/.logstash_jdbc_last_run”
O horário UTC da sincronização completa é registrado no arquivo oculto .logstash_jdbc_last_run no caminho /usr/share/logstash/ no contêiner
Registre o tempo após a conclusão de cada sincronização (importante)
Observe que
logstash_jdbc_last_run não está disponível por padrão, e
o arquivo criado após a execução do incremento também pode ser excluído e
o contêiner será criado automaticamente após a reinicialização