MySQL adalah teknologi yang sangat matang. Sudah ada selama seperempat abad dan merupakan salah satu DBMS paling populer di dunia. Dengan demikian, sebagai seorang insinyur, seseorang mengharapkan fitur dasar seperti replikasi dan failover disempurnakan, stabil, dan idealnya bahkan mudah diatur. Show
Dan sementara MySQL hadir dengan fungsionalitas replikasi di luar kotak, failover otomatis dan manajemen topologi bukan bagian dari rangkaian fiturnya. Selain itu, ternyata agak sulit untuk tidak menyalahkan diri sendiri saat mengonfigurasi replikasi Faktanya, tanpa konfigurasi yang hati-hati dan alat yang tepat, failover dari sumber ke server replika hampir pasti akan kehilangan transaksi yang telah diakui sebagai komitmen pada aplikasi. Ini adalah posting blog tentang pengaturan replikasi MySQL lossless dengan failover otomatis, mis. e. memastikan bahwa tidak ada satu transaksi pun yang hilang selama failover, dan bahwa failover terjadi sepenuhnya tanpa campur tangan manusia. Terminologi & PenafianPosting blog ini menggunakan terminologi MySQL yang baru dan tidak terlalu ofensif seperti yang diperkenalkan di versi 8. 0. 26. Kami menyebut host primer sebagai "sumber" dan host replikasinya sebagai "replika". Parameter konfigurasi mungkin masih menggunakan istilah ofensif. Saya seorang insinyur perangkat lunak dan bukan DBA. Maafkan kesalahan dan beri tahu saya. Saya senang memperbaiki kesalahan apa pun Replikasi asinkron adalah upaya terbaik dan akan kehilangan transaksi selama failoverMekanisme replikasi default MySQL adalah replikasi asinkron, artinya transaksi yang dilakukan oleh aplikasi direplikasi oleh utas latar belakang ke semua host replika yang terhubung. Selama host sumber tidak macet, ini baik-baik saja. Namun, jika ya, tidak ada jaminan bahwa semua transaksi sudah sampai ke host replika sebelum crash Pertimbangkan topologi dari tiga host, dengan A sebagai sumber dan B dan C menjadi replika dari A Dengan asumsi pada host sumber (A), cara kerja replikasi asinkron adalah seperti ini.
Ini jelas berbahaya karena aplikasi mendapat pengakuan transaksi sebelum direplikasi. Jika sumber (A) lumpuh setelah itu, replikasi mungkin belum direplikasi ke B dan/atau C dan Anda kehilangan transaksi. Replikasi semi-sinkronisasi untuk menyelamatkan, semacamJelas, replikasi asinkron bukanlah jawaban jika kehilangan transaksi tidak dapat diterima untuk aplikasi Anda. Replikasi semi-sinkronisasi memecahkan masalah ini, setidaknya sebagian. Berbeda dengan replikasi asinkron, sumber tidak mengakui transaksi ke aplikasi sampai replika mengakui penerimaan (namun bukan eksekusi). ) dari transaksi tersebut Beginilah urutan operasi berubah dengan semi-sinkronisasi diaktifkan pada sumber dan replika, mis. e. dengan di A, dan di B dan C
(Alur contoh ini mengasumsikan bahwa dan mengabaikan dan. Kita akan membahasnya nanti. ) Ini terlihat jauh lebih baik. Jika sumber mogok sebelum transaksi dikirim ke B dan C (poin mogok 1), aplikasi kita berada dalam status yang konsisten. A belum mengakui transaksi ke aplikasi sebelum macet, jadi seolah-olah tidak pernah dilakukan. Selama kita gagal ke B atau C dan tidak pernah memulai ulang sumbernya (lebih lanjut tentang itu nanti. ), kami baik-baik saja Titik crash lainnya (crash point 2) lebih menarik. Jika A macet setelah transaksi ditransfer ke log relai di B dan C, aplikasi akan kehilangan koneksi databasenya ke A dan berpikir bahwa transaksi gagal. Jika kita memulai ulang A (yang seharusnya tidak kita lakukan), transaksi akan tetap ada di log biner A dan akan diteruskan selama pemulihan kerusakan. Dalam kedua kasus tersebut, transaksi tidak akan hilang. Dengan asumsi kita gagal ke B atau C, namun transaksi akan tetap dijalankan di sana, meskipun ada kesalahan koneksi. Replikasi tanpa kerugian berarti kami tidak kehilangan apa pun, jadi ini sebenarnya adalah skenario yang dapat diterima, meskipun sangat tidak terduga dari perspektif pengembang. Kami telah melihat kasus lemparan-kesalahan-tetapi-masih-dieksekusi ini berkali-kali, jadi Anda harus bisa menghadapinya Jelas ada lebih dari dua poin crash, tapi saya pikir Anda mengerti. replikasi semi-sinkronisasi memastikan bahwa setiap transaksi telah ditulis ke setidaknya satu replika lain sebelum mengirim pemberitahuan ke aplikasi Jebakan semi-sinkronisasi yang berbahayaSayangnya, menyiapkan semi-sinkronisasi tidak sesederhana yang diharapkan. Ada sejumlah parameter konfigurasi yang tidak mencolok, namun cukup penting yang harus Anda lakukan dengan benar Fallback tidak disengaja ke replikasi asinkronParameter mengontrol berapa lama sumber akan menunggu replika untuk merespons dan mengakui penerimaan transaksi sebelum menyerah dan kembali ke replikasi asinkron. Nilai defaultnya adalah 10.000 ms (10 detik), yang berarti bahwa dalam konfigurasi defaultnya, replikasi semi-sinkronisasi akan kembali ke perilaku replikasi asinkron upaya terbaik jika replika tidak merespons dalam waktu tersebut Meskipun 10 detik mungkin terasa lama untuk satu transaksi, kita semua tahu bahwa ada lusinan hal yang dapat menyebabkan penundaan seperti itu bahkan pada perangkat keras modern. (sementara) kegagalan jaringan, disk buruk, atau beban berat -- semuanya merupakan alasan mengapa replika dapat (setidaknya untuk sementara) tidak merespons dalam waktu 10 detik. Berikut adalah ilustrasi dari contoh di atas, namun kali ini kami kehabisan waktu (3 & 4) saat mencoba mengirim/menulis ke replika. Perhatikan bahwa transaksi masih diakui ke aplikasi (5), meskipun downstream habis, jadi jika failover terjadi sekarang, kami akan kehilangan transaksi ini Kami sebenarnya telah digigit dengan sangat parah di salah satu produk kami. Blip jaringan sementara menyebabkan fallback ke replikasi asinkron, dan failover berikutnya ke replika (juga karena kegagalan jaringan sementara) menyebabkan hilangnya 4 detik transaksi. Itu mungkin tidak terlihat banyak, tetapi kami butuh beberapa hari untuk memperbaiki tabel yang terpengaruh Jika Anda ingin memastikan bahwa Anda tidak pernah kembali ke replikasi asinkron, Anda harus menyetel ke sesuatu yang sangat tinggi, mis. g. , satu jam atau bahkan 24 jam Meskipun ini akan menjamin bahwa transaksi tidak akan ditulis ke sumber tanpa setidaknya diterima oleh satu replika, implikasinya adalah jika replika Anda mati (bahkan hanya untuk pemeliharaan), aplikasi Anda akan diblokir "selamanya". Ini adalah status yang diinginkan jika persyaratan terpenting Anda tidak kehilangan satu transaksi pun, tetapi masih merupakan sesuatu yang mungkin tidak sepenuhnya jelas bagi administrator atau pengembang saat menyiapkan replikasi semi-sinkronisasi (Perhatikan bahwa ada cara untuk menghindari sifat pemblokiran selamanya dari semi-sinkronisasi menggunakan dua replika, dan manajemen bendera semi-sinkronisasi dinamis menggunakan orkestrator. Saya akan membicarakan ini lebih jauh ke bawah. ) Kebingungan promosi karena jumlah replika yang salahOpsi konfigurasi mengontrol berapa banyak replika yang akan ditunggu MySQL sebelum mengakui transaksi ke aplikasi. Nilai defaultnya adalah 1, artinya meskipun Anda memiliki dua replika semi-sinkronisasi yang dikonfigurasi, MySQL hanya akan menunggu salah satunya untuk merespons sebelum menganggap semuanya baik-baik saja. Dengan asumsi tiga contoh host kami di atas telah ditetapkan, kami tidak akan tahu apakah B atau C mengakui transaksi tersebut. Selama sumber (A) tidak macet, tentu saja ini bukan masalah. Namun, jika A mogok, skrip failover kami (atau manajer topologi kami) harus memutuskan replika mana yang akan dialihkan dan dipromosikan menjadi sumber baru. B atau C. Bergantung pada kecanggihan skrip failover atau manajer topologi, tentu saja mungkin untuk mengetahui replika mana yang telah menerima transaksi terbaru (menggunakan GTID dan/atau posisi log biner), tetapi ini membuat keseluruhan skenario jauh lebih rumit Untuk penyiapan kami, kami telah memilih untuk mengaktifkan semi-sinkronisasi hanya pada salah satu replika dan tidak pernah mempromosikan replika asinkron kedua. Ini dapat dicapai dengan opsi baru orkestrator (lihat di bawah) Menggunakan kembali sumber yang gagalMeskipun dokumentasi semi-sinkronisasi dengan jelas menyatakan bahwa Anda tidak boleh menggunakan kembali sumber yang gagal, saya merasa berkewajiban untuk mengulanginya di sini, karena implikasi penggunaan kembali sumber yang gagal cukup signifikan. Inilah yang dikatakan dokumen. “Dengan replikasi semisinkron, jika sumber macet dan failover ke replika dilakukan, sumber yang gagal tidak boleh digunakan kembali sebagai sumber replikasi, dan harus dibuang. Itu bisa memiliki transaksi yang tidak diakui oleh replika mana pun, yang karenanya tidak dilakukan sebelum kegagalan. “ Paragraf ini berbicara tentang skenario crash point 1 dari atas. Ketika sebuah transaksi ditulis ke log biner pada sumber (A), tetapi tidak sampai ke B atau C, transaksi ini secara resmi tidak pernah terjadi dari perspektif aplikasi dan dari perspektif B dan C Jika Anda sekarang menggunakan kembali A (bahkan sebagai replika B atau C), akan ada transaksi pemberontak di A. Dalam kasus terbaik, A tidak akan memulai dengan benar. Dalam kasus terburuk, Anda tidak akan menyadarinya untuk sementara waktu, tetapi status sumber dan replika tidak akan sama Intinya. Jangan pernah menggunakan kembali sumber yang gagal. Bangun kembali menggunakan xtrabackup dari sumber baru yang dipromosikan Failover otomatis sulitSementara replikasi adalah bagian dari rangkaian fitur inti MySQL, manajemen topologi dan failover otomatis tidak. Artinya, jika host sumber mati, atau harus diturunkan untuk pemeliharaan, MySQL tidak akan memutuskan sumber baru, mengubah target replikasi, dan tentu saja tidak akan memberi tahu aplikasi Anda replika mana yang Untuk mencapai failover otomatis dari sumber yang gagal ke replika, Anda harus menggunakan layanan alat lain. Sayangnya, lanskap alat untuk failover MySQL telah berubah selama bertahun-tahun dan masih sedikit liar di luar sana keepalived, VIP, dan skrip roll-your-own. bukan untuk failover tanpa kerugianUntuk waktu yang sangat lama, kami menggunakan mekanisme failover yang didasarkan pada keepalived, alamat IP virtual mengambang (VIP) dan beberapa skrip pemantauan dan failover kustom Dalam pengaturan ini, aplikasi berbicara ke host sumber MySQL melalui alamat IP mengambang, yang dikontrol dan dikelola oleh keepalived. Setiap host MySQL menjalankan keepalived, yang secara teratur menjalankan skrip pemantauan yang melakukan pemeriksaan dasar (1). Jika pemeriksaan kesehatan sumber MySQL gagal, VIP akan dipindahkan ke host replika yang akan menjadi sumber baru (2) dan kemudian (. ) memicu skrip notifikasi yang akan membalikkan host untuk membaca/menulis untuk menjadi sumber baru (3) Penyiapan ini benar-benar berfungsi dengan baik, membutuhkan sedikit bagian yang bergerak dan tidak ada host tambahan. Namun, menurut pengalaman kami, ini kurang kuat dibandingkan penyiapan berbasis proxy dan tidak cocok jika Anda memerlukan failover lossless dengan semi-sync. Berikut adalah daftar masalah (tidak lengkap) yang kami temui keepalived tidak tahu apa-apa tentang MySQL. Itu hanya mengelola VIP dan tidak mengetahui topologi MySQL. Itu tidak tahu siapa sumbernya, bendera apa yang disetel atau apakah semi-sinkronisasi diaktifkan. Semua itu harus Anda lakukan dengan skrip Anda sendiri. Tidak hanya itu banyak pekerjaan, itu juga rawan kesalahan. Anda harus menerapkan kunci mutex secara manual untuk memastikan hanya satu skrip yang berjalan pada satu waktu, Anda harus menerapkan menunggu log relai diproses, memagari, dan Anda harus secara manual membalik status hanya baca dan semi-sinkronisasi. Banyak yang harus dilakukan, banyak yang salah keepalived terdesentralisasi. Ini bekerja dengan semua node yang berpartisipasi berkomunikasi satu sama lain. Artinya adalah jika komunikasi antar node (bahkan untuk sementara) terganggu, ada risiko otak terbelah yang signifikan dan dengan itu, risiko dua node akan mencoba meraih VIP dan menyatakan diri mereka sebagai sumber dengan. Sementara lapisan jaringan jelas akan memastikan bahwa hanya satu host yang memiliki VIP, itu masih bisa mengepak bolak-balik di antara host. Konsekuensinya cukup dahsyat, karena dapat menyebabkan dua host MySQL menerapkan transaksi. Badai yang sempurna Saya bisa melanjutkan, tetapi saya akan berhenti di situ. Kami mengalami banyak masalah dengan solusi ini saat kami benar-benar mulai memainkan Chaos Monkey, jadi saya menyarankan agar hal ini tidak dilakukan jika Anda menyukai data Anda HAproxy/ProxySQL, orkestrator, Templat Konsul dan KonsulUntungnya, ada beberapa penyiapan populer di luar sana yang berfungsi dengan baik dan tidak mengalami masalah yang disebutkan di atas. Hampir semuanya berkisar menggunakan kombinasi ProxySQL atau HAproxy, orkestra, Konsul, dan Templat Konsul. Ada sejumlah sumber daya yang bagus (4 tautan. ) di luar sana menjelaskannya, jadi saya akan singkat (Perhatikan bahwa dalam ilustrasi ini, "proxy" dapat berupa HAproxy atau ProxySQL. Lihat di bawah untuk detailnya. ) Semua penyiapan tertaut bergantung pada pemantauan host MySQL untuk kesehatannya (responsif, replikasi, kelambatan, …) menggunakan orkestra manajer topologi, dan memproksi lalu lintas SQL melalui HAproxy (proksi tingkat TCP) atau ProxySQL (proksi tingkat aplikasi) . Ketika orkestra mendeteksi kegagalan pada host sumber (A), ia pertama kali menentukan replika mana yang akan menjadi sumber baru, baik B atau C. Setelah mengetahuinya, ia menunjuk ulang replikasi MySQL ( Jebakan kegagalan yang berbahayaBahkan lebih dari menyiapkan replikasi semi-sinkronisasi MySQL, menyiapkan failover seperti yang dijelaskan di atas cukup rumit. Ada banyak alat yang terlibat, dan tentu saja masing-masing memiliki banyak opsi konfigurasi. Banyak hal yang salah Selalu tunggu log relai sebelum menerima lalu lintas tulisReplikasi semi-sinkronisasi menjamin pengiriman transaksi ke replika, tetapi bukan eksekusi. Itu memastikan bahwa log relai pada replika memiliki salinan setiap transaksi, tetapi tetap menangani eksekusi secara asinkron. Itu berarti sangat mudah bagi replika MySQL untuk tertinggal dalam eksekusi transaksi dan membuat jeda replikasi, jika utas SQL tidak dapat mengeksekusi transaksi dengan cukup cepat di mesin penyimpanan (7). Itu sebabnya ini disebut replikasi semi-sinkronisasi, dan bukan replikasi sinkron. (Tentu akan menyenangkan jika sepenuhnya sinkron. ) Jika Anda mengembangkan solusi failover Anda sendiri, Anda harus memastikan bahwa Anda sepenuhnya memproses semua log relai yang ada pada replika yang telah ditetapkan sebagai sumber baru sebelum mengaktifkan lalu lintas tulis, yaitu. e. sebelum pengaturan. Jika tidak, Anda akan mulai menulis transaksi ke mesin penyimpanan yang rusak. Dalam skenario kasus terbaik, mereka tidak terkait, tetapi kemungkinan besar Anda akan mendapatkan pengecualian kunci duplikat yang cukup mengerikan dan akan menghabiskan waktu berjam-jam atau berhari-hari untuk mencoba memperbaiki keadaan. Saat menggunakan orkestra, menunggu log relai dapat diaktifkan dengan pengaturan. Karena orkestra mengelola status hanya-baca, Anda tidak perlu mengkhawatirkannya secara terpisah Pastikan untuk menembak node lain di kepalaAda banyak mode kegagalan berbeda yang dapat menyebabkan keputusan untuk gagal ke replika. Demi kesederhanaan, kita sebagai insinyur sering hanya berbicara tentang hard crash sumber dan terkadang lupa bahwa kegagalan sementara seperti blip jaringan, proses yang macet atau bahkan hanya restart layanan. Tidak mempertimbangkan kegagalan sementara seperti ini bisa menjadi kesalahan besar, karena kami selalu ingin memastikan bahwa aplikasi kami hanya berbicara dengan sumber yang benar, dan bukan ke host yang kembali dari kematian tempat kami gagal. Ketika keputusan dibuat untuk mengalihkan dari sumber yang gagal ke replika yang baru dipromosikan, penting untuk membatasi simpul yang gagal dari aplikasi sebelum menunjuk replika menjadi sumber baru. Proses ini disebut Shoot The Other Node in the Head (STONITH) Berikut adalah contoh failover dengan orkestra yang menyertakan pre-hook STONITH Dalam ilustrasi ini, kita melihat orkestra telah menemukan kegagalan pada sumber (A) dan memutuskan untuk mengalihkan ke B. Menggunakan kait pra-failover orkestra, kami memagari A dengan mengarahkan proxy ke "tempat" sementara failover sedang berlangsung. Setelah orkestra menyelesaikan failover ke sumber baru B (3), dan menunjuk ulang replika C lainnya ke sumber baru (4), itu memperbarui konfigurasi proxy lagi (5) untuk mengirim lalu lintas ke sumber baru (6) Tanpa langkah STONITH (2), proxy akan menunjuk ke sumber yang gagal sampai orkestra selesai dengan failover. Jika host kembali online sementara itu, Anda akan menulis ke host sumber yang salah, dan dalam kasus terburuk Anda akan kehilangan transaksi tersebut Sayangnya, orkestra tidak mendukung STONITH, jadi Anda harus menulis skrip pre-hook Anda sendiri untuk menyelesaikannya. Di HAproxy, Anda cukup memperbarui blok (Harap dicatat bahwa pendekatan STONITH bukannya tanpa kontroversi. Anda dapat membaca lebih lanjut di posting blog ini. ) Menyatukan semuanyaMulai hari ini, kami telah menerapkan penyiapan semi-sinkronisasi lossless dan solusi failover otomatis pada ratusan host, mengelola ratusan juta tabel. Meskipun ada beberapa gangguan (cukup parah) dan ratusan jam yang kami habiskan untuk mengoptimalkan dan mengotomatiskan berbagai hal, menurut saya secara keseluruhan kami cukup senang dengan penyiapannya. Kami menggunakan pengaturan persis seperti yang telah saya bicarakan, yaitu HAproxy, orkestra, Konsul, dan Templat Konsul. Saya telah mengupload sekumpulan file konfigurasi yang representatif ke GitHub, jadi Anda tidak perlu memulai dari nol saat menyiapkannya sendiri Berikut beberapa detail dan konfigurasi penting MySQL Kami menggunakan Percona Server 8, yang berfungsi cukup baik, terlepas dari skala ekstrem yang kami gunakan. Kami telah melihat sejumlah crash yang mengerikan terkait dengan terlalu banyak restart replikasi (yang kami perbaiki dengan memberi tahu orkestra untuk tidak terlalu sering memulai ulang replikasi melalui pengaturan yang lebih tinggi), tetapi selain itu saya akan mengatakan itu solid. Pengaturan semi-sinkronisasi di mysqld kami. file cnf sesuai dengan apa yang telah dibahas di atas. Batas waktu sumber yang lama untuk mencegah async fallback, dan semi-sync diaktifkan secara default
Perlu dicatat bahwa jika Anda mengaktifkan pengaturan sumber semi-sinkronisasi pada semua host (termasuk replika) saat memulai, Anda mungkin mengalami keanehan dalam statistik Anda. Kami memecahkan ini dengan skrip khusus (bukan di repositori) yang menonaktifkan pengaturan pada replika secara dinamis () HAproxy Setelah upaya yang gagal untuk menggunakan ProxySQL (itu terus-menerus mogok), kami memutuskan untuk menggunakan HAproxy untuk mem-proksi lalu lintas SQL ke host sumber yang saat ini aktif. Haproksi utama. File cfg cukup mendasar dan tidak terlalu layak untuk dibicarakan. mysql. Namun, file cfg berisi _Itu juga mengimplementasikan salah satu bagian dari pendekatan STONITH kami. Jika kunci Konsul Templat Konsul Template di atas diperbarui dan dirender ulang oleh Consul Template menggunakan file config haproxy. hcl. Setelah merender ulang file, kami memuat ulang HAproxy untuk menyegarkan konfigurasi. Dalam lingkungan produksi kami yang sebenarnya, kami tidak hanya memanggil Konsul Konsul adalah satu-satunya sumber kebenaran yang host MySQL adalah sumbernya. Instalasinya cukup mudah (lihat file konfigurasi) pemimpin orkestra Kami menjalankan orkestra dalam kelompok tiga dengan backend MySQL dan dengan dukungan Raft (lihat file konfigurasi) Yang terpenting, kami mengaktifkan , yang memastikan bahwa orkestra menunggu log relai sebelum mempromosikan replika dan mengaktifkan baca-tulis. Lihat di atas untuk diskusi terperinci tentang ini Kami juga mengaktifkan pengaturan baru (yang saya sangat bangga telah berkontribusi pada orkestra), yang sepenuhnya mengelola status replika semi-sinkronisasi. dengan pengaturan ini, orkestra akan memberlakukan bendera semi-sinkronisasi yang benar pada replika selama failover (mis. e. mengaktifkan dan menonaktifkannya), cocok dengan jumlah tunggu yang ditetapkan. Bagi kami, ini sangat penting, karena kami hanya ingin memiliki satu replika semi-sinkronisasi, meskipun kami memiliki dua replika, sehingga kami tahu host mana yang harus dialihkan, sehingga dapat melakukan pemeliharaan atau salah satunya dapat Melihat di orkestra. json, Anda dapat melihat bahwa kami memanggil skrip bernama MembungkusnyaSeperti yang Anda tahu dari panjang posting ini, perjalanan kami menuju replikasi dan failover MySQL lossless itu rumit. Sangat mudah untuk mengacaukannya dan kehilangan data. Saya harap posting ini membantu mencegah kehilangan data di organisasi Anda Apa itu replikasi semi sinkronisasi MySQL?Replikasi semisinkron berada di antara replikasi asinkron dan sinkron sepenuhnya . Sumber menunggu hingga setidaknya satu replika telah menerima dan mencatat peristiwa (jumlah replika yang diperlukan dapat dikonfigurasi), lalu melakukan transaksi.
Bagaimana cara mengkonfigurasi replikasi sinkron di MySQL?Mengatur Konfigurasi Sumber Replikasi Mengatur Konfigurasi Replika Membuat Pengguna untuk Replikasi Memperoleh Koordinat Log Biner Sumber Replikasi Memilih Metode untuk Snapshot Data Menyiapkan Replika Mengatur Konfigurasi Sumber pada Replika Menambahkan Replika ke Lingkungan Replikasi Apa itu replikasi sinkron dan asinkron di MySQL?Jenis asli sinkronisasi adalah satu arah, replikasi asinkron, di mana satu server bertindak sebagai sumber, sementara satu atau lebih server lain bertindak sebagai replika. This is in contrast to the synchronous replication which is a characteristic of NDB Cluster (see MySQL NDB Cluster 7.5 and NDB Cluster 7.6).
Apa itu replikasi sinkron?Replikasi sinkron adalah proses penyalinan data melalui jaringan area penyimpanan, jaringan area lokal, atau jaringan area luas sehingga ada banyak salinan data saat ini. Synchronous replication is mainly used for high-end transactional applications that need instant failover if the primary node fails. |