Replikasi database MySQL. pengantar

Jarang yang dilakukan sistem produksi modern tanpa replikasi database. Ini adalah alat yang ampuh di jalur untuk meningkatkan kinerja sistem dan toleransi kesalahan, dan sangat penting bagi pengembang modern untuk memiliki setidaknya pemahaman dasar tentang replikasi. Pada artikel ini, saya akan membagikan beberapa pengetahuan dasar tentang replikasi dan menunjukkan kepada Anda contoh sederhana tentang cara mengatur replikasi di MySQL menggunakan Docker.



gambar



Apa itu replikasi dan mengapa itu dibutuhkan



Replikasi itu sendiri mengacu pada proses sinkronisasi beberapa salinan dari suatu objek. Dalam kasus kami, objek seperti itu adalah server database, dan datanya sendiri memiliki nilai terbesar. Jika kami memiliki dua atau lebih server, dan dengan cara apa pun mempertahankan kumpulan data tersinkronisasi di dalamnya, kami telah menerapkan replikasi sistem. Bahkan opsi manual c mysqldump -> mysql load



juga merupakan replikasi.



Perlu dipahami bahwa replikasi data itu sendiri tidak memiliki nilai, dan hanya alat untuk menyelesaikan tugas-tugas berikut:



  • meningkatkan kinerja membaca data. Dengan bantuan replikasi, kami akan dapat memelihara beberapa salinan server, dan mendistribusikan beban di antara mereka.
  • . , . , .
  • . , , , .
  • . , ( , ), , .
  • . , , .
  • . .


MySQL



Proses replikasi melibatkan penyebaran perubahan data dari server utama (biasanya disebut sebagai master, master ), ke satu atau lebih server bawahan (slave, slave ). Ada juga konfigurasi yang lebih kompleks, khususnya dengan beberapa server master, tetapi untuk setiap perubahan pada server master tertentu, master lainnya secara bersyarat menjadi budak dan menggunakan perubahan ini.



Secara umum, replikasi MySQL terdiri dari tiga langkah:



  1. Server master menulis perubahan data ke log. Log ini disebut log biner , dan perubahan disebut peristiwa log biner .
  2. Budak menyalin perubahan ke log biner menjadi miliknya sendiri, yang disebut log relai .
  3. Budak memutar ulang perubahan dari log relai, menerapkannya ke datanya sendiri.


Jenis replikasi



Ada dua pendekatan yang berbeda secara fundamental untuk replikasi: perintah - perintah demi perintah dan baris demi baris . Dalam kasus replikasi perintah demi perintah, permintaan perubahan data (INSERT, UPDATE, DELETE) dicatat ke log master, dan budak mereproduksi perintah yang sama persis. Dengan replikasi baris demi baris, log akan langsung mengubah baris dalam tabel, dan perubahan aktual yang sama akan diterapkan ke slave.



Karena tidak ada peluru perak, masing-masing metode ini memiliki kelebihan dan kekurangan. Replikasi dengan perintah lebih mudah diterapkan dan dipahami, dan mengurangi beban pada master dan jaringan. Namun, replikasi per perintah dapat menyebabkan efek yang tidak dapat diprediksi saat menggunakan fungsi non-deterministik seperti NOW (), RAND (), dll. Ada juga masalah yang disebabkan oleh data yang tidak sinkron antara master dan slave. Replikasi baris demi baris menghasilkan hasil yang lebih dapat diprediksi, karena perubahan data aktual ditangkap dan direproduksi. Namun, metode ini dapat secara signifikan meningkatkan beban di server master, yang harus mencatat setiap perubahan di log, dan di jaringan tempat perubahan ini menyebar.



MySQL mendukung kedua metode replikasi, dan default (kami dapat mengatakan bahwa itu disarankan) berubah tergantung pada versinya. Versi modern seperti MySQL 8 menggunakan replikasi berbasis baris secara default.



Prinsip kedua untuk membagi pendekatan replikasi adalah jumlah server master... Kehadiran satu server master menyiratkan bahwa hanya itu yang menerima perubahan data, dan merupakan semacam tolok ukur dari mana perubahan sudah disebarkan ke banyak budak. Dalam kasus replikasi master-master, kita mendapat untung dan masalah. Salah satu keuntungannya, misalnya, adalah kami dapat memberikan klien jarak jauh dari Sydney dan Helsinki yang sama kesempatan yang sama cepatnya untuk menulis perubahan mereka ke database. Ini mengarah ke kelemahan utama jika kedua klien secara bersamaan mengubah data yang sama, yang perubahannya dianggap final, yang transaksinya dilakukan, dan yang transaksinya dibatalkan.



Juga, perlu dicatat bahwa kehadiran master replikasi master umumnya tidak dapat meningkatkan kinerja penulisan data dalam sistem. Bayangkan bahwa master kami hanya dapat memproses hingga 1000 permintaan dalam satu waktu. Dengan menambahkan master kedua yang direplikasi ke dalamnya, kami tidak akan dapat memproses 1000 permintaan pada masing-masingnya, karena selain memproses permintaan "mereka", mereka harus menerapkan perubahan yang dibuat pada master kedua. Bahwa, dalam kasus replikasi perintah-demi-perintah, akan membuat total kemungkinan pemuatan pada keduanya tidak lebih dari pada yang paling lemah dari mereka, dan dengan replikasi baris demi baris, efeknya tidak sepenuhnya dapat diprediksi, itu dapat menjadi positif atau negatif, tergantung pada kondisi tertentu.



Contoh membangun replikasi sederhana di MySQL



Sekarang saatnya membuat konfigurasi replikasi sederhana di MySQL. Untuk ini kita akan menggunakan gambar Docker dan MySQL dari dockerhub , serta database dunia .



Untuk memulainya, kita akan meluncurkan dua kontainer, salah satunya akan kita konfigurasikan sebagai master, dan yang lainnya sebagai budak. Mari jaringan mereka sehingga mereka dapat berbicara satu sama lain.



docker run -d --name samplereplication-master -e MYSQL_ALLOW_EMPTY_PASSWORD=true -v ~/path/to/world/dump:/docker-entrypoint-initdb.d  mysql:8.0

docker run -d --name samplereplication-slave -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:8.0

docker network create samplereplication
docker network connect samplereplication samplereplication-master
docker network connect samplereplication samplereplication-slave

      
      





Koneksi volume dengan dump world.sql ditentukan untuk kontainer master untuk mensimulasikan keberadaan beberapa basis awal di atasnya. Saat membuat wadah, mysql akan mengunduh dan mengeksekusi skrip sql yang terletak di direktori docker-entrypoint-initdb.d.



Untuk bekerja dengan file konfigurasi, kita membutuhkan editor teks. Apa pun yang nyaman dapat digunakan, saya lebih suka vim.



docker exec samplereplication-master apt-get update && docker exec samplereplication-master apt-get install -y vim 
docker exec samplereplication-slave apt-get update && docker exec samplereplication-slave apt-get install -y vim

      
      





Pertama-tama, mari buat akun di master yang akan digunakan untuk replikasi:



docker exec -it samplereplication-master mysql

      
      





mysql> CREATE USER 'replication'@'%';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%';

      
      





Selanjutnya, mari ubah file konfigurasi untuk server master:



docker exec -it samplereplication-master bash
~ vi /etc/mysql/my.cnf

      
      





Tambahkan parameter berikut ke file my.cnf di bagian [mysqld]:



server_id = 1 #     
log_bin = mysql-bin #       

      
      





Mengaktifkan / menonaktifkan log biner membutuhkan boot ulang server. Dalam kasus Docker, container dimuat ulang.



docker restart samplereplication-master

      
      





Pastikan log biner diaktifkan. Nilai spesifik seperti nama file dan posisi mungkin berbeda.



mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      156 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

      
      





Untuk memulai replikasi data, perlu untuk "menarik" slave ke status master. Untuk melakukan ini, Anda perlu memblokir sementara wizard itu sendiri untuk membuat snapshot dari data yang sebenarnya.



mysql> FLUSH TABLES WITH READ LOCK;

      
      





Selanjutnya, kami akan menggunakan mysqldump untuk mengekspor data dari database. Tentu saja, dalam contoh ini, Anda dapat menggunakan world.sql yang sama, tetapi mari kita lebih dekat ke skenario yang lebih realistis.



docker exec samplereplication-master mysqldump world > /path/to/dump/on/host/world.sql

      
      





Setelah itu, Anda perlu menjalankan perintah SHOW MASTER STATUS lagi, dan ingat atau tulis nilai File dan Posisi. Inilah yang disebut koordinat dari log biner. Dari merekalah kita selanjutnya akan menunjukkan untuk memulai budak. Sekarang kita dapat membuka kunci master lagi:



mysql> UNLOCK TABLES;

      
      





Master telah dikonfigurasi dan siap untuk mereplikasi ke server lain. Mari beralih ke budak sekarang. Pertama-tama, muat dump dari master ke dalamnya.



docker cp /path/to/dump/on/host/world.sql samplereplication-slave:/tmp/world.sql
docker exec -it samplereplication-slave mysql
mysql> CREATE DATABASE `world`;
docker exec -it samplereplication-slave bash
~ mysql world < /tmp/world.sql

      
      





Dan kemudian kita akan mengubah konfigurasi slave dengan menambahkan parameter:



log_bin = mysql-bin  #      
server_id = 2  #   
relay-log = /var/lib/mysql/mysql-relay-bin #    
relay-log-index = /var/lib/mysql/mysql-relay-bin.index  #        
read_only = 1  #     “ ”

      
      





Setelah itu, muat ulang budak:



docker restart samplereplication-slave

      
      





Dan sekarang kita perlu memberi tahu slave server mana yang akan menjadi masternya, dan di mana harus mulai mereplikasi data. Alih-alih MASTER_LOG_FILE dan MASTER_LOG_POS, Anda harus mengganti nilai yang diperoleh dari SHOW MASTER STATUS pada master. Parameter ini secara kolektif disebut koordinat log biner.



mysql> CHANGE MASTER TO MASTER_HOST='samplereplication-master', MASTER_USER='replication', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=156;

      
      





Mari mulai memutar ulang log relai, dan periksa status replikasi:



mysql> START SLAVE;
mysql> SHOW SLAVE STATUS\G

      
      





STATUS BUDAK
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: samplereplication-master
                  Master_User: replication
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 156
               Relay_Log_File: mysql-relay-bin.000002
                Relay_Log_Pos: 324
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 156
              Relay_Log_Space: 533
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: c341beb7-3a33-11eb-9440-0242ac110002
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 0
            Network_Namespace:
1 row in set, 1 warning (0.00 sec)
      
      







Jika semuanya berjalan dengan baik, status Anda akan terlihat serupa. Parameter kunci di sini:



  • Slave_IO_State - sebenarnya, status replikasi.
  • Read_Master_Log_Pos adalah posisi terakhir yang dibaca dari log master.
  • Relay_Master_Log_File - File log master saat ini.
  • Seconds_Behind_Master - slave tertinggal di belakang master, dalam hitungan detik.
  • Last_IO_Error , Last_SQL_Error - kesalahan replikasi, jika ada.


Mari kita coba mengubah data pada master:



docker exec -it samplereplication-master mysql

      
      





mysql> USE world;
mysql> INSERT INTO city (Name, CountryCode, District, Population) VALUES ('Test-Replication', 'ALB', 'Test', 42);

      
      





Dan periksa apakah mereka muncul di budak.



docker exec -it samplereplication-slave mysql

      
      





mysql> USE world;
mysql> SELECT * FROM city ORDER BY ID DESC LIMIT 1;
+------+------------------+-------------+----------+------------+
| ID   | Name             | CountryCode | District | Population |
+------+------------------+-------------+----------+------------+
| 4081 | Test-Replication | ALB         | Test     |         42 |
+------+------------------+-------------+----------+------------+
1 row in set (0.00 sec)

      
      





Luar biasa! Rekor yang dimasukkan juga terlihat pada budak. Selamat, Anda sekarang telah membuat replikasi MySQL pertama Anda!



Kesimpulan



Saya berharap dalam kerangka artikel ini saya dapat memberikan pemahaman dasar tentang proses replikasi, membiasakan diri dengan penggunaan alat ini, dan mencoba secara mandiri menerapkan contoh replikasi sederhana di MySQL. Topik replikasi, dan penerapan praktisnya, sangat luas, dan jika Anda tertarik dengan topik ini, saya dapat merekomendasikan sumber-sumber berikut untuk dipelajari:



  • Laporkan "Cara Kerja Replikasi MySQL" oleh Andrey Aksenov (Sphinx)
  • Buku “MySQL to the Maximum. Optimasi, replikasi, backup ”- Baron Schwartz, Petr Zaitsev, Vadim Tkachenko
  • "Beban tinggi" - di sini Anda dapat menemukan resep khusus untuk replikasi data


Semoga artikel ini bermanfaat dan kami menyambut umpan balik serta komentar Anda!



All Articles