All Products
Search
Document Center

PolarDB:Panduan penggunaan skrip Lua

Last Updated:Feb 11, 2026

Saat Anda perlu mengeksekusi beberapa perintah secara atomik dalam satu interaksi database—misalnya untuk mengimplementasikan distributed locks, rate limiter, atau melakukan conditional updates—beberapa round trip jaringan dapat meningkatkan latency dan memperkenalkan risiko race condition. Orca, protokol yang kompatibel dengan Redis, menyediakan fitur skrip Lua yang memungkinkan Anda mengenkapsulasi beberapa perintah kompatibel Redis ke dalam satu skrip. Database mengeksekusi skrip ini secara atomik, sehingga secara efektif menyelesaikan masalah tersebut serta meningkatkan efisiensi eksekusi dan konsistensi data pada operasi kompleks.

Fitur

Fitur skrip Lua pada Orca, protokol yang kompatibel dengan Redis, memungkinkan Anda mengeksekusi skrip Lua sebagaimana di Redis. Keunggulan utamanya adalah atomicity dan high performance.

  • Atomicity: Semua perintah dalam skrip dieksekusi sebagai satu kesatuan yang tidak dapat dibagi. Tidak ada perintah atau skrip lain yang dapat mengganggu eksekusi skrip tersebut. Hal ini menjamin operasi atomik dan mencegah terjadinya intermediate states akibat eksekusi parsial.

  • High performance:

    • Reduced network overhead: Anda dapat mengemas beberapa perintah ke dalam satu skrip dan mengirimkannya ke database sekaligus. Ini secara signifikan mengurangi jumlah round trip jaringan antara client dan server.

    • Script caching: Anda dapat memuat skrip ke dalam memori kluster terlebih dahulu menggunakan perintah SCRIPT LOAD untuk mendapatkan checksum SHA1. Selanjutnya, Anda dapat menggunakan perintah EVALSHA untuk memanggil skrip tersebut hanya dengan mengirim nilai SHA1 pendek ini. Hal ini lebih lanjut mengurangi volume data yang ditransmisikan melalui jaringan.

Lingkup

  • Versi kluster: Versi kluster harus MySQL 8.0.2, dan versi mesin minor harus 8.0.2.2.33 atau lebih baru.

  • Endpoint: Anda harus menggunakan ORCA Endpoint dengan Read/Write diatur ke Read/Write (Automatic Read/Write Splitting) untuk mengeksekusi perintah skrip Lua.

  • Perintah yang tidak didukung: Perintah-perintah berikut tidak dapat dieksekusi dalam skrip Lua menggunakan redis.call() atau redis.pcall(). Jika Anda mencoba menggunakannya, sistem akan mengembalikan error.

    • Perintah kontrol transaksi: WATCH, UNWATCH, MULTI, EXEC, atau DISCARD

    • Perintah blocking: BLPOP atau BRPOP

    • Perintah skrip Lua: EVAL, EVAL_RO, EVALSHA, EVALSHA_RO, atau SCRIPT

    • Perintah Pub/Sub: SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, atau PUNSUBSCRIBE

    • Perintah manajemen koneksi: AUTH, HELLO, atau CLIENT

Sintaks dasar

Berikut adalah perintah inti untuk mengoperasikan skrip Lua. Untuk informasi lebih lanjut, lihat Lua scripting commands dan Scripting with Lua di website resmi Redis.

Perintah

Sintaks

Deskripsi

EVAL

EVAL script numkeys [key [key ...]] [arg [arg ...]]

Langsung mengeksekusi skrip Lua yang diberikan. Ini adalah metode eksekusi paling dasar. Deskripsi parameter:

  • script: Skrip Lua.

  • numkeys: Menentukan jumlah parameter KEYS[], berupa bilangan bulat non-negatif.

  • KEYS[]: Parameter key Redis yang dilewatkan. Indeks array dimulai dari 1.

  • ARGV[]: Parameter skrip yang dilewatkan. Indeks array dimulai dari 1.

EVAL_RO

EVAL_RO script numkeys [key [key ...]] [arg [arg ...]]

Menjalankan skrip Lua dalam mode read-only. Ini berlaku untuk skenario read/write splitting, memastikan skrip tidak melakukan operasi write. Jika skrip berisi perintah write, sistem akan mengembalikan error. Deskripsi parameternya sama dengan EVAL.

EVALSHA

EVALSHA sha1 numkeys [key [key ...]] [arg [arg ...]]

Menjalankan skrip yang telah di-cache menggunakan checksum SHA1-nya. Jika skrip belum di-cache, sistem akan mengembalikan error NOSCRIPT. Cache skrip target terlebih dahulu menggunakan perintah EVAL atau SCRIPT LOAD, lalu coba lagi.

EVALSHA_RO

EVALSHA_RO sha1 numkeys [key [key ...]] [arg [arg ...]]

Menjalankan skrip yang telah di-cache menggunakan checksum SHA1-nya dalam mode read-only. Ini berlaku untuk skenario read/write splitting, memastikan skrip tidak melakukan operasi write. Jika skrip berisi perintah write, sistem akan mengembalikan error. Deskripsi parameternya sama dengan EVALSHA.

SCRIPT LOAD

SCRIPT LOAD script

Memuat skrip ke dalam cache dan mengembalikan checksum SHA1-nya untuk pemanggilan selanjutnya menggunakan EVALSHA.

SCRIPT EXISTS

SCRIPT EXISTS sha1 [sha1 ...]

Memeriksa apakah satu atau beberapa skrip yang sesuai dengan checksum SHA1 ada di cache. Mengembalikan 1 jika ada, 0 jika tidak ada.

SCRIPT KILL

SCRIPT KILL

Menghentikan skrip Lua yang sedang dieksekusi. Orca mendukung penghentian skrip apa pun (termasuk skrip write) dan secara otomatis membatalkan perubahan data yang dilakukan oleh skrip tersebut, sehingga menjaga konsistensi data.

SCRIPT FLUSH

SCRIPT FLUSH [ASYNC | SYNC]

Menghapus semua cache skrip Lua di kluster saat ini.

  • ASYNC: Menghapus cache skrip secara asinkron.

  • SYNC (default): Menghapus cache skrip secara sinkron.

Contoh operasi

  1. Persiapkan data uji:

    SET polardb orca
  2. Perintah uji:

    EVAL

    EVAL "return redis.call('GET', KEYS[1])" 1 polardb

    Contoh hasil:

    "orca"

    EVAL_RO

    EVAL_RO "return redis.call('GET', KEYS[1])" 1 polardb

    Contoh hasil:

    "orca"

    SCRIPT LOAD

    SCRIPT LOAD "return redis.call('GET', KEYS[1])"

    Contoh hasil:

    "d3c21d0c2b9ca22f82737626a27bcaf5d288f99f"

    EVALSHA

    EVALSHA d3c21d0c2b9ca22f82737626a27bcaf5d288f99f 1 polardb

    Contoh hasil:

    "orca"

    EVALSHA_R

    EVALSHA_RO d3c21d0c2b9ca22f82737626a27bcaf5d288f99f 1 polardb

    Contoh hasil:

    "orca"

    SCRIPT EXISTS

    SCRIPT EXISTS d3c21d0c2b9ca22f82737626a27bcaf5d288f99f ffffffffffffffffffffffffffffffffffffffff

    Contoh hasil:

    1) (integer) 1
    2) (integer) 0

    SCRIPT FLUSH

    Peringatan

    Perintah ini menghapus semua cache skrip Lua di kluster. Cache yang dihasilkan oleh SCRIPT LOAD atau EVAL akan dihapus.

    • Setelah cache dihapus, semua panggilan yang bergantung pada EVALSHA atau EVALSHA_RO mungkin mengembalikan error NOSCRIPT. Anda harus memuat ulang skrip dan mencoba kembali operasi tersebut.

    • Jika banyak skrip di-cache, perintah SCRIPT FLUSH dapat memblokir kluster dalam waktu lama. Kami menyarankan Anda menjalankan perintah ini selama jam sepi.

    • Kami menyarankan Anda menyimpan kode sumber skrip di sisi client atau aplikasi dan mengimplementasikan mekanisme pemulihan otomatis untuk error NOSCRIPT. Misalnya, Anda dapat memuat ulang skrip menggunakan SCRIPT LOAD atau mendaftarkannya kembali menggunakan EVAL.

    SCRIPT FLUSH

    Contoh hasil:

    OK

Skenario umum

Konfigurasikan dan jalankan atomic counter

Anda dapat menghindari race condition yang disebabkan oleh operasi INCR konkuren. Hal ini memastikan bahwa counter benar-benar bertambah dan dapat di-reset secara kondisional.

Tinjauan proses

  1. Tulis skrip Lua.

  2. Muat ke dalam cache kluster.

  3. Gunakan kembali dan jalankan skrip dengan EVALSHA.

Menggunakan kombinasi SCRIPT LOAD + EVALSHA mengurangi network traffic dan meningkatkan performa serta idempotensi. Konten skrip tidak terekspos dalam badan permintaan.

Prosedur

  1. Tulis skrip dan simpan secara lokal:

    -- counter.lua: Jika key tidak ada, atur nilainya ke 0, lalu tambahkan 1; kembalikan nilai baru.
    if redis.call('EXISTS', KEYS[1]) == 0 then
      redis.call('SET', KEYS[1], 0)
    end
    return redis.call('INCR', KEYS[1])
  2. Muat skrip dan dapatkan checksum SHA1:

    SCRIPT LOAD "if redis.call('EXISTS', KEYS[1]) == 0 then redis.call('SET', KEYS[1], 0) end return redis.call('INCR', KEYS[1])"
    
    
    -- Hasil pengembalian
    "b547eabbcde73b25330442e4f4e4dc1783b91241"
  3. (Direkomendasikan) Gunakan kembali dan jalankan skrip:

    EVALSHA b547eabbcde73b25330442e4f4e4dc1783b91241 1 my_counter
    
    -- Hasil pengembalian
    (integer) 1
    -- Jalankan lagi, hasil pengembalian
    (integer) 2

Jalankan skrip read-only

  1. Pastikan skrip tidak berisi operasi write: Periksa apakah skrip memanggil perintah write apa pun, seperti SET, DEL, HSET, atau LPUSH. Jika iya, jangan gunakan EVAL_RO.

    Catatan

    Jika skrip berisi perintah write, sistem akan mengembalikan error (error) ERR Write commands are not allowed from read-only scripts.

  2. Jalankan skrip menggunakan EVAL_RO:

    EVAL_RO "return {redis.call('SET', KEYS[1]), redis.call('TTL', KEYS[1])}" 1 polardb
    
    -- Hasil pengembalian
    1) "orca"
    2) (integer) -1

Hentikan skrip Lua yang berjalan abnormal

Anda dapat mencegah skrip yang berjalan lama memblokir kluster. Untuk itu, hentikan eksekusi menggunakan perintah SCRIPT KILL. Sistem secara otomatis membatalkan semua perubahan untuk menjaga konsistensi data.

Catatan

Anda hanya dapat menghentikan skrip yang sedang dieksekusi. Anda tidak dapat menentukan nilai SHA1 untuk menghentikan skrip tertentu.

SCRIPT KILL

-- Hasil pengembalian
OK

Praktik terbaik optimasi performa

Untuk mengurangi dampak pemblokiran skrip Lua terhadap kluster dan mencegah penggunaan memori berlebih akibat caching banyak skrip yang fungsinya redundan, kami merekomendasikan praktik terbaik berikut:

  • Batas timeout: Timeout eksekusi default untuk satu skrip Lua adalah 300 detik.

    • Hindari menulis skrip Lua yang terlalu besar untuk mencegah konsumsi memori berlebih.

    • Hindari operasi write berdurasi panjang atau batch data besar dalam skrip Lua.

  • Risiko pemblokiran: Skrip Lua dieksekusi secara atomik di kluster. Selama eksekusi, skrip tersebut memblokir perintah dan skrip lainnya. Oleh karena itu, Anda harus mengontrol ukuran batch write dan durasi eksekusi untuk menghindari loop panjang atau traversal data yang luas. Jika perlu, pisahkan logika kompleks menjadi beberapa skrip independen untuk dieksekusi.

  • Cache skrip non-persisten: Cache skrip Lua tidak dihapus selama runtime kluster. Namun, cache akan dihapus setelah restart kluster, alih bencana high-availability (HA), atau eksekusi perintah SCRIPT FLUSH. Anda harus mendaftarkan ulang skrip dalam kasus-kasus tersebut.

  • Pedoman penulisan skrip: Gunakan KEYS[] dan ARGV[] untuk pass parameter. Hindari hard coding parameter dalam skrip.

  • Kurangi network traffic: Gunakan kombinasi SCRIPT LOAD + EVALSHA untuk performa optimal dan pengurangan network traffic.

Contoh operasi

  1. Muat skrip: Saat inisialisasi aplikasi atau saat pertama kali digunakan, muat skrip ke dalam kluster menggunakan SCRIPT LOAD dan dapatkan nilai SHA1-nya. Aplikasi Anda harus menyimpan nilai SHA1 ini secara lokal.

    # Muat skrip yang mengatur nilai suatu key
    SCRIPT LOAD "return redis.call('set', KEYS[1], ARGV[1])"
    # Contoh hasil
    "55b22c0d0cedf3866879ce7c854970626dcef0c3"
  2. Jalankan skrip: Selanjutnya, gunakan perintah EVALSHA dengan nilai SHA1 yang diperoleh pada langkah sebelumnya untuk menjalankan skrip.

    # Gunakan skrip yang di-cache untuk mengatur k1 = v1
    EVALSHA 55b22c0d0cedf3866879ce7c854970626dcef0c3 1 k1 v1
    # Gunakan skrip yang sama untuk mengatur k2 = v2
    EVALSHA 55b22c0d0cedf3866879ce7c854970626dcef0c3 1 k2 v2
  3. Handle error NOSCRIPT: Jika EVALSHA mengembalikan error NOSCRIPT, aplikasi harus menangkap error ini. Kemudian, aplikasi dapat secara otomatis beralih ke penggunaan perintah EVAL atau SCRIPT LOAD untuk mengeksekusi skrip sekali dan menyimpannya di cache kluster.

    • EVAL: Secara otomatis menyimpan ulang skrip selama eksekusi.

    • SCRIPT LOAD: Memuat skrip ke dalam kluster dan mendapatkan nilai SHA1-nya.

  4. Bersihkan penggunaan memori skrip Lua: Jika Anda tidak lagi perlu mengeksekusi skrip Lua, Anda dapat menjalankan perintah SCRIPT FLUSH untuk menghapus cache skrip Lua. Jika terlalu banyak skrip Lua di-cache di kluster, perintah ini dapat memblokir kluster dalam waktu lama. Kami menyarankan Anda menjalankannya selama jam sepi.

FAQ

  • Bagaimana cara menangani error NOSCRIPT No matching script. Please use EVAL.?

    Penyebab: Error ini menunjukkan bahwa Anda mencoba mengeksekusi skrip yang tidak ada di cache kluster menggunakan perintah EVALSHA atau EVALSHA_RO. Error ini biasanya terjadi setelah restart kluster, alih bencana high-availability (HA), atau eksekusi perintah SCRIPT FLUSH.
    Solusi: Kode client Anda harus memiliki logika penanganan error. Saat Anda menangkap error NOSCRIPT, Anda dapat beralih ke penggunaan perintah EVAL atau SCRIPT LOAD untuk mengeksekusi ulang skrip dan menyimpannya di cache kluster. Panggilan EVALSHA selanjutnya kemudian akan berjalan sebagaimana mestinya.

  • Apa yang harus dilakukan jika eksekusi skrip Lua melebihi timeout?

    Timeout skrip default adalah 300 detik. Error timeout biasanya menunjukkan bahwa logika skrip terlalu kompleks atau memproses data terlalu banyak.
    Solusi:

    • Optimalkan logika skrip. Hindari loop yang tidak efisien atau traversal data berskala besar dalam skrip.

    • Jika skrip berjalan terlalu lama, Anda dapat menghentikannya menggunakan perintah SCRIPT KILL. PolarDB kemudian akan membatalkan semua perubahan yang dilakukan oleh skrip tersebut.

    • Pisahkan logika bisnis kompleks menjadi beberapa skrip yang lebih kecil dan cepat untuk dieksekusi secara bertahap.

  • Mengapa eksekusi skrip dengan EVAL_RO mengembalikan error ERR Write commands are not allowed from read-only scripts.?

    EVAL_RO dan EVALSHA_RO adalah mode read-only. Mode ini secara ketat melarang eksekusi operasi write apa pun, seperti SET, HSET, atau DEL. Error ini menunjukkan bahwa skrip Anda berisi perintah write.
    Solusi:

    • Periksa skrip dan hapus semua perintah write.

    • Untuk melakukan operasi write, gunakan perintah EVAL atau EVALSHA.