Sorted set menyimpan kumpulan anggota unik yang setiap anggotanya membawa satu skor, dan server menjaga urutan anggota menurut skor tersebut secara permanen. Topik ini membahas penambahan anggota dengan ZADD, pembacaan skor dengan ZSCORE, pembaruan skor dengan ZINCRBY, penghitungan dengan ZCARD dan ZCOUNT, pembacaan rentang dengan ZRANGE beserta opsi REV dan WITHSCORES, rentang skor dengan ZRANGEBYSCORE, penentuan peringkat dengan ZRANK dan ZREVRANK, serta pengambilan nilai ekstrem dengan ZPOPMAX dan ZPOPMIN. Studi kasusnya adalah papan peringkat (leaderboard) untuk kuis matematika sebuah kelas yang berisi empat peserta bernama Ali, Budi, Citra, dan Dewi.
Anggota, skor, dan penambahan dengan ZADD#
Sorted set mewarisi keunikan anggota dari set, tetapi setiap anggota diberi satu skor berupa bilangan pecahan presisi ganda (double), dan urutan keanggotaan dijaga menurut skor dari terendah ke tertinggi. ZADD menambahkan anggota beserta skornya, baik satu pasangan skor dan anggota maupun beberapa pasangan sekaligus dalam satu perintah. Balasan ZADD adalah jumlah anggota yang benar-benar baru, sehingga penulisan ulang anggota lama hanya mengubah skornya dan mengembalikan 0. ZSCORE membaca skor satu anggota dan mengembalikan nil apabila anggota itu belum ada, sedangkan ZCARD menghitung jumlah seluruh anggota.
# menghapus key lama agar isi selalu mulai dari kosong
redis-cli del papan:kuis >/dev/null
# menambahkan satu anggota beserta skornya
redis-cli zadd papan:kuis 88 Ali
# menambahkan tiga anggota sekaligus
redis-cli zadd papan:kuis 92 Budi 75 Citra 85 Dewi
# membaca skor Citra
redis-cli zscore papan:kuis Citra
# membaca skor anggota yang belum ada
redis-cli zscore papan:kuis Eka
# menghitung jumlah anggota papan
redis-cli zcard papan:kuis1
3
75
4Balasan 1 dari perintah pertama berarti Ali benar-benar anggota baru, sedangkan balasan 3 berarti tiga pasangan berikutnya seluruhnya baru. Skor Citra terbaca 75, dan ZSCORE untuk Eka mengembalikan nil karena anggota itu belum ditambahkan. redis-cli interaktif menampilkan balasan nil sebagai (nil), sedangkan keluaran pada topik ini diambil dari redis-cli yang dipanggil tanpa sesi interaktif sehingga nil hanya menyisakan satu baris kosong.
Membaca papan dengan ZRANGE#
ZRANGE mengembalikan anggota pada rentang indeks posisi, dan tanpa opsi tambahan urutannya menaik dari skor terendah ke tertinggi. Indeks 0 dan -1 memilih seluruh anggota, sama seperti indeks negatif pada list. Opsi WITHSCORES menyisipkan skor setelah setiap anggota pada keluaran, sehingga satu permintaan sudah memuat nama beserta skornya. Opsi REV membalik urutan menjadi menurun dari skor tertinggi, dan indeks dihitung setelah urutan dibalik, sehingga ZRANGE 0 1 REV mengembalikan dua anggota teratas. Nama lama ZREVRANGE setara dengan ZRANGE REV dan masih berfungsi, tetapi statusnya kini legacy, yaitu perintah lama yang dipertahankan dan telah digantikan oleh bentuk baru.
# menghapus key lama agar keluaran tetap stabil
redis-cli del papan:kuis >/dev/null
# mengisi ulang papan dengan empat peserta dan skor tetap
redis-cli zadd papan:kuis 88 Ali 92 Budi 75 Citra 85 Dewi
# seluruh anggota dalam urutan menaik menurut skor
redis-cli zrange papan:kuis 0 -1
# seluruh anggota beserta skornya
redis-cli zrange papan:kuis 0 -1 withscores
# seluruh anggota dalam urutan menurun
redis-cli zrange papan:kuis 0 -1 rev
# dua anggota dengan skor tertinggi
redis-cli zrange papan:kuis 0 1 rev4
Citra
Dewi
Ali
Budi
Citra
75
Dewi
85
Ali
88
Budi
92
Budi
Ali
Dewi
Citra
Budi
AliUrutan menaik menempatkan Citra dengan skor 75 di awal meskipun Citra ditambahkan ketiga, karena urutan ditentukan skor dan bukan waktu penyisipan. Bagian WITHSCORES mencetak pasangan anggota dan skor bergantian, sedangkan opsi REV membalik barisan sehingga Budi dengan skor 92 menduduki posisi pertama. Dua anggota teratas pada permintaan terakhir adalah Budi dan Ali.
Memperbarui skor dan rentang skor#
ZADD yang menyentuh anggota yang sudah ada menimpa skornya dengan nilai baru dan mengembalikan 0 karena tidak ada anggota bertambah. ZINCRBY menaikkan skor secara relatif terhadap nilai semula, termasuk kenaikan negatif untuk menurunkan skor, dan mengembalikan skor terbarunya. Untuk papan skor yang bertambah poin demi poin, ZINCRBY lebih tepat daripada ZADD karena nilai lama tidak perlu dibaca lebih dahulu.
ZCOUNT menghitung jumlah anggota yang skornya berada pada rentang tertutup, misalnya antara 80 dan 90, sehingga kedua batasnya ikut dihitung. ZRANGEBYSCORE mengembalikan anggota yang skornya berada pada rentang tersebut, dan konstanta +inf dapat digunakan sebagai batas tanpa atas. ZREVRANGE mengembalikan rentang indeks dalam urutan menurun, sehingga ZREVRANGE 0 2 memilih tiga anggota teratas.
# menghapus key lama agar keluaran tetap stabil
redis-cli del papan:kuis >/dev/null
# mengisi ulang papan dengan empat peserta dan skor tetap
redis-cli zadd papan:kuis 88 Ali 92 Budi 75 Citra 85 Dewi
# menimpa skor Citra menjadi 80
redis-cli zadd papan:kuis 80 Citra
# menaikkan skor Ali sebesar tiga poin
redis-cli zincrby papan:kuis 3 Ali
# menghitung anggota dengan skor 80 sampai 90
redis-cli zcount papan:kuis 80 90
# anggota dengan skor 85 ke atas
redis-cli zrangebyscore papan:kuis 85 +inf
# tiga anggota teratas dalam urutan menurun
redis-cli zrevrange papan:kuis 0 24
0
91
2
Dewi
Ali
Budi
Budi
Ali
DewiZADD untuk Citra mengembalikan 0 karena anggota itu sudah ada, dan skornya berubah dari 75 menjadi 80. ZINCRBY mengembalikan 91, yaitu skor Ali semula 88 ditambah tiga poin. ZCOUNT menghitung dua anggota, yaitu Citra dengan 80 dan Dewi dengan 85, karena kedua batas rentangnya ikut dihitung. Rentang skor 85 ke atas mengembalikan Dewi, Ali, dan Budi sesuai urutan menaik, sedangkan ZREVRANGE 0 2 mengembalikan Budi, Ali, dan Dewi sebagai tiga skor terbesar.
Peringkat dengan ZRANK dan ZREVRANK#
ZRANK dan ZREVRANK mengembalikan posisi satu anggota dalam urutan menaik atau menurun, dan posisinya dihitung mulai dari nol. ZREVRANK 0 berarti anggota dengan skor tertinggi, sehingga nomor peringkat yang lazim ditampilkan pada papan adalah nilai ZREVRANK ditambah satu. ZRANK sebaliknya menghitung dari skor terendah dan lebih jarang digunakan pada papan peringkat. ZPOPMAX dan ZPOPMIN mengeluarkan anggota dengan skor tertinggi atau terendah beserta skornya, sekaligus menghapus anggota itu dari sorted set.
# menghapus key lama agar keluaran tetap stabil
redis-cli del papan:kuis >/dev/null
# mengisi ulang papan dengan empat peserta dan skor tetap
redis-cli zadd papan:kuis 88 Ali 92 Budi 75 Citra 85 Dewi
# peringkat menaik untuk Ali
redis-cli zrank papan:kuis Ali
# peringkat menurun untuk Ali
redis-cli zrevrank papan:kuis Ali
# peringkat menurun untuk Citra
redis-cli zrevrank papan:kuis Citra
# mengeluarkan anggota dengan skor tertinggi
redis-cli zpopmax papan:kuis
# mengeluarkan anggota dengan skor terendah
redis-cli zpopmin papan:kuis
# jumlah anggota yang tersisa
redis-cli zcard papan:kuis4
2
1
3
Budi
92
Citra
75
2Ali berada pada posisi ketiga dari bawah sehingga ZRANK mengembalikan 2, sedangkan ZREVRANK mengembalikan 1 karena hanya Budi yang skornya lebih tinggi. Citra mendapat ZREVRANK 3 sehingga nomor peringkat yang tampil di papan adalah 4. ZPOPMAX mengembalikan Budi beserta skor 92 dan menghapusnya, kemudian ZPOPMIN mengembalikan Citra beserta skor 75, sehingga jumlah anggota tersisa dua.
Mengapa sorted set cocok untuk leaderboard#
Urutan pada sorted set dijaga oleh server setiap kali skor ditulis, sehingga pembacaan papan tidak memerlukan penyortiran ulang di sisi aplikasi. Redis menjaga struktur ini dengan tabel hash dan skip list, yaitu daftar bertingkat yang mempercepat pencarian dan pembacaan rentang, sehingga penambahan anggota, pencarian peringkat, dan pembacaan rentang tetap cepat pada kumpulan besar. Pendekatan alternatif menyimpan skor dalam list atau hash dan mengurutkannya setiap kali papan diminta, sehingga pekerjaan penyortiran berulang dan bertambah seiring jumlah anggota. Satu key juga memuat seluruh papan, sehingga peringkat, rentang skor, dan nilai ekstrem dibaca dari satu sumber yang konsisten.
Diagram berikut merangkum keadaan papan:kuis setelah keempat peserta dimasukkan. Barisan anggotanya terurut dari skor tertinggi, dan nomor peringkat di bawah setiap kotak adalah nilai ZREVRANK ditambah satu.
Kesalahan umum#
Kesalahan pertama adalah menganggap ZRANGE mengikuti urutan penyisipan. Sorted set tidak menyimpan urutan masuk, sehingga Citra yang ditambahkan ketiga tetap muncul pertama karena skornya paling rendah. Logika aplikasi yang mencatat urutan tampil sendiri di sisi klien akan bertentangan dengan keluaran Redis.
Kesalahan kedua adalah memberikan skor yang sama kepada beberapa anggota dan mengandalkan urutan tampilnya. Apabila dua anggota berskor sama, Redis mengurutkan keduanya menurut urutan byte nama anggota secara leksikografis, dan bukan menurut waktu penambahan. Contoh pada topik ini sengaja menggunakan skor yang berbeda untuk setiap peserta agar urutan papan tidak ambigu.
Kesalahan ketiga adalah membaca balasan ZREVRANK sebagai nomor peringkat langsung. Balasan tersebut dihitung mulai dari nol, sehingga anggota teratas balasannya 0 dan bukan 1. Nomor peringkat yang lazim tampil pada papan harus dihitung sebagai ZREVRANK ditambah satu di sisi aplikasi.
Ringkasan#
- ZADD menyimpan pasangan anggota dan skor, mengembalikan jumlah anggota yang benar-benar baru, dan menimpa skor anggota yang sudah ada.
- Server menjaga urutan anggota menurut skor, sehingga ZRANGE dengan opsi REV dan WITHSCORES, ZCOUNT, serta ZRANGEBYSCORE membaca papan tanpa penyortiran di sisi aplikasi.
- ZINCRBY mengubah skor secara relatif dan mengembalikan skor terbarunya, sedangkan ZRANK dan ZREVRANK mengembalikan posisi anggota mulai dari nol.
- ZPOPMAX dan ZPOPMIN mengeluarkan anggota dengan skor tertinggi atau terendah beserta skornya, sekaligus menghapusnya dari sorted set.
Referensi#
- Sorted sets — Redis — Dokumentasi tipe data sorted set beserta contoh papan peringkat.
- ZADD — Redis — Semantik penambahan anggota, penimpaan skor, dan balasan ZADD.
- ZRANGE — Redis — Opsi REV, BYSCORE, dan WITHSCORES beserta status legacy ZREVRANGE dan ZRANGEBYSCORE.
- ZINCRBY — Redis — Dokumentasi penambahan skor relatif beserta balasan skor terbaru.
- ZRANK — Redis — Peringkat anggota pada urutan skor menaik beserta cara perhitungannya.