Selain Dibutuhkan: Apache Ignite Cluster
Cluster di Ignite adalah sekumpulan node server dan klien , di mana node server digabungkan menjadi struktur logis dalam bentuk cincin, dan node klien terhubung ke node server yang sesuai. Perbedaan utama antara node klien dan node server adalah node pertama tidak menyimpan data.
Data, dari sudut pandang logis, termasuk dalam partisi, yang, sesuai dengan beberapa fungsi afinitas, didistribusikan ke seluruh node ( lebih lanjut tentang distribusi data di Ignite ). Di partisi utama ( utama ) dapat berupa salinan ( backup ).
Bagaimana transaksi bekerja di Apache Ignite
Arsitektur cluster di Apache Ignite memberlakukan persyaratan tertentu pada mekanisme transaksi: konsistensi data dalam lingkungan terdistribusi. Ini berarti bahwa data yang terletak di node yang berbeda harus diubah secara holistik dalam kaitannya dengan prinsip ACID . Ada sejumlah protokol yang tersedia untuk melakukan apa yang Anda inginkan. Apache Ignite menggunakan algoritme komit dua fase yang terdiri dari dua tahap:
- mempersiapkan;
- melakukan;
Perhatikan bahwa, tergantung pada tingkat isolasi transaksi , mekanisme pengambilan kunci, dan sejumlah parameter lainnya, detail dalam tahapan dapat berubah.
Mari kita lihat bagaimana kedua fase tersebut terjadi menggunakan transaksi berikut sebagai contoh:
Transaction tx = client.transactions().txStart(PESSIMISTIC, READ_COMMITTED);
client.cache(DEFAULT_CACHE_NAME).put(1, 1);
tx.commit();
Mempersiapkan fase
- β (near node Apache Ignite) β prepare- , primary- , .
- primary- Prepare- backup-, , . backup- .
- backup- Acknowledge- primary-, , , , .
Commit
Setelah menerima pesan pengakuan dari semua node yang berisi partisi primer, node koordinator transaksi mengirimkan pesan Commit, seperti yang ditunjukkan pada gambar di bawah ini.
Sebuah transaksi dianggap selesai saat koordinator transaksi telah menerima semua pesan Pengakuan.
Dari teori ke praktek
Untuk mempertimbangkan logika transaksi, mari beralih ke penelusuran.
Untuk mengaktifkan pelacakan di Apache Ignite, ikuti langkah-langkah berikut:
- ignite-opencensus OpenCensusTracingSpi tracingSpi :
<bean class="org.apache.ignite.configuration.IgniteConfiguration"> <property name="tracingSpi"> <bean class="org.apache.ignite.spi.tracing.opencensus.OpenCensusTracingSpi"/> </property> </bean>
IgniteConfiguration cfg = new IgniteConfiguration(); cfg.setTracingSpi( new org.apache.ignite.spi.tracing.opencensus.OpenCensusTracingSpi());
- :
JVM_OPTS="-DIGNITE_ENABLE_EXPERIMENTAL_COMMAND=true" ./control.sh --tracing-configuration set --scope TX --sampling-rate 1
ignite.tracingConfiguration().set( new TracingConfigurationCoordinates.Builder(Scope.TX).build(), new TracingConfigurationParameters.Builder(). withSamplingRate(SAMPLING_RATE_ALWAYS).build());
:
- API
JVM_OPTS="-DIGNITE_ENABLE_EXPERIMENTAL_COMMAND=true" - sampling-rate , , . , .
- , SPI, . , , .
- API
- PESSIMISTIC, SERIALIZABLE .
Transaction tx = client.transactions().txStart(PESSIMISTIC, SERIALIZABLE); client.cache(DEFAULT_CACHE_NAME).put(1, 1); tx.commit();
Mari beralih ke Pusat Kontrol GridGain (gambaran umum rinci alat) dan lihat pohon rentang yang dihasilkan: Dalam ilustrasi, kita dapat melihat bahwa rentang akar transaksi, yang dibuat pada awal transaksi (). Panggilan TxStart, memunculkan dua grup rentang bersyarat:
- Mesin penangkap kunci dimulai oleh operasi put ():
- transactions.near.enlist.write
- transactions.colocated.lock.map
- transactions.commit, tx.commit(), , , β prepare finish Apache Ignite (finish- commit- ).
Sekarang mari kita lihat lebih dekat pada tahap persiapan dari sebuah transaksi, yang, dimulai dari node koordinator transaksi (node ββdekat dalam istilah Apache Ignite), menghasilkan rentang transaksi.near.prepare.
Setelah berada di partisi utama, permintaan-persiapan memicu pembuatan rentang transaksi.dht.prepare, di mana permintaan-persiapan dikirim ke cadangan tx.process.prepare.req, di mana mereka diproses oleh tx.dht.process.prepare.response dan dikirim kembali ke partisi utama, yang mengirimkan pesan konfirmasi ke koordinator transaksi, sepanjang jalan membuat span tx.near.process.prepare.response. Fase Selesai dalam contoh ini akan serupa dengan fase persiapan, yang menyelamatkan kita dari kebutuhan akan analisis terperinci.
Dengan mengklik salah satu span, kita akan melihat informasi meta yang sesuai:
Jadi, misalnya, untuk rentang transaksi root, kita melihat bahwa itu dibuat pada node klien 0eefd.
Kami juga dapat meningkatkan perincian pelacakan transaksi dengan mengaktifkan penelusuran protokol komunikasi.
Menyiapkan parameter pelacakan
JVM_OPTS="-DIGNITE_ENABLE_EXPERIMENTAL_COMMAND=true" ./control.sh --tracing-configuration set --scope TX --included-scopes Communication --sampling-rate 1 --included-scopes COMMUNICATION
ignite.tracingConfiguration().set(
new TracingConfigurationCoordinates.Builder(Scope.TX).build(),
new TracingConfigurationParameters.Builder().
withIncludedScopes(Collections.singleton(Scope.COMMUNICATION)).
withSamplingRate(SAMPLING_RATE_ALWAYS).build())
Sekarang kami memiliki akses ke informasi tentang transmisi pesan melalui jaringan antara node cluster, yang, misalnya, akan membantu menjawab pertanyaan apakah masalah potensial disebabkan oleh nuansa komunikasi jaringan. Kami tidak akan membahas detailnya, kami hanya mencatat bahwa rangkaian socket.write dan socket.read spans masing-masing bertanggung jawab untuk menulis ke soket dan membaca pesan ini atau itu.
Penanganan Pengecualian dan Crash Recovery
Karenanya, kami melihat bahwa implementasi protokol transaksi terdistribusi di Apache Ignite mendekati kanonik dan memungkinkan Anda mendapatkan tingkat konsistensi data yang tepat, bergantung pada tingkat isolasi transaksi yang dipilih. Jelas, iblis ada dalam detail dan lapisan logika besar tetap berada di luar cakupan materi yang dianalisis di atas. Jadi, misalnya, kami belum mempertimbangkan mekanisme operasi dan pemulihan transaksi jika terjadi jatuhnya node yang berpartisipasi di dalamnya. Kami akan memperbaikinya sekarang.
Kami mengatakan di atas bahwa dalam konteks transaksi di Apache Ignite, tiga jenis node dapat dibedakan:
- Koordinator transaksi (dekat node);
- Node primer untuk kunci yang sesuai (simpul primer);
- Node dengan partisi kunci cadangan (node ββcadangan);
dan dua fase transaksi itu sendiri:
- Mempersiapkan;
- Selesai;
Melalui penghitungan sederhana, kita akan mendapatkan kebutuhan untuk memproses enam opsi untuk node crash - dari cadangan jatuh selama fase persiapan hingga jatuhnya koordinator transaksi selama fase akhir. Mari pertimbangkan opsi ini lebih detail.
Jatuh cadangan baik pada tahap persiapan maupun tahap akhir
Situasi ini tidak memerlukan tindakan tambahan apa pun. Data akan ditransfer ke node cadangan baru secara independen sebagai bagian dari penyeimbangan kembali dari node utama.
Jatuh simpul utama dalam fase persiapan
Jika ada risiko menerima data yang tidak konsisten, koordinator transaksi akan membuat pengecualian. Ini adalah sinyal untuk mentransfer kontrol untuk membuat keputusan untuk memulai kembali transaksi atau cara lain untuk menyelesaikan masalah ke aplikasi klien.
Jatuhnya node utama pada fase akhir
Dalam hal ini, koordinator transaksi menunggu pesan NodeFailureDetection tambahan, setelah menerima pesan yang dapat memutuskan penyelesaian transaksi yang berhasil, jika data ditulis pada partisi cadangan.
Jatuhnya koordinator transaksi
Kasus yang paling menarik adalah hilangnya konteks transaksi. Dalam situasi seperti itu, node utama dan cadangan secara langsung bertukar konteks transaksional lokal satu sama lain, dengan demikian memulihkan konteks global, yang memungkinkan pengambilan keputusan untuk memverifikasi komit. Jika, misalnya, salah satu node melaporkan bahwa ia tidak menerima pesan Selesai, transaksi akan dibatalkan.
Ringkasan
Dalam contoh di atas, kami memeriksa aliran transaksi, menggambarkannya menggunakan penelusuran, yang menunjukkan logika internal secara detail. Seperti yang Anda lihat, implementasi transaksi di Apache Ignite mirip dengan konsep klasik komit dua fase dengan beberapa penyesuaian di bidang kinerja transaksi terkait dengan mekanisme pengambilan kunci, fitur pemulihan setelah kegagalan, dan logika batas waktu transaksi.