Jika Anda perlu menyinkronkan data dari instans ApsaraDB RDS for MySQL ke kluster Alibaba Cloud Elasticsearch, Anda dapat menggunakan plugin logstash-input-jdbc Alibaba Cloud Logstash. Plugin ini telah diinstal secara default dan tidak dapat diuninstall. Dengan konfigurasi pipeline, plugin ini menyinkronkan data penuh atau data inkremental ke kluster Alibaba Cloud Elasticsearch secara real time. Topik ini menjelaskan cara menerapkan sinkronisasi tersebut.
Batasan
Pastikan instans ApsaraDB RDS for MySQL, kluster Alibaba Cloud Logstash, dan kluster Alibaba Cloud Elasticsearch berada dalam zona waktu yang sama. Jika tidak, saat data terkait waktu disinkronkan, akan terjadi perbedaan zona waktu antara data sebelum dan sesudah sinkronisasi.
Field
_iddi Elasticsearch harus sama dengan fieldiddi MySQL.Kondisi ini memastikan bahwa ketika sebuah record di MySQL ditulis ke Elasticsearch, tugas sinkronisasi dapat membuat pemetaan langsung antara record MySQL dan dokumen Elasticsearch. Misalnya, ketika sebuah record diperbarui di MySQL, tugas sinkronisasi akan menimpa dokumen Elasticsearch yang memiliki ID yang sama dengan record yang diperbarui tersebut.
CatatanBerdasarkan mekanisme internal Elasticsearch, pembaruan pada dasarnya merupakan penghapusan dokumen lama diikuti dengan pengindeksan dokumen baru. Oleh karena itu, menimpa dokumen di Elasticsearch sama efisiennya dengan operasi update.
Saat data dimasukkan atau diperbarui di MySQL, record yang bersangkutan harus berisi field yang menyimpan waktu pembaruan atau waktu penyisipan.
Setiap kali Logstash melakukan polling ke MySQL, Logstash menyimpan waktu pembaruan atau waktu penyisipan dari record terakhir yang dibacanya dari MySQL. Saat membaca data, Logstash hanya membaca record yang memenuhi kondisi tersebut, yaitu record yang waktu pembaruan atau waktu penyisipannya lebih baru daripada record terakhir pada polling sebelumnya.
PentingPlugin
logstash-input-jdbctidak dapat menyinkronkan penghapusan. Anda harus menjalankan perintah terkait di Elasticsearch untuk menghapus dokumen secara manual.
Prasyarat
Kami menyarankan Anda membuat instans berikut dalam virtual private cloud (VPC) yang sama:
Anda juga dapat menggunakan layanan yang dideploy di Internet. Dalam kasus ini, Anda harus mengonfigurasi SNAT, mengaktifkan titik akhir publik instans ApsaraDB RDS for MySQL, dan menghapus batasan daftar putih. Untuk informasi lebih lanjut tentang cara mengonfigurasi SNAT, lihat Konfigurasi gerbang NAT untuk transfer data publik. Untuk informasi lebih lanjut tentang cara mengonfigurasi daftar putih, lihat Konfigurasi daftar putih alamat IP.
Buat instans ApsaraDB RDS for MySQL. Untuk informasi lebih lanjut, lihat Buat instans ApsaraDB RDS for MySQL. Pada topik ini, digunakan MySQL 5.7.
Buat kluster Alibaba Cloud Elasticsearch. Untuk informasi lebih lanjut, lihat Buat kluster Alibaba Cloud Elasticsearch. Pada topik ini, digunakan kluster Elasticsearch V8.17.
Buat kluster Alibaba Cloud Logstash. Untuk informasi lebih lanjut, lihat Buat instans Alibaba Cloud Logstash. Pada topik ini, digunakan kluster Logstash V8.11.4.
Informasi latar belakang
Alibaba Cloud Logstash adalah tool pengumpulan dan pemrosesan data yang menyediakan kemampuan pengumpulan data, transformasi, optimasi, dan output. Plugin logstash-input-jdbc Logstash telah diinstal secara default dan tidak dapat diuninstall. Anda dapat menggunakan plugin ini untuk mengkueri data di instans ApsaraDB RDS for MySQL secara batch dan menyinkronkan data tersebut ke Elasticsearch. Plugin ini juga secara berkala melakukan polling terhadap data di instans ApsaraDB RDS for MySQL dan menyinkronkan record yang disisipkan atau diubah sejak polling sebelumnya ke Elasticsearch. Untuk informasi lebih lanjut, lihat How to keep Elasticsearch synchronized with a relational database using Logstash dalam dokumentasi resmi. Solusi ini cocok untuk skenario di mana data penuh disinkronkan dan latensi beberapa detik dapat diterima, atau skenario di mana data yang memenuhi kondisi tertentu dikueri secara batch lalu disinkronkan.
Sinkronisasi data
Langkah 1: Siapkan lingkungan
Aktifkan fitur Auto Indexing untuk kluster Elasticsearch Anda agar Logstash dapat membuat indeks secara otomatis. Untuk detailnya, lihat Akses dan konfigurasi kluster Elasticsearch.
Unggah driver JDBC yang kompatibel dengan versi MySQL Anda ke kluster Logstash. Contoh ini menggunakan
mysql-connector-java-5.1.48.jar. Untuk detailnya, lihat Konfigurasi library pihak ketiga.Siapkan data uji. Pernyataan berikut digunakan untuk membuat tabel:
CREATE table food ( id int PRIMARY key AUTO_INCREMENT, name VARCHAR (32), insert_time DATETIME, update_time DATETIME );Pernyataan berikut digunakan untuk memasukkan data:
INSERT INTO food values(null,'Chocolates',now(),now()); INSERT INTO food values(null,'Yogurt',now(),now()); INSERT INTO food values(null,'Ham sausage',now(),now());Tambahkan alamat IP node Alibaba Cloud Logstash ke daftar putih instans ApsaraDB RDS for MySQL. Anda dapat memperoleh alamat IP tersebut pada halaman Basic Information kluster Logstash.
Langkah 2: Konfigurasi pipeline Logstash
Buka halaman Logstash Clusters.
Navigasi ke kluster target.
Di bilah navigasi atas, pilih wilayah tempat kluster berada.
Pada halaman Logstash Clusters, temukan kluster tersebut dan klik ID-nya.
-
Di panel navigasi kiri, klik Pipelines.
-
Klik Create Pipeline.
Pada halaman Create Pipeline, masukkan Pipeline ID, lalu konfigurasikan Config.
Konfigurasi Config berikut digunakan dalam topik ini.
input { jdbc { jdbc_driver_class => "com.mysql.jdbc.Driver" jdbc_driver_library => "/ssd/1/share/<Logstash cluster ID>/logstash/current/config/custom/mysql-connector-java-5.1.48.jar" jdbc_connection_string => "jdbc:mysql://rm-bp1xxxxx.mysql.rds.aliyuncs.com:3306/<Database name>?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowLoadLocalInfile=false&autoDeserialize=false" jdbc_user => "xxxxx" jdbc_password => "xxxx" jdbc_paging_enabled => "true" jdbc_page_size => "50000" statement => "select * from food where update_time >= :sql_last_value" schedule => "* * * * *" record_last_run => true last_run_metadata_path => "/ssd/1/<Logstash cluster ID>/logstash/data/last_run_metadata_update_time.txt" clean_run => false tracking_column_type => "timestamp" use_column_value => true tracking_column => "update_time" } } filter { } output { elasticsearch { hosts => "http://es-cn-0h****dd0hcbnl.elasticsearch.aliyuncs.com:9200" index => "rds_es_dxhtest_datetime" user => "elastic" password => "xxxxxxx" document_id => "%{id}" } }CatatanGanti placeholder
<Logstash cluster ID>dalam kode dengan ID kluster Logstash yang telah Anda buat. Untuk informasi lebih lanjut tentang cara memperoleh ID tersebut, lihat Lihat informasi dasar kluster.Konfigurasi
Deskripsi
inputMenentukan sumber data masukan. Untuk jenis sumber data yang didukung, lihat Input plugins. Pada topik ini digunakan sumber data JDBC. Untuk deskripsi parameter, lihat parameter input.
filterMenentukan plugin yang digunakan untuk memfilter data masukan. Untuk jenis plugin yang didukung, lihat Filter plugins.
outputMenentukan jenis sumber data tujuan. Untuk jenis sumber data yang didukung, lihat Output plugins. Pada topik ini, data di MySQL disinkronkan ke Elasticsearch. Oleh karena itu, informasi tentang kluster Elasticsearch tujuan harus ditentukan dalam
output. Untuk deskripsi parameter, lihat Langkah 3: Buat dan jalankan pipeline.PentingJika parameter
file_extenddigunakan dalamoutput, pluginlogstash-output-file_extendharus diinstal terlebih dahulu. Untuk informasi lebih lanjut, lihat Instal atau hapus plugin.Parameter
Deskripsi
jdbc_driver_classKonfigurasi kelas JDBC.
jdbc_driver_libraryMenentukan file driver JDBC yang digunakan untuk menghubungkan ke MySQL. Formatnya adalah
/ssd/1/share/<Logstash cluster ID>/logstash/current/config/custom/<nama file driver>. Anda harus mengunggah file driver tersebut di konsol terlebih dahulu. Untuk daftar file driver yang didukung oleh Alibaba Cloud Logstash dan cara mengunggahnya, lihat Konfigurasi library pihak ketiga.jdbc_connection_stringMenentukan nama domain, port, dan database dari koneksi database. Formatnya adalah
jdbc:mysql://<MySQL endpoint>:<Port>/<Nama database>?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowLoadLocalInfile=false&autoDeserialize=false.<MySQL endpoint>: tentukan titik akhir internal MySQL. Jika Anda menggunakan titik akhir publik, Anda harus mengonfigurasi gerbang NAT untuk Logstash dan mengaturjdbc:mysql://<MySQL endpoint>:<Port>ke nama domain publik agar data ditransmisikan melalui Internet. Untuk informasi lebih lanjut, lihat Konfigurasi gerbang NAT untuk transfer data publik.<Port>: port harus konsisten dengan port outbound MySQL. Umumnya, port tersebut adalah 3306.
jdbc_userUsername database.
jdbc_passwordPassword database.
jdbc_paging_enabledMenentukan apakah paging diaktifkan. Nilai default:
false.jdbc_page_sizeUkuran paging.
statementMenentukan pernyataan SQL. Untuk kueri lintas beberapa tabel, Anda dapat menggunakan pernyataan join.
Catatansql_last_valuedigunakan untuk menentukan baris mana yang akan dikueri. Sebelum kueri apa pun dijalankan, nilai ini diatur ke Kamis, 1 Januari 1970. Untuk informasi lebih lanjut, lihat Jdbc input plugin.scheduleMenentukan operasi terjadwal. Nilai
* * * * *menunjukkan bahwa data disinkronkan setiap menit. Parameter ini menggunakan ekspresi cron gaya Rufus.record_last_runMenentukan apakah hasil eksekusi sebelumnya dicatat. Jika parameter ini diatur ke
true, nilai fieldtracking_columnpada eksekusi sebelumnya akan direkam dan disimpan ke file yang ditentukan olehlast_run_metadata_path.last_run_metadata_pathMenentukan path file yang menyimpan waktu eksekusi terakhir. Backend saat ini membuka path
/ssd/1/<Logstash cluster ID>/logstash/data/untuk menyimpan file tersebut. Setelah Anda menentukan path, Logstash akan secara otomatis menghasilkan file di path tersebut, tetapi konten file tidak dapat dilihat.CatatanSaat mengonfigurasi pipeline Logstash, kami menyarankan Anda mengonfigurasi parameter ini berdasarkan path
/ssd/1/<Logstash cluster ID>/logstash/data/. Jika Anda tidak menggunakan path ini, record kondisional yang disinkronkan tidak dapat disimpan di file konfigurasi di bawah pathlast_run_metadata_pathkarena izin tidak mencukupi.clean_runMenentukan apakah record
last_run_metadata_pathdihapus. Nilai default:false. Jika parameter ini diatur ketrue, semua record database akan dikueri dari awal setiap kali.use_column_valueMenentukan apakah nilai kolom harus direkam. Jika parameter ini diatur ke
true, sistem akan merekam nilai terbaru dari kolom yang ditentukan olehtracking_column, dan menggunakan nilai kolom tersebut pada eksekusi pipeline berikutnya untuk menentukan record yang harus diperbarui.tracking_column_typeJenis kolom pelacak. Nilai default:
numeric.tracking_columnMenentukan kolom pelacak. Kolom tersebut harus bersifat inkremental. Umumnya, kolom tersebut adalah primary key MySQL.
PentingKonfigurasi di atas didasarkan pada data uji. Dalam skenario bisnis aktual, konfigurasikan parameter sesuai kebutuhan bisnis Anda. Untuk opsi konfigurasi lain yang didukung oleh plugin input, lihat topik resmi Logstash Jdbc input plugin.
Jika konfigurasi berisi parameter seperti
last_run_metadata_path, Alibaba Cloud Logstash harus menyediakan path file tersebut. Backend saat ini membuka path/ssd/1/<Logstash cluster ID>/logstash/data/untuk pengujian, dan data dalam direktori tersebut tidak dihapus. Oleh karena itu, pastikan disk memiliki ruang kosong yang cukup. Setelah Anda menentukan path, Logstash akan secara otomatis menghasilkan file di path tersebut, tetapi konten file tidak dapat dilihat.Untuk meningkatkan keamanan, jika driver JDBC digunakan saat mengonfigurasi pipeline, Anda harus menambahkan
allowLoadLocalInfile=false&autoDeserialize=falseke parameterjdbc_connection_string. Jika tidak, sistem penjadwalan akan melaporkan kegagalan verifikasi saat Anda menambahkan file konfigurasi Logstash. Contoh:jdbc_connection_string => "jdbc:mysql://xxx.drds.aliyuncs.com:3306/<Nama database>?allowLoadLocalInfile=false&autoDeserialize=false".
Untuk konfigurasi Config lainnya, lihat File konfigurasi Logstash.
Klik Next untuk mengonfigurasi parameter pipeline.
PeringatanMenyimpan dan menerapkan pipeline akan memicu restart kluster Logstash. Pastikan restart tidak akan memengaruhi beban kerja Anda sebelum melanjutkan.
Parameter
Deskripsi
Default
Pipeline Workers
Jumlah thread yang menjalankan plugin filter dan output secara paralel. Tingkatkan nilai ini saat sumber daya CPU kurang dimanfaatkan atau event menumpuk.
Jumlah vCPU
Pipeline Batch Size
Jumlah maksimum event yang dikumpulkan oleh satu worker dari input sebelum menjalankan filter dan output. Nilai yang lebih tinggi meningkatkan throughput tetapi memerlukan lebih banyak memori heap JVM.
125
Pipeline Batch Delay
Berapa lama worker menunggu event tambahan sebelum memulai batch kecil, dalam milidetik.
50
Queue Type
Model antrian internal untuk buffering event. MEMORY: antrian dalam memori. PERSISTED: antrian berbasis disk dengan ACK untuk ketahanan.
MEMORY
Queue Max Bytes
Ukuran maksimum antrian di disk. Harus lebih kecil dari kapasitas disk yang tersedia.
1024 MB
Queue Checkpoint Writes
Jumlah maksimum event yang ditulis sebelum checkpoint dipaksakan (hanya untuk antrian persisten). Atur ke 0 untuk tanpa batas.
1024

Klik Save and Deploy untuk merestart kluster Logstash dan menerapkan konfigurasi segera. Atau, klik Save untuk menyimpan konfigurasi dan memicu perubahan kluster, tetapi pengaturan belum berlaku. Untuk menerapkan nanti, buka halaman Pipelines, temukan pipeline tersebut, lalu klik Deploy Now di kolom Actions.
Langkah 3: Verifikasi hasil
Login ke konsol Kibana kluster Elasticsearch Anda. Untuk detailnya, lihat Login ke konsol Kibana.
Di pojok kiri atas, klik ikon
lalu pilih .Pada tab Console, jalankan perintah berikut untuk memastikan tiga baris telah disinkronkan:
GET rds_es_dxhtest_datetime/_count { "query": {"match_all": {}} }Tanggapan yang diharapkan:
{ "count" : 3, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 } }Perbarui dan sisipkan baris di MySQL untuk menguji sinkronisasi inkremental:
UPDATE food SET name='Chocolates',update_time=now() where id = 1; INSERT INTO food values(null,'Egg',now(),now());Di konsol Kibana, lihat data yang diperbarui.
Cari baris yang diperbarui:
GET rds_es_dxhtest_datetime/_search { "query": { "match": { "name": "Chocolates" } } }{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.5580825, "hits" : [ { "_index" : "rds_es_dxhtest_datetime", "_type" : "_doc", "_id" : "1", "_score" : 1.5580825, "_source" : { "update_time" : "2020-03-23T03:43:19.000Z", "@version" : "1", "name" : "Chocolates", "insert_time" : "2020-03-23T03:00:36.000Z", "@timestamp" : "2020-03-23T03:44:00.1857", "id" : 1 } } ] } }Kueri semua dokumen:
GET rds_es_dxhtest_datetime/_search { "query": { "match_all": {} } }Tanggapan mencakup dokumen baru dengan id=4 dan name=Egg, yang mengonfirmasi bahwa sinkronisasi data berhasil.
{ "_index" : "rds_es_dxhtest_datetime", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "update_time" : "2020-03-23T03:43:19.000Z", "@version" : "1", "name" : "Chocolates", "insert_time" : "2020-03-23T03:00:36.000Z", "@timestamp" : "2020-03-23T03:44:00.185Z", "id" : 1 } }, { "_index" : "rds_es_dxhtest_datetime", "_type" : "_doc", "_id" : "4", "_score" : 1.0, "_source" : { "update_time" : "2020-03-23T04:05:01.000Z", "@version" : "1", "name" : "Egg", "insert_time" : "2020-03-23T04:05:01.000Z", "@timestamp" : "2020-03-23T04:06:00.192Z", "id" : 4 } }
FAQ
Pipeline saya macet di status initializing, data tidak konsisten setelah sinkronisasi, atau koneksi database gagal. Apa yang harus saya lakukan?
Periksa log kluster Logstash terlebih dahulu. Buka konsol Logstash dan gunakan fitur Query logs untuk melihat detail error. Untuk detailnya, lihat Kueri log.
Jika pembaruan kluster sedang berlangsung saat Anda menerapkan perbaikan, jeda pembaruan tersebut terlebih dahulu. Lihat Lihat progres tugas kluster. Setelah perbaikan, sistem akan merestart kluster dan melanjutkan pembaruan secara otomatis.
Tabel berikut mencantumkan penyebab umum dan solusinya:
Penyebab | Solusi |
Alamat IP node Logstash tidak ditambahkan ke daftar putih MySQL. | Tambahkan alamat IP node Logstash ke daftar putih MySQL dengan mengikuti petunjuk dalam Gunakan klien database atau CLI untuk menghubungkan ke instans ApsaraDB RDS for MySQL. Catatan Untuk informasi lebih lanjut tentang cara memperoleh alamat IP node Logstash, lihat Lihat informasi dasar kluster. |
Menyinkronkan dari MySQL yang dikelola sendiri di ECS: IP privat node dan port tidak ada di security group ECS | Tambahkan alamat IP privat node Logstash dan port internal ke security group ECS. Lihat Tambahkan aturan grup keamanan. |
Kluster Elasticsearch tidak berada dalam VPC yang sama dengan kluster Logstash | Beli kluster Elasticsearch dalam VPC yang sama, atau konfigurasi gerbang NAT untuk akses lintas Internet. Lihat Buat kluster Alibaba Cloud Elasticsearch dan Konfigurasi gerbang NAT untuk transmisi data melalui Internet. |
Endpoint MySQL salah, atau port bukan 3306. | Peroleh endpoint dan port yang benar dengan mengikuti petunjuk dalam Kelola endpoint dan port instans. Kemudian, gunakan endpoint dan port yang benar untuk mengganti nilai parameter Penting
|
Auto Indexing dinonaktifkan pada kluster Elasticsearch | Aktifkan Auto Indexing. Lihat Konfigurasi file YML. |
Beban pada kluster Elasticsearch atau Logstash terlalu tinggi. | Tingkatkan konfigurasi kluster dengan mengikuti petunjuk dalam Tingkatkan konfigurasi kluster. Catatan Anda dapat melihat beban pada Elasticsearch melalui metrik pemantauan di konsol. Untuk informasi lebih lanjut, lihat Metrik pemantauan dan penanganan exception. Anda dapat melihat beban pada Logstash melalui pemantauan X-Pack di Kibana. Untuk informasi lebih lanjut, lihat Konfigurasi pemantauan X-Pack. |
Driver JDBC belum diunggah | Unggah file driver tersebut. Lihat Konfigurasi library pihak ketiga. |
| Instal plugin tersebut, atau hapus parameter |
Untuk panduan troubleshooting lebih lanjut, lihat FAQ tentang transfer data menggunakan Logstash.
Bagaimana cara menyinkronkan data dari beberapa tabel MySQL ke indeks Elasticsearch yang terpisah?
Definisikan beberapa blok jdbc dalam bagian input, tetapkan nilai type untuk masing-masing, lalu gunakan kondisi if[type] dalam bagian output untuk mengarahkan data setiap tabel ke indeks yang berbeda:
input {
jdbc {
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_driver_library => "/ssd/1/share/<Logstash cluster ID>/logstash/current/config/custom/mysql-connector-java-5.1.48.jar"
jdbc_connection_string => "jdbc:mysql://rm-bp1xxxxx.mysql.rds.aliyuncs.com:3306/<Database name>?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowLoadLocalInfile=false&autoDeserialize=false"
jdbc_user => "xxxxx"
jdbc_password => "xxxx"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
statement => "select * from tableA where update_time >= :sql_last_value"
schedule => "* * * * *"
record_last_run => true
last_run_metadata_path => "/ssd/1/<Logstash cluster ID>/logstash/data/last_run_metadata_update_time.txt"
clean_run => false
tracking_column_type => "timestamp"
use_column_value => true
tracking_column => "update_time"
type => "A"
}
jdbc {
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_driver_library => "/ssd/1/share/<Logstash cluster ID>/logstash/current/config/custom/mysql-connector-java-5.1.48.jar"
jdbc_connection_string => "jdbc:mysql://rm-bp1xxxxx.mysql.rds.aliyuncs.com:3306/<Database name>?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowLoadLocalInfile=false&autoDeserialize=false"
jdbc_user => "xxxxx"
jdbc_password => "xxxx"
jdbc_paging_enabled => "true"
jdbc_page_size => "50000"
statement => "select * from tableB where update_time >= :sql_last_value"
schedule => "* * * * *"
record_last_run => true
last_run_metadata_path => "/ssd/1/<Logstash cluster ID>/logstash/data/last_run_metadata_update_time.txt"
clean_run => false
tracking_column_type => "timestamp"
use_column_value => true
tracking_column => "update_time"
type => "B"
}
}
output {
if[type] == "A" {
elasticsearch {
hosts => "http://es-cn-0h****dd0hcbnl.elasticsearch.aliyuncs.com:9200"
index => "rds_es_dxhtest_datetime_A"
user => "elastic"
password => "xxxxxxx"
document_id => "%{id}"
}
}
if[type] == "B" {
elasticsearch {
hosts => "http://es-cn-0h****dd0hcbnl.elasticsearch.aliyuncs.com:9200"
index => "rds_es_dxhtest_datetime_B"
user => "elastic"
password => "xxxxxxx"
document_id => "%{id}"
}
}
}