MySQL: Eksekusi Tidak Dapat Diampuni





Situs web dan toko online "Eldorado" melakukan sekitar 40 ribu pembelian setiap hari. Mungkin tidak perlu menjelaskan apa artinya ini bagi bisnis perusahaan.



Secara historis, toko berjalan pada mesin Bitrix dengan sejumlah besar kode dan add-on khusus. Penyimpanan adalah cluster MySQL dengan empat server master.



Sejumlah besar perusahaan memiliki aplikasi monolitik, dan banyak yang harus bekerja dengan mereka. Ada banyak cara untuk menangani monolit, tetapi sayangnya, hanya sedikit orang yang menulis tentang yang sukses. Saya harap cerita tentang bagaimana kami menopang monolit kami (sampai kami melihatnya) akan menarik bagi Anda.



Kami sangat menyadari bahwa arsitektur yang masif dapat membawa banyak masalah. Tetapi mudah untuk menghancurkannya, dengan keputusan sederhana yang berkemauan keras, tidak mungkin: penjualan terus berjalan, situs harus berfungsi, perubahan untuk pengguna tidak boleh radikal. Oleh karena itu, transisi dari monolit ke serangkaian layanan mikro membutuhkan waktu, yang perlu kita pertahankan: untuk memastikan sistem beroperasi dan ketahanannya terhadap tekanan.



Apa masalahnya



Untuk waktu yang sangat lama, cluster database di situs eldorado.ru dibangun sesuai dengan skema berikut:





Semua master dalam skema ini bekerja secara bersamaan dan semua dalam mode aktif, secara berurutan memainkan aliran replikasi ... M1-> M2- > M3-> M4-> M1 -> M2-> M3-> M4-> M1-> M2 ...



Dalam pengaturan kami, konfigurasi ini memberikan satu-satunya nilai tambah - memungkinkan sistem untuk bekerja dan mempertahankan bebannya. Faktanya adalah bahwa penyeimbang permintaan aplikasi, setelah pembaruan apa pun untuk memastikan konsistensi, mengalihkan seluruh aliran baca ke master ini, dan satu master pernah tidak cukup untuk menampung seluruh aliran baca.



Tetapi skema seperti itu tidak dapat memberikan keandalan atau kecepatan kerja. Meski terlihat sederhana, ada sejumlah kekurangan. Dia sangat lambat dalam memperbarui data di cluster: dalam kasus terburuk, ada hingga lima lengan replikasi (bergantung pada master mana perubahan dimulai). Karena penundaan ini, banyak masalah muncul baik dalam pengoperasian situs maupun saat melakukan pemesanan di toko online.



Kontra dari skema ini :



  • Budak zona terjauh dari master aktif menerima pembaruan data dalam kasus terburuk hanya setelah 4 kali waktu eksekusi transaksi, terkadang ada penundaan replikasi yang hiruk pikuk;
  • Kegagalan apa pun pada master mana pun menyebabkan ketidakkonsistenan data di seluruh kluster hingga dihapus;
  • (- β€” );
  • ;
  • , ( , , );
  • UPDATE/DELETE SELECT ;
  • , slave_status seconds_behind_master.


Anda dapat meniru perilaku ini di lingkungan pengujian Anda dengan mengaktifkan penundaan replikasi buatan selama 1-2 detik pada slave (yang kami lakukan), ini adalah cara yang bagus untuk menguji kesiapan aplikasi Anda untuk arsitektur terdistribusi tersebut melalui opsi MASTER_DELAY = N .



dan akhirnya, transisi ke database lain dalam kasus kami bukanlah suatu pilihan, karena sistem yang terlalu besar-besaran dan banyak di dalamnya terkait dengan penggunaan MySQL fitur dan bahkan dengan nuansa query optimizer internal.



Bagaimana kami menyelesaikannya



Kami tidak ingin mengubah skema sendiri (ini adalah operasi yang berisiko) dan mulai dengan mencari perusahaan konsultan yang dapat mengusulkan dan menerapkan arsitektur baru, dan melakukannya sehingga situs tetap dapat diakses dan peralihan tidak terlihat. Di antara perusahaan-perusahaan ini terdapat integrator dan pengembang perangkat lunak terbesar.



Beberapa perusahaan tidak menjawab kami (dan ini normal), sementara yang lain menulis bahwa mereka tidak siap untuk melakukan tugas seperti itu. Pada saat yang sama, pertanyaan tentang kemungkinan biaya proyek bahkan tidak muncul.

Jika integrator besar tidak ingin terlibat dalam suatu tugas, maka akan sangat menarik untuk menyelesaikannya sendiri. Kami memiliki peralatan yang bagus untuk kami gunakan, masalah dengan stabilitas dan toleransi kesalahan menjadi prioritas kedua, dan pada awalnya kami ingin mempercepat transfer data. Beberapa opsi yang muncul di MySQL versi 5.6 dan 5.7 bekerja dengan baik untuk ini.



Benar, dokumentasi secara transparan mengisyaratkan bahwa tidak mungkin untuk mengaktifkannya begitu saja, tk. di atas ring pasti akan ada budak dengan versi yang lebih kecil, tapi ini dia seperti ini:

5.7 master mampu membaca log biner lama yang ditulis sebelum peningkatan dan mengirimkannya ke 5.7 budak. Para budak mengenali format lama dan menanganinya dengan benar.



Log biner yang dibuat oleh master setelah peningkatan dalam format 5.7. Ini juga diakui oleh 5,7 budak.



Dengan kata lain, saat memutakhirkan ke MySQL 5.7, budaknya harus MySQL 5.7 sebelum Anda dapat memutakhirkan master ke 5.7.


Untuk pengujian, cukup bagi kami untuk menaikkan cincin pengujian, misalnya, melalui mysqld_multi, dan menjalankan kueri khas di atasnya (Anda bahkan dapat pada host yang sama, 4 instance pada port berbeda dengan set offset berbeda), seperti ini:



mysql -h127.0.0.1 -P 3302 -e "RESET SLAVE; RESET MASTER; SHOW MASTER STATUS\G;"
mysql -h127.0.0.1 -P 3302 -e "CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3301, MASTER_USER='root', MASTER_PASSWORD='', MASTER_LOG_FILE='master1-binlog.000001', MASTER_LOG_POS = 107;START SLAVE;"
mysql -h127.0.0.1 -P 3303 -e "RESET SLAVE; RESET MASTER; SHOW MASTER STATUS\G;"
mysql -h127.0.0.1 -P 3303 -e "CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3302, MASTER_USER='root', MASTER_PASSWORD='', MASTER_LOG_FILE='master2-binlog.000001', MASTER_LOG_POS = 107;START SLAVE;"
mysql -h127.0.0.1 -P 3304 -e "RESET SLAVE; RESET MASTER; SHOW MASTER STATUS\G;"
mysql -h127.0.0.1 -P 3304 -e "CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3303, MASTER_USER='root', MASTER_PASSWORD='', MASTER_LOG_FILE='master3-binlog.000001', MASTER_LOG_POS = 107;START SLAVE;"
mysql -h127.0.0.1 -P 3301 -e "RESET SLAVE; RESET MASTER; SHOW MASTER STATUS\G;"
mysql -h127.0.0.1 -P 3301 -e "CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3304, MASTER_USER='root', MASTER_PASSWORD='', MASTER_LOG_FILE='master4-binlog.000001', MASTER_LOG_POS = 107;START SLAVE;"
      
      





Setelah itu, Anda dapat mengubah versi instance apa pun dengan menjalankan konfigurasi dengan port yang diinginkan dengan biner lain, yang diletakkan di sebelahnya, dan membuat mysql_upgrade untuk tabel data / sistem.



Dijual, kami dapat, untuk waktu yang terbatas, mengirim semua lalu lintas ke hanya satu master, memperbarui yang lain saat ini, lalu beralih ke sana dan memperbarui semua yang lain. Namun untuk ini, perlu dipastikan kompatibilitas format binlog antar versi, sehingga benar-benar semua transaksi berhasil hilang.



Sedikit lebih banyak dokumentasi yang berguna untuk kasus kami:

Untuk menghindari ketidakcocokan, atur variabel berikut pada master MySQL 5.6:



binlog_checksum=NONE
binlog_row_image=FULL
binlog_rows_query_log_events=OFF
log_bin_use_v1_row_events=1 (NDB Cluster only) 
      
      





Bendera ini ternyata wajib bagi kami, meskipun kami tidak menggunakan NDB apa pun, tanpa itu, replikasi berakhir antara server 5.6 - 5.5, dan mysqlbinlog membaca log tanpa opsi ini dengan kesalahan ERROR: Error in Log_event :: read_log_event () : 'Pemeriksaan kesehatan gagal', data_len: 8203, event_type: 30, jika diaktifkan, maka semuanya bahkan dimulai dan berfungsi.

Kami tidak menyertakan GTID, karena Selain persyaratan kompatibilitas dengan semua alat lama, secara obyektif kami tidak melihat keuntungan yang cukup untuk transisi.



gtid_mode=OFF
      
      





Tes paling sederhana untuk memeriksa kebenaran replikasi adalah dengan mengunggah dump secara bergantian ke server dengan 5.5 dan server dengan 5.6 dan melihat apakah semuanya akan baik-baik saja.



Sayangnya, meskipun diharapkan, tes tersebut tidak berhasil.



Last_Error: Column 18 of table 'eldorado2.b_adv_banner' cannot be converted from type '<unknown type>' to type 'datetime'
      
      





datetime di 5.6 adalah spesial, mikrodetik ditambahkan ke dalamnya, jadi di 5.6 memiliki datetime baru, tidak diketahui di



versi 5.5 versi 5.6 - ini dapat bekerja dalam cluster di ring secara paralel dengan 5.5, jika pada saat yang sama tidak ada field yang dibuat di salah satu tabel yang menjalankan replikasi dengan tipe bidang baru. (datetime 5.6! = ​​datetime 5.5, mirip dengan waktu, stempel waktu, ada lebih dari 240 bidang serupa di database kami).



Kami tidak dapat sepenuhnya menjamin tidak adanya DDL dengan bidang ini, dan kami tidak ingin membahayakan kinerja seluruh kluster. Tapi kami memiliki Rencana B. yang lebih aman.



Itu berarti adanya perangkat keras tambahan untuk bermanuver dan meningkatkan salinan lengkap cluster di dekatnya, untungnya, kami memiliki perangkat keras seperti itu. Dan karena ada kemungkinan seperti itu, maka perlu untuk membuat cluster "normal" sekaligus.



Namun, pada saat yang sama, penting untuk memastikan pemeliharaan pengoperasian semua alat pemantauan, debugging, dan analisis binlog saat ini dan untuk menghilangkan sebanyak mungkin semua kekurangan yang ada dari arsitektur saat ini.



Replikasi multisaluran



Sebuah peluru perak diperlukan untuk menjaga situs tetap utuh dan admin diberi makan. Ini adalah replikasi multichannel. Kami apriori tidak mempercayai peluang baru dan tidak yakin tentang teknologinya, kami tidak dapat menemukan informasi atau kasus seperti itu di mana pun, hanya ada sedikit pengalaman publik dalam produksi besar.



Karena itu, kami memikirkan semuanya sendiri, rencananya adalah sebagai berikut:



  • : 5.7, ;
  • ;
  • , β€” , , .








β€” , , , . , , ? . , Β« Β»! , - !

( Β« Β»)


Dalam skema target, 4 master adalah 4 stream rekaman independen untuk setiap slave, yang diproses secara independen.



Pada semua master, sekarang log_slave_updates dapat dimatikan - mereka tidak perlu menyampaikan apa pun ke mana pun, mereka mengirim semua perubahan dalam aliran utama (=> beban pada master bahkan lebih rendah).



Dan pada saat yang sama, Anda juga dapat mengaktifkan format binlog minimum dan pemrosesan transaksi paralel di sepanjang jalan (secara bersyarat, Anda perlu memahaminya dengan benar):



slave_parallel_workers=5
slave_parallel_type=LOGICAL_CLOCK
binlog_row_image=minimal
      
      





Dengan penyiapan ini, kami dapat mengalihkan beban ke cluster baru kapan saja, tetapi rute ini satu arah dan tidak menyediakan rollback.



Selama masa koneksi ke cluster lama, opsi log_slave_updates pada satu titik masuk master ke cluster baru masih ada, dan oleh karena itu semua perubahan dari koneksi ke cluster "lama" dikirim dengan sempurna ke cluster baru, dan segera setelahnya mereka mati opsi ini dinonaktifkan, aplikasi untuk saat ini melihat 3 master lain dan aliran data tidak berpotongan dengan cara apapun.



Hasilnya, kami mendapatkan serangkaian keuntungan berikut:



  • Jika permintaan yang panjang memblokir sesuatu, maka ini hanya memengaruhi satu dari 4 utas replikasi dan tidak memengaruhi yang lain dengan cara apa pun;
  • Format binlog baru, yang sebelumnya tidak mungkin hanya karena versi MySQL, sekarang memakan ruang beberapa kali lebih sedikit dan, oleh karena itu, lalu lintas, karena ini, lebih banyak perubahan dapat melewati seluruh cluster;
  • Sekarang Anda dapat mematikan master mana pun tanpa menimbulkan rasa sakit tanpa memengaruhi yang lainnya;
  • Kecelakaan master sekarang tidak begitu menakutkan, sekarang Anda dapat mengkloning server apa pun dalam satu menit dalam situasi apa pun yang tidak dapat dipahami, membuat ulang server_id, membuat kredit untuk akses budak dan - master baru sudah siap.


Ada juga yang "minus":



  • Setiap master memiliki lebih banyak budak dan lebih mudah untuk masuk ke saluran (pada kenyataannya, ini bukan peningkatan lalu lintas, tetapi redistribusi dalam ruang dan waktu).


Apa yang diberikan skema baru itu



Perpindahan ke skema baru ternyata berhasil, kami melakukannya dalam satu hari, pada 28 Agustus 2020. Pengalaman menggunakan arsitektur baru telah menunjukkan bahwa jumlah masalah replikasi telah berkurang tiga hingga empat kali lipat (tidak mungkin untuk sepenuhnya menghilangkannya). Stabilitas sistem meningkat. Dan hasil utamanya adalah peningkatan throughput maksimum sistem. Jika pengembang sebelumnya dapat menyalahkan masalah yang tidak dapat dipahami pada replikasi, sekarang itu tidak berhasil untuk mereka.



Jumlah masalah klien yang disebabkan oleh penundaan replikasi telah dikurangi beberapa kali, yang berarti bahwa klien mengalami setidaknya sedikit rasa sakit yang berkurang. Sekarang kita dapat mematikan server master mana saja kapan saja untuk melaksanakannya. Ini tidak mempengaruhi seluruh cluster atau menghentikan proses replikasi.



Cluster ini melayani situs utama "Eldorado" - sebagian besar, aplikasi monolitik lama dengan kartu produk, akun pribadi, keranjang, pemrosesan pesanan, pusat panggilan, dll. Pada saat penulisan ini, total beban baca pada cluster (hanya pada slave) adalah 40k rps, kira-kira 5k rps per server basis data, tidak termasuk beban teknis pada masing-masing slave teknis, yang secara signifikan lebih tinggi pada waktu puncak. Ini mungkin tidak terlihat banyak, tetapi kita harus memperhitungkan sifat dan kompleksitas pertanyaan ini.



Kami sangat berharap pengalaman kami dapat bermanfaat bagi seseorang. Selain replikasi multichannel, kami juga menggunakan banyak hal menarik, seperti blackhole dan federated tables, mereka juga memungkinkan Anda untuk menghilangkan banyak sakit kepala (dan menambahkan sedikit untuk mereka yang tidak mengerti mengapa mereka dibutuhkan), jika seseorang tertarik dengan nuansa dan pertanyaan lain tentang MySQL kami - Selamat datang di kolom komentar.



Selama setengah tahun operasi komersial, kami belum menemukan masalah apa pun yang terkait dengan multisaluran, dan kami pasti dapat merekomendasikan penyiapan seperti itu sebagai cukup toleran terhadap kesalahan dan dapat diandalkan.



Monolit itu sendiri sekarang dalam proses pemotongan menjadi sejumlah layanan terpisah dan independen, beberapa di antaranya akan kami pisahkan dan beri tahu Anda tentang pengalaman kami - pantau terus.



Terima kasih khusus kepada tim saya yang luar biasa, kami tidak akan melakukan ini tanpa dia!



PS Ngomong-ngomong, kami masih sangat membutuhkan programmer berbakat . Jika Anda seperti itu, ayo , itu akan menarik.



All Articles