Topik ini membahas pemindaian keyspace, yaitu ruang tempat seluruh key milik satu server disimpan. Pembahasan mencakup kontrak perintah SCAN sebagai pengganti KEYS, iterasi kursor (cursor) dari nilai 0 sampai kembali ke 0, opsi MATCH, COUNT, dan TYPE, serta disiplin pemindaian yang layak digunakan pada produksi. Seluruh contoh dijalankan pada server khusus di port 6381, sehingga keluarannya dapat direproduksi ulang di terminal.
KEYS dan blokirnya pada keyspace besar#
Perintah KEYS mengembalikan seluruh key yang cocok dengan pola dalam satu pemanggilan. Server menjalankan pemindaian tersebut di thread utama, yaitu satu alur eksekusi yang juga melayani perintah klien lain, sehingga perintah berikutnya harus menunggu pemindaian selesai. Dokumentasi resmi mencatat pemindaian satu juta key memerlukan sekitar 40 milidetik pada perangkat keras sederhana, angka yang bertambah seiring ukuran keyspace dan beban server.
Lab pada topik ini menjalankan server khusus di port 6381 dengan direktori data di /tmp/lab-scan, tanpa persistensi, dan log diarahkan ke berkas terpisah agar terminal tetap bersih. Keyspace lab diisi 30 key, yaitu 24 key inventory:*, empat key sesi:*, satu set bernama arsip:label, dan satu hash bernama laporan:ringkas. Pada keyspace sekecil ini, KEYS aman dicoba, sedangkan peringatan produksi berlaku untuk dataset yang sesungguhnya.
# hentikan sisa server dari sesi sebelumnya, bila ada
redis-cli -p 6381 shutdown nosave 2>/dev/null || true
# siapkan direktori data server khusus topik ini
mkdir -p /tmp/lab-scan
# nyalakan server khusus di port 6381 tanpa persistensi, log diarahkan ke berkas
redis-server --port 6381 --bind 127.0.0.1 --daemonize yes --dir /tmp/lab-scan --save "" --protected-mode no --logfile /tmp/lab-scan-server.log
# tunggu server siap, lalu pastikan koneksi hidup
sleep 1
redis-cli -p 6381 PINGPONG# isi 24 key inventory dengan nilai string
for i in $(seq 1 24); do redis-cli -p 6381 SET "inventory:item-$i" "komponen-$i" >/dev/null; done
# isi empat key sesi
for i in $(seq 1 4); do redis-cli -p 6381 SET "sesi:aktif-$i" "pengguna-$i" >/dev/null; done
# tambahkan satu set dan satu hash sebagai pembanding tipe data
redis-cli -p 6381 SADD arsip:label gudang-a
redis-cli -p 6381 HSET laporan:ringkas total 24
# hitung seluruh key di keyspace
redis-cli -p 6381 DBSIZE1
1
30# tampilkan seluruh key, keluarannya diurutkan agar mudah dibandingkan
redis-cli -p 6381 KEYS '*' | sortarsip:label
inventory:item-1
inventory:item-10
inventory:item-11
inventory:item-12
inventory:item-13
inventory:item-14
inventory:item-15
inventory:item-16
inventory:item-17
inventory:item-18
inventory:item-19
inventory:item-2
inventory:item-20
inventory:item-21
inventory:item-22
inventory:item-23
inventory:item-24
inventory:item-3
inventory:item-4
inventory:item-5
inventory:item-6
inventory:item-7
inventory:item-8
inventory:item-9
laporan:ringkas
sesi:aktif-1
sesi:aktif-2
sesi:aktif-3
sesi:aktif-4Keluaran memuat 30 key yang telah diurutkan oleh sort. Redis sendiri mengembalikan key menurut tata letak tabel hash internalnya, urutan yang tidak mengikuti urutan penyisipan dan berbeda antar proses server. Seluruh key tampil dalam satu pemanggilan tanpa jeda antar bagian, dan perilaku inilah sumber risikonya pada keyspace besar.
Kontrak SCAN dan iterasi kursor#
Perintah SCAN membagi pemindaian keyspace menjadi banyak pemanggilan kecil yang tidak memblokir server. Setiap pemanggilan menerima nilai kursor, yaitu penanda posisi iterasi, dan mengembalikan sebagian key (batch) beserta kursor untuk pemanggilan berikutnya. Iterasi dimulai dari kursor 0 dan dinyatakan selesai ketika SCAN mengembalikan kursor 0 kembali, sehingga pemanggilannya berbentuk perulangan.
Nilai kursor bersifat buram, artinya klien tidak menafsirkan isinya dan cukup meneruskannya ke pemanggilan SCAN berikutnya. Server tidak menyimpan status iterasi apa pun, sehingga iterasi dapat dilanjutkan kapan pun tanpa sesi khusus di sisi server. Kompleksitas satu pemanggilan tetap, sedangkan iterasi penuh sebanding dengan jumlah key yang dipindai.
Jaminan SCAN bersifat parsial karena statusnya hanya berupa kursor. Selama keyspace tidak berubah dari awal sampai akhir iterasi, iterasi penuh mengumpulkan setiap key yang ada persis satu kali. Apabila data berubah di tengah iterasi, key yang sama dapat dikembalikan lebih dari satu kali, sedangkan key yang baru ditambah atau dihapus dapat ikut dikembalikan atau terlewat. Untuk inventarisasi administratif, perilaku ini dapat diterima, sedangkan kebutuhan snapshot data yang konsisten memerlukan mekanisme lain.
Diagram berikut merangkum alur iterasi kursor dari pemanggilan pertama sampai iterasi dinyatakan selesai.
Iterasi kursor sampai kembali ke nol#
Iterasi kursor dijalankan sebagai perulangan yang berhenti ketika kursor kembali ke 0. Setiap putaran membaca baris pertama keluaran redis-cli sebagai kursor berikutnya dan mengumpulkan baris selebihnya sebagai key. Nilai kursor perantara berbeda antar proses server karena tata letak tabel hash ditetapkan secara acak saat proses dimulai, sehingga blok berikut hanya menampilkan nilai akhir yang tetap.
# kumpulkan seluruh key inventory melalui iterasi kursor
KURSOR=0
HASIL=()
while :; do
BALASAN=$(redis-cli -p 6381 SCAN "$KURSOR" MATCH 'inventory:*' COUNT 5)
KURSOR=$(head -n 1 <<<"$BALASAN")
mapfile -t BARIS < <(tail -n +2 <<<"$BALASAN")
HASIL+=("${BARIS[@]}")
# berhenti ketika kursor kembali ke 0
[ "$KURSOR" = "0" ] && break
done
# tampilkan hasil akhir iterasi penuh
printf 'kursor akhir: %s\n' "$KURSOR"
printf 'key terkumpul: %d\n' "${#HASIL[@]}"kursor akhir: 0
key terkumpul: 24Keluaran menunjukkan 24 dari 30 key, yang berarti pola MATCH 'inventory:*' menyaring empat key sesi:*, set arsip:label, dan hash laporan:ringkas. Nilai kursor akhir: 0 berarti perulangan berakhir karena server mengumumkan iterasi selesai, bukan karena batas jumlah putaran. Jumlah pemanggilan yang diperlukan bergantung pada nilai COUNT dan penyebaran key di dalam tabel hash.
Opsi TYPE membatasi iterasi pada key bertipe tertentu, sedangkan perintah TYPE memeriksa tipe satu key secara langsung. Periksa tipe arsip:label terlebih dahulu, lalu jalankan SCAN dengan TYPE set pada keyspace yang sama. Kombinasi ini memisahkan key berdasarkan tipe datanya tanpa membaca nilai key mana pun.
# periksa tipe data key arsip:label
redis-cli -p 6381 TYPE arsip:label
# pindai key bertipe set dalam satu pemanggilan besar
redis-cli -p 6381 SCAN 0 TYPE set COUNT 100set
0
arsip:labelNilai COUNT 100 melampaui jumlah slot tabel hash pada keyspace kecil ini, sehingga seluruh tabel dipindai dalam satu pemanggilan dan kursor langsung kembali ke 0. Hasilnya hanya berisi arsip:label, sedangkan 29 key bertipe string lainnya tersaring. Pada keyspace produksi, opsi ini membantu inventarisasi per tipe data, misalnya menghitung seluruh key bertipe hash tanpa membaca nilainya satu per satu.
Iterasi SCAN dalam skrip Python#
Klien Redis yang mapan menyediakan pembungkus perulangan sehingga penanganan kursor tidak ditulis manual. Pada redis-py, method scan_iter menjalankan perulangan yang sama dengan blok bash sebelumnya dan mengembalikan key sebagai iterator (iterator) yang dapat diurutkan langsung. Opsi decode_responses=True membuat key datang sebagai string, bukan byte, sehingga penampilannya bersih. Skrip berikut mengumpulkan seluruh key inventory lalu menampilkan tiga key pertama menurut urutan leksikografis, urutan yang menempatkan inventory:item-10 tepat setelah inventory:item-1.
import redis
# kumpulkan seluruh key inventory melalui scan_iter
r = redis.Redis(host="127.0.0.1", port=6381, decode_responses=True)
kunci = sorted(r.scan_iter(match="inventory:*", count=5))
print(f"key terkumpul: {len(kunci)}")
print("tiga key pertama:", ", ".join(kunci[:3]))key terkumpul: 24
tiga key pertama: inventory:item-1, inventory:item-10, inventory:item-11Disiplin pemindaian pada produksi#
SCAN digunakan untuk inventarisasi administratif, yaitu pekerjaan seperti audit key, migrasi data, dan pembersihan bertahap, dan bukan untuk jalur panas (hot path). Jalur panas adalah kode yang dijalankan pada setiap permintaan aplikasi. Pemindaian yang dipicu per permintaan menambah beban server tanpa kebutuhan, sedangkan pencarian key yang teratur diselesaikan melalui desain penamaan key dan struktur data yang tepat. Tabel berikut merangkum perbedaan keduanya.
| Aspek | KEYS | SCAN |
|---|---|---|
| Cara kerja | satu pemanggilan atas seluruh keyspace | iterasi bertahap melalui kursor |
| Dampak server | memblokir thread utama selama pemindaian | setiap pemanggilan singkat dan tidak memblokir |
| Jaminan hasil | snapshot lengkap pada saat eksekusi | cakupan penuh bila keyspace tidak berubah |
| Penggunaan pantas | debugging pada keyspace kecil | inventarisasi administratif pada keyspace besar |
Empat kebiasaan berikut menjaga pemindaian tetap aman pada keyspace produksi.
- Gunakan pola
MATCHyang mengikuti konvensi penamaan key, misalnyainventory:*, sehingga iterasi tidak mengangkut key yang tidak diperlukan. - Pilih nilai
COUNTyang wajar, misalnya 100 sampai 500 pada keyspace besar, untuk menyeimbangkan jumlah pemanggilan dan ukuran setiap batch. - Ulangi pemanggilan sampai kursor
0dan perlakukan kursor sebagai nilai buram yang cukup diteruskan kembali ke server. - Antisipasi key ganda dengan mengumpulkan hasil ke struktur tanpa duplikat di sisi klien sebelum key tersebut diproses.
Percobaan pada topik ini selesai, sehingga server khusus dimatikan tanpa menyimpan data ke disk.
# periksa kembali jumlah key sebelum server dimatikan
redis-cli -p 6381 DBSIZE
# matikan server khusus topik ini tanpa menyimpan data ke disk
redis-cli -p 6381 shutdown nosave30Ringkasan#
KEYSmengembalikan seluruh key dalam satu pemanggilan dan memblokir thread utama server, sehingga tidak layak dijalankan pada keyspace produksi yang besar.SCANmembagi pemindaian menjadi pemanggilan kecil yang tidak memblokir, dengan kursor yang dimulai dan diakhiri pada nilai0.- Opsi
MATCHmenyaring pola,COUNTmenjadi petunjuk besaran kerja per pemanggilan, danTYPEmembatasi hasil pada satu tipe data. - Cakupan penuh hanya terjamin bila keyspace tidak berubah selama iterasi, sehingga
SCANdigunakan untuk inventarisasi administratif dan bukan jalur panas aplikasi.
Referensi#
- SCAN — Redis — Dokumentasi resmi perintah SCAN beserta jaminan iterasi, opsi MATCH, COUNT, dan TYPE.
- KEYS — Redis — Dokumentasi resmi perintah KEYS beserta peringatan penggunaannya pada produksi.
- TYPE — Redis — Dokumentasi resmi perintah TYPE untuk memeriksa tipe data sebuah key.