Redis menawarkan dua mekanisme untuk menangani transaksi – transaksi berbasis MULTI/EXEC dan evaluasi skrip Lua. Skrip Redis Lua adalah pendekatan yang disarankan dan cukup populer dalam penggunaan.
Pelanggan Redis™ kami yang menggunakan skrip Lua sering melaporkan kesalahan ini – “BUSY Redis sedang sibuk menjalankan skrip. Anda hanya dapat menelepon SCRIPT KILL atau SHUTDOWN NOSAVE ”. Dalam postingan ini, kami akan menjelaskan properti transaksional Redis dari skrip, tentang apa kesalahan ini, dan mengapa kami harus ekstra hati-hati tentangnya pada sistem yang dikelola Sentinel yang dapat melakukan failover.
Sifat Transaksional Skrip Redis Lua
Redis "transaksi" sebenarnya bukan transaksi seperti yang dipahami secara konvensional – jika terjadi kesalahan, tidak ada rollback penulisan yang dibuat oleh skrip.
“Atomisitas” skrip Redis dijamin dengan cara berikut:
- Setelah skrip mulai dijalankan, semua perintah/skrip lainnya diblokir hingga skrip selesai. Jadi, klien lain melihat perubahan yang dibuat oleh skrip atau tidak. Ini karena mereka hanya dapat mengeksekusi sebelum skrip atau setelah skrip.
- Namun, Redis tidak melakukan rollback, jadi jika terjadi kesalahan dalam skrip, setiap perubahan yang telah dibuat oleh skrip akan dipertahankan dan perintah/skrip selanjutnya akan melihat sebagian perubahan tersebut.
- Karena semua klien lain diblokir saat skrip dijalankan, skrip harus berperilaku baik dan selesai tepat waktu.
Nilai 'lua-time-limit'
Sangat disarankan agar skrip selesai dalam batas waktu. Redis memberlakukan ini dengan dengan cara yang lemah dengan nilai 'lua-time-limit'. Ini adalah waktu maksimum yang diizinkan (dalam ms) yang diizinkan untuk dijalankan oleh skrip. Nilai default adalah 5 detik. Ini adalah waktu yang sangat lama untuk aktivitas terikat CPU (skrip memiliki akses terbatas dan tidak dapat menjalankan perintah yang mengakses disk).
Namun, skrip tidak dimatikan saat dijalankan di luar waktu tersebut. Redis mulai menerima perintah klien lagi, tetapi meresponsnya dengan kesalahan SIBUK.
Jika Anda harus mematikan skrip pada saat ini, ada dua opsi yang tersedia:
- SCRIPT MEMBUNUH perintah dapat digunakan untuk menghentikan skrip yang belum melakukan penulisan apa pun.
- Jika skrip telah melakukan penulisan ke server dan masih harus dihentikan, gunakan SHUTDOWN NOSAVE untuk mematikan server sepenuhnya.
Biasanya lebih baik menunggu skrip menyelesaikan operasinya. Informasi lengkap tentang metode untuk menghentikan eksekusi skrip dan perilaku terkait tersedia di dokumentasi.
Transaksi Redis &Skrip Lua yang Berjalan LamaKlik Untuk TweetPerilaku pada Sistem Ketersediaan Tinggi yang Dipantau Sentinel
Sistem ketersediaan tinggi yang dikelola Sentinel menambahkan masalah baru pada hal ini. Faktanya, diskusi ini berlaku untuk semua sistem ketersediaan tinggi yang bergantung pada polling kesehatan server Redis:
- Skrip yang berjalan lama awalnya akan memblokir perintah klien. Nanti ketika 'lua-time-limit' telah berlalu, server akan mulai merespons dengan kesalahan BUSY.
- Penjaga akan menganggap node tersebut sebagai tidak tersedia, dan jika ini terus berlanjut di luar nilai down-after-milidetik yang dikonfigurasikan pada Sentinel, mereka akan menentukan node tersebut tidak aktif.
- Jika node tersebut adalah master, failover akan dimulai. Node replika mungkin dipromosikan dan dapat mulai menerima koneksi baru dari klien.
- Sementara itu, master yang lebih tua pada akhirnya akan menyelesaikan eksekusi skrip dan kembali online. Namun, Sentinel pada akhirnya akan mengonfigurasi ulang sebagai replika dan akan mulai menyinkronkan dengan master baru. Semua data yang ditulis oleh skrip akan hilang.
|
Demonstrasi
Kami menyiapkan sistem ketersediaan tinggi yang sensitif untuk menunjukkan perilaku failover ini. Setup memiliki 2 server Redis yang berjalan dalam konfigurasi master/replika yang dipantau oleh kuorum 3-penjaga.
Nilai lua-time-limit disetel ke 500 md sehingga mulai merespons klien dengan kesalahan jika skrip berjalan lebih dari 500 md. Nilai turun setelah milidetik pada Sentinel disetel ke 5 detik sehingga simpul yang melaporkan kesalahan ditandai TURUN setelah 5 detik.
Kami mengeksekusi skrip Lua berikut pada master:
local i = 0 while (true) do local key = "Key-" .. i local value = "Value-" .. i redis.call('set', key, value) i = i + 1 redis.call('time') end
Ini terus menulis entri ke master Redis. Kami berlangganan acara di salah satu penjaga untuk mengamati perilaku tersebut.
Skrip dimulai pada master:
$ redis-cli -a --eval test.lua Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Berikut adalah urutan aktivitas yang terpotong seperti yang terlihat di Sentinel:
3) "+vote-for-leader" 4) "9096772621089bb885eaf7304a011d9f46c5689f 1" 1) "pmessage" 2) "*" 3) "+sdown" <<< master marked DOWN 4) "master test 172.31.2.48 6379" 1) "pmessage" 2) "*" 3) "+odown" 4) "master test 172.31.2.48 6379 #quorum 3/2" 1) "pmessage" 2) "*" 3) "-role-change" << role change initiated 4) "slave 172.31.28.197:6379 172.31.28.197 6379 @ test 172.31.2.48 6379 new reported role is master" 1) "pmessage" 2) "*" 3) "+config-update-from" 4) "sentinel 9096772621089bb885eaf7304a011d9f46c5689f 172.31.2.48 26379 @ test 172.31.2.48 6379" 1) "pmessage" 2) "*" 3) "+switch-master" 4) "test 172.31.2.48 6379 172.31.28.197 6379"
Nanti, ketika master lama dibawa online, itu diubah menjadi replika:
3) "-role-change" 4) "slave 172.31.2.48:6379 172.31.2.48 6379 @ test 172.31.28.197 6379 new reported role is master" 1) "pmessage" 2) "*" 3) "-sdown" 4) "slave 172.31.2.48:6379 172.31.2.48 6379 @ test 172.31.28.197 6379" 1) "pmessage" 2) "*" 3) "+role-change" 4) "slave 172.31.2.48:6379 172.31.2.48 6379 @ test 172.31.28.197 6379 new reported role is slave"
Semua data yang ditulis ke master lama melalui skrip hilang.
Rekomendasi
- Anda harus mengetahui karakteristik skrip yang berjalan lama terlebih dahulu sebelum menerapkannya dalam produksi.
- Jika skrip Anda secara teratur melanggar batas waktu lua, Anda harus meninjau skrip secara menyeluruh untuk kemungkinan pengoptimalan. Anda juga dapat memecahnya menjadi beberapa bagian yang selesai dalam jangka waktu yang dapat diterima.
- Jika Anda harus menjalankan skrip yang melanggar batas waktu lua, pertimbangkan untuk menjadwalkan skrip ini selama periode di mana aktivitas klien lainnya akan rendah.
- Nilai lua-time-limit juga dapat ditingkatkan. Ini akan menjadi solusi yang dapat diterima jika aplikasi klien lain yang dijalankan secara paralel dengan skrip dapat mentolerir menerima respons yang sangat tertunda daripada kesalahan SIBUK dan mencoba lagi nanti.
Pertimbangan tambahan pada sistem ketersediaan tinggi yang dipantau Sentinel:
- Jika skrip hanya melakukan operasi baca dan Anda memiliki replika yang tersedia, Anda dapat memindahkan skrip ini ke replika.
Ubah parameter Sentinel turun setelah milidetik ke nilai yang akan memastikan bahwa failover tidak dimulai. Anda harus melakukan ini hanya setelah mempertimbangkan dengan cermat karena meningkatkan nilai secara drastis akan membahayakan karakteristik ketersediaan tinggi dari sistem Anda. Ini juga dapat menyebabkan kegagalan server asli diabaikan.
|