Mengapa Anda perlu replikasi semi-sinkron?

Halo semuanya. Dalam sentuhan Vladislav Rodin. Saat ini saya mengajar kursus arsitektur perangkat lunak dan arsitektur perangkat lunak beban tinggi di portal OTUS. Sebagai antisipasi dimulainya aliran baru kursus "Arsitek beban tinggi", saya memutuskan untuk menulis materi kepenulisan kecil, yang ingin saya bagikan kepada Anda.




pengantar


Karena kenyataan bahwa hanya sekitar 400-700 operasi per detik dapat dilakukan pada HDD (yang tidak dapat dibandingkan dengan rps tipikal yang jatuh pada sistem yang sarat beban), basis data disk klasik adalah leher arsitektur yang sempit. Oleh karena itu, perhatian khusus harus diberikan pada pola penskalaan repositori ini.

Saat ini ada 2 pola penskalaan dasar: replikasi dan sharding. Sharding memungkinkan Anda untuk skala operasi penulisan, dan, sebagai akibatnya, mengurangi rps untuk merekam per satu server di cluster Anda. Replikasi memungkinkan Anda melakukan hal yang sama, tetapi dengan operasi baca. Artikel ini dikhususkan untuk pola ini.

Replikasi


Jika Anda melihat replikasi pada tingkat yang sangat tinggi, ini adalah hal yang sederhana: Anda memiliki satu server, datanya ada di sana, dan kemudian server ini berhenti mengatasi beban membaca data ini. Anda menambahkan beberapa server lagi, menyinkronkan data di semua server, dan pengguna dapat membaca dari server mana pun di kluster Anda.

Terlepas dari kesederhanaan yang tampak, ada beberapa opsi untuk mengklasifikasikan berbagai implementasi skema ini:

  • Dengan peran dalam cluster (master-master atau master-slave)
  • Dengan objek yang diteruskan (berbasis baris, berbasis pernyataan atau campuran)
  • Menurut mekanisme sinkronisasi simpul

Hari ini kita akan membahas poin ke-3.

Bagaimana transaksi dilakukan


Topik ini tidak berhubungan langsung dengan replikasi, artikel terpisah dapat ditulis tentangnya, namun, karena tanpa pemahaman lebih lanjut tentang mekanisme komitmen transaksi, bacaan lebih lanjut tidak berguna, izinkan saya mengingatkan Anda tentang hal-hal yang paling mendasar. Transaksi dilakukan dalam 3 tahap:

  1. Menulis transaksi ke log basis data.
  2. Penerapan transaksi dalam mesin basis data.
  3. Kembalikan konfirmasi kepada klien tentang keberhasilan aplikasi transaksi.

Dalam berbagai basis data, nuansa dapat muncul dalam algoritme ini: misalnya, dalam mesin InnoDB dari database MySQL terdapat 2 log: satu untuk replikasi (log biner) dan yang lainnya untuk mempertahankan ACID (undo / redo log), sedangkan di PostgreSQL ada satu log yang mengeksekusi kedua fungsi (tulis log depan = WAL). Namun di atas justru konsep umum yang memungkinkan nuansa seperti itu diabaikan.

Replikasi sinkron (sinkron)


Mari tambahkan logika untuk mereplikasi perubahan yang diterima ke algoritma komit transaksi:

  1. Menulis transaksi ke log basis data.
  2. Penerapan transaksi dalam mesin basis data.
  3. Mengirim data ke semua replika.
  4. Terima konfirmasi dari semua replika tentang transaksi pada mereka.
  5. Kembalikan konfirmasi kepada klien tentang keberhasilan aplikasi transaksi.

Dengan pendekatan ini, kami mendapatkan sejumlah kerugian:

  • klien sedang menunggu perubahan untuk diterapkan ke semua replika.
  • karena jumlah node dalam gugus meningkat, kami mengurangi kemungkinan operasi penulisan akan berhasil.

Jika semuanya kurang lebih jelas dengan paragraf 1, maka alasan paragraf 2 harus diklarifikasi. Jika selama replikasi sinkron kami tidak mendapatkan respons dari setidaknya satu simpul, kami memutar kembali transaksi. Dengan demikian, meningkatkan jumlah node dalam cluster, Anda meningkatkan kemungkinan bahwa operasi penulisan akan gagal.

Bisakah kita menunggu konfirmasi hanya dari sebagian kecil node, misalnya, dari 51% (kuorum)? Ya, kami bisa, tetapi dalam versi klasik, konfirmasi dari semua node diperlukan, karena ini adalah bagaimana kami dapat memastikan konsistensi data yang lengkap dalam klaster, yang merupakan keuntungan tidak diragukan dari jenis replikasi ini.

Replikasi async


Mari kita modifikasi algoritma sebelumnya. Kami akan mengirimkan data ke replika "beberapa saat kemudian", dan "beberapa waktu kemudian" perubahan akan diterapkan pada replika:

  1. Menulis transaksi ke log basis data.
  2. Penerapan transaksi dalam mesin basis data.
  3. Kembalikan konfirmasi kepada klien tentang keberhasilan aplikasi transaksi.
  4. Mengirim data ke replika dan menerapkan perubahan padanya.

Pendekatan ini mengarah pada fakta bahwa cluster cepat, karena kami tidak membuat klien menunggu data untuk mencapai replika dan bahkan dikomunikasikan.

Tetapi kondisi menjatuhkan data ke replika "beberapa saat kemudian" dapat menyebabkan hilangnya transaksi, dan hilangnya transaksi yang dikonfirmasi kepada pengguna, karena jika data tidak memiliki waktu untuk mereplikasi, konfirmasi dikirim kepada klien tentang keberhasilan operasi, dan simpul tempat perubahan datang terbang. HDD, kami kehilangan transaksi, yang dapat menyebabkan konsekuensi yang sangat tidak menyenangkan.

Replikasi semisync


Akhirnya, kami mendapat replikasi semi-sinkron. Jenis replikasi ini tidak terlalu dikenal dan tidak terlalu umum, tetapi sangat menarik, karena dapat menggabungkan keuntungan dari replikasi sinkron dan asinkron.

Mari kita coba menggabungkan 2 pendekatan sebelumnya. Kami tidak akan lama menyimpan klien, tetapi kami mengharuskan data direplikasi:

  1. Menulis transaksi ke log basis data.
  2. Penerapan transaksi dalam mesin basis data.
  3. Mengirim data ke replika.
  4. Menerima konfirmasi dari replika tentang menerima perubahan (perubahan akan diterapkan “beberapa saat kemudian”).
  5. Kembalikan konfirmasi kepada klien tentang keberhasilan aplikasi transaksi.

Harap perhatikan bahwa dengan algoritme ini, kerugian transaksi hanya terjadi jika terjadi penurunan simpul yang menerima perubahan dan simpul replika. Probabilitas kerusakan seperti itu dianggap kecil, dan risiko ini diterima.

Tetapi dengan pendekatan ini, risiko pembacaan hantu dimungkinkan. Bayangkan skenario berikut: pada langkah 4, kami tidak menerima konfirmasi dari replika apa pun. Kami harus memutar kembali transaksi ini, dan tidak mengembalikan konfirmasi kepada klien. Karena data diterapkan pada langkah 2, ada kesenjangan waktu antara akhir langkah 2 dan rollback transaksi, di mana transaksi paralel dapat melihat perubahan-perubahan yang seharusnya tidak ada dalam database.

Replikasi semisync kurang-kalah


Jika Anda berpikir sedikit, Anda hanya dapat mengubah langkah-langkah algoritma di tempat-tempat untuk memperbaiki masalah pembacaan hantu dalam skenario ini:

  1. Menulis transaksi ke log basis data.
  2. Mengirim data replika.
  3. Menerima konfirmasi dari replika tentang menerima perubahan (perubahan akan diterapkan “beberapa saat kemudian”).
  4. Penerapan transaksi dalam mesin basis data.
  5. Kembalikan konfirmasi kepada klien tentang keberhasilan aplikasi transaksi.

Sekarang kami melakukan perubahan hanya jika itu direplikasi.

Kesimpulan


Seperti biasa, tidak ada solusi yang sempurna, ada satu set solusi, yang masing-masing memiliki kelebihan dan kekurangan sendiri dan cocok untuk memecahkan berbagai kelas masalah. Ini juga berlaku untuk memilih mekanisme untuk menyinkronkan data dalam database yang direplikasi. Seperangkat manfaat yang dimiliki replikasi semi-sinkron solid dan cukup menarik untuk dianggap layak mendapat perhatian, meskipun prevalensinya rendah.

Itu saja. Sampai jumpa di lapangan !

All Articles