Cara menentukan master di mysql master-slave

17

Saya menyiapkan replikasi MySQL Master-slave dan saya mencoba mencari cara untuk menangani situasi failover di mana saya mempromosikan slave to master (jika master turun).

Server aplikasi saya perlu mengarahkan semua penulisan ke master saat ini, tetapi saya tidak dapat menggunakan tingkat server HA antara master dan slave (detak jantung, terus hidup) karena dua server db berada pada subnet yang sangat berbeda di lokasi fisik yang berbeda.

Saya pikir ini adalah sesuatu yang perlu saya tangani di level aplikasi. Saya dapat meminta dua server dan bertanya yang mana adalah master, lalu melakukan semua pertanyaan dengan yang itu.

Apakah ada permintaan di MySQL untuk melihat apakah server saat ini adalah master dalam replika master-slave?

Ethan Hayon
sumber
Apa versi MySQL yang Anda gunakan ???
RolandoMySQLDBA
Ini adalah output mysqlServer version: 5.5.23 MySQL Community Server (GPL)
Ethan Hayon

Jawaban:

13

@RolandoMySQLDBA telah menjawab pertanyaan secara akurat ... tetapi ia juga menunjukkan bahwa solusinya adalah "cepat dan kotor."

Dan itu adalah pernyataan yang sangat benar. :)

Hal yang menjadi perhatian saya di sini bukanlah dengan jawaban itu, melainkan bahwa pertanyaan awal tampaknya membuat asumsi yang salah:

Saya dapat meminta dua server dan bertanya yang mana adalah master, lalu melakukan semua pertanyaan dengan yang itu.

Masalahnya adalah bahwa dalam replikasi MySQL, master tidak pernah benar-benar menyadari bahwa itu adalah master.

Konsep "promosi untuk menguasai" sebenarnya bukan konsep replikasi asinkron MySQL. "Mempromosikan" server MySQL ke peran master adalah sesuatu yang terjadi "eksternal ke" server MySQL, sebagai lawan dari sesuatu yang terjadi "internal ke" server MySQL.

"Promosi ke master" tidak dilakukan oleh segala jenis penyediaan server, karena, secara teknis, setiap server MySQL yang mengaktifkan pencatatan biner adalah master, walaupun tidak pernah memiliki slave. SHOW MASTER STATUSbekerja dengan cara yang persis sama dan mengembalikan hasil yang sama persis, budak atau tidak, dan master dengan 2 budak tidak lebih atau kurang master daripada master dengan 1 budak atau 0 budak. Demikian pula, master yang semua budaknya offline tetap sama besarnya dengan master, karena ketika budak kembali online, mereka akan mengambil replikasi di mana mereka tinggalkan.

Dalam arti tertentu, satu-satunya "kesadaran" pada bagian dari kedua server bukanlah apakah itu master, melainkan apakah itu adalah seorang budak (atau "tidak").

Itulah yang ditanyakan solusi Rolando: "apakah Anda seorang budak?" Jika jawabannya tidak, maka asumsinya adalah bahwa ini harus menjadi tuan ... yang ia juga tunjukkan sebagai asumsi yang salah jika STOP SLAVE;dikeluarkan. Tetapi budak yang dihentikan masihlah seorang budak, jadi "bukan budak" (kapan saja) tidak sama dengan "menjadi tuan."

Tes serupa dapat dilakukan pada master yang diduga:

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';

atau

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';

Jika nilainya nol, maka utas slave slave tidak tersambung. Tes ini memiliki cacat yang sama, yaitu jika budak terputus secara administratif, terisolasi, atau gagal, maka tidak akan terhubung. Jadi ini juga tidak benar-benar menyelesaikan apa pun.

Lebih buruk lagi (untuk salah satu skenario ini) "tabel" information_schema.processlist adalah tabel virtual yang terwujud setiap kali dipilih, dan ini membutuhkan waktu dan biaya sumber daya. Semakin sibuk server Anda, semakin banyak biayanya, karena setiap aktivitas utas harus diintip ke dalam.

Solusi yang lebih ringan adalah:

SELECT @@global.read_only;

Pada seorang budak, Anda dapat / harus mengatur variabel global read_onlysehingga pengguna tanpa SUPERhak istimewa tidak dapat menulisnya secara tidak sengaja (dan aplikasi Anda seharusnya tidak memilikinya SUPER). Jika Anda secara manual "mempromosikan" budak ke peran utama, Anda SET GLOBAL read_only = OFFdapat mengaktifkan penulisan. (Replikasi selalu dapat menulis ke budak, tidak peduli bagaimana ini diatur).

Tapi saya pikir, masih ada hal penting yang terlewatkan:

Saya akan mengusulkan bahwa aplikasi tidak harus membuat keputusan ini secara heuristik dalam pengaturan master / slave, dan tentu saja tidak berdasarkan koneksi-oleh-koneksi. Aplikasi harus menggunakan opsi konfigurasi yang sulit, atau aplikasi harus tetap tidak sadar dan tujuan koneksi database ditangani oleh sesuatu yang lain.

Atau, paling tidak, aplikasi tidak boleh beralih sampai master gagal, dan kemudian tidak boleh kembali dengan sendirinya.

Inilah mengapa saya mengatakan bahwa: setelah "keputusan" dibuat - oleh siapa pun atau apa pun - untuk menjadikan server lain master, aplikasi tidak dapat diizinkan dengan alasan apa pun untuk beralih kembali ke master asli, bahkan setelah itu kembali online , tanpa intervensi.

Katakanlah Anda menabrak bug dan ada crash yang dipaksakan oleh perangkat lunak; mysqld_safepatuh memulai kembali mysqld, dan pemulihan kerusakan InnoDB tampil dengan sempurna. Tapi itu butuh beberapa menit.

Sementara itu, master sedang down sehingga aplikasi Anda telah beralih ke slave. Transaksi telah dibuat, pesanan ditempatkan, dana ditransfer, komentar diposting, blog diedit, apa pun sistem Anda.

Sekarang, master asli kembali online.

Jika aplikasi Anda beralih kembali ke master asli, Anda berada di dunia yang benar-benar terluka, karena hal berikutnya yang mungkin terjadi adalah replikasi berhenti karena inkonsistensi, karena aplikasi Anda telah mengubah data pada slave di mean waktu. Anda sekarang memiliki dua server database dengan data tidak konsisten yang harus Anda rekonsiliasi secara manual. Jika ada dolar atau poin atau kredit yang terlibat, Anda sekarang memiliki saldo yang tidak cocok.

Jadi, sangat penting bahwa aplikasi tidak diizinkan untuk beralih kembali ke master asli tanpa campur tangan Anda.

Tunggu, apakah Anda baru saja menemukan masalah dengan skenario ini seperti yang saya jelaskan? Master telah gagal tetapi aplikasi Anda tidak akan menggunakan slave, karena ia berpikir slave masih slave dan bukan master ... information_schema.processlistpermintaan pada slave masih akan mengembalikan non-nol bahkan jika server master dimatikan .

Jadi tidak ada gunanya aplikasi menemukan sesuatu, karena Anda harus secara manual STOP SLAVEagar tes itu berguna.

Mungkin pendekatan yang lebih baik jika Anda ingin aplikasi dapat beralih adalah mengkonfigurasi server dengan replikasi melingkar.

Replikasi melingkar memiliki masalah yang melekat sendiri, tetapi selama aplikasi Anda hanya selalu menulis ke satu server pada suatu waktu, sebagian besar masalah tersebut menjadi non-masalah. Dengan kata lain, kedua mesin selalu dan sekaligus merupakan master dan slave, dalam arti replikasi, tetapi aplikasi Anda, melalui beberapa mekanisme, selalu hanya menunjuk ke satu mesin sekaligus sebagai "master" di mana ia dapat dan harus menulis .

Anda tidak dapat menggunakan alat HA di server MySQL karena pemisahan mereka, tetapi Anda bisa menerapkannya dengan HAProxy berjalan di server aplikasi. Aplikasi terhubung ke "MySQL" di localhost, yang bukan MySQL sama sekali, tetapi sebenarnya HAProxy ... dan meneruskan koneksi TCP ke mesin MySQL yang sesuai.

HAProxy dapat menguji koneksi ke server MySQL dan hanya menawarkan lalu lintas ke mesin MySQL yang menerima koneksi dan memungkinkan otentikasi.

Kombinasi HAProxy yang berjalan di server aplikasi (permintaannya akan sumber daya tidak akan substansial dibandingkan dengan hal lain yang harus dilakukan server aplikasi - cukup banyak hanya mengikat soket dan mengabaikan muatannya) ... dan replikasi melingkar MySQL akan menjadi pendekatan yang mungkin saya ambil dalam contoh ini, berdasarkan apa yang diketahui dari pertanyaan.

Atau, untuk pengaturan ketat manual, lakukan sesuatu yang jauh lebih sederhana daripada "penemuan," seperti entri dalam /etc/hostsfile server aplikasi dengan nama host yang digunakan aplikasi untuk terhubung ke MySQL, yang dapat Anda perbarui secara manual - dengan asumsi promosi budak menjadi master dimaksudkan untuk menjadi proses manual.

Atau, sesuatu yang lebih kompleks, menggunakan Percona XtraDB Cluster. Untuk ini, Anda ingin menambahkan server ketiga, karena dengan 3 node di PXC, jika 2 server dapat melihat satu sama lain tetapi terisolasi dari 1 server (jika ketiganya masih berjalan) kedua server tetap berjalan dengan gembira tetapi 1 server meringkuk menjadi bola kecil dan menolak untuk melakukan apa pun karena menyadari itu pasti yang aneh. Ini berfungsi karena 2 menyadari mereka masih merupakan mayoritas dari node yang sedang online sebelum jaringan terpecah dan 1 menyadari bahwa itu bukan. Dengan PXC, tidak masalah server mana yang terhubung dengan aplikasi Anda.

Saya mengatakan semua ini adalah untuk mengatakan "tidak memiliki aplikasi jajak pendapat server untuk melihat mana yang merupakan master" karena itu akan menggigit Anda cepat atau lambat dan itu akan menggigit kinerja Anda sampai hari itu menggigit.

Michael - sqlbot
sumber
Pertama-tama, terima kasih atas tanggapan yang ditulis dengan baik. Saya pikir Anda telah mengusulkan solusi yang baik. Saya telah berpikir tentang menggunakan replikasi melingkar di masa lalu, tetapi telah membaca hal-hal buruk mengenai keandalannya. Namun, banyak dari masalah ini dapat dicegah dengan memodifikasi auto_increment_increment, auto_increment_offset, dll ... Menggunakan HAProxy secara lokal di server aplikasi (hanya sebagai failover saja) akan bekerja dengan baik bagi kita karena kita tidak perlu memodifikasi aplikasi kita, oleh karena itu abstraksi kegagalan tersebut logika jauh dari lapisan aplikasi. Saya akan memeriksa konfigurasi HAProxy, terima kasih!
Ethan Hayon
1
Senang untuk membantu. Pemungutan suara akan dihargai jika Anda belum melakukannya. Replikasi melingkar sama andalnya dengan master / slave (ini teknologi yang sama, hanya berjalan dua arah) selama Anda memahami cara kerjanya dan menggunakannya dengan cara yang masuk akal. Selama server disinkronkan dengan benar dan aplikasi hanya menulis ke satu server pada satu waktu, saya tidak pernah punya masalah dengan itu. The auto_increment_*variabel masih baik untuk digunakan dalam skenario ini, "berjaga-jaga." Juga, ingatlah untuk menggunakan binlog_format= rowatau mixed- tidak statement(bahkan jika Anda tidak melakukan lingkaran).
Michael - sqlbot
Saya mengubah jawaban yang diterima murni karena penjelasan terperinci ini membantu saya merancang ulang sistem agar lebih kuat. @ RolandoMySQLDBA jawaban masih benar dan menyelesaikan masalah yang saya jelaskan sebelumnya. Terima kasih!
Ethan Hayon
10

Jika Anda hanya menggunakan Master / Budak, berikut adalah sesuatu yang cepat dan kotor:

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

Apa artinya ini bagimu?

  • Jika SlaveThreadCount= 0, Anda memiliki Master
  • Jika SlaveThreadCount> 0, Anda memiliki Budak

CAVEAT : Ini berfungsi selama Anda tidak lariSTOP SLAVE;

Hal lain untuk dicoba adalah ini: Jika Anda menonaktifkan log biner pada Slave dan Anda menjalankan SHOW MASTER STATUS;, Master memberi Anda log biner saat ini. Budak tidak memberi Anda apa-apa.

RolandoMySQLDBA
sumber
Luar biasa, inilah yang saya butuhkan. Apakah Anda pikir ini solusi berantakan untuk masalah ini? Satu-satunya masalah yang dapat saya bayangkan adalah kedua server dipromosikan menjadi master, tetapi itu seharusnya tidak pernah benar-benar terjadi.
Ethan Hayon
Jika jawaban ini adalah yang Anda butuhkan, tandai jawaban yang diterima dengan mengklik tanda centang pada jawaban saya.
RolandoMySQLDBA
Saya tidak dapat menandainya sebagai diterima selama 5 menit :)
Ethan Hayon
Tidak masalah. Saya senang saya bisa membantu !!!
RolandoMySQLDBA
0

jalankan pernyataan ini dari mysql prompt
mysql> tampilkan status budak;

Pada slave itu menunjukkan banyak parameter dan nilai / statusnya sementara pada master itu menunjukkan set kosong

akrai48
sumber