Stream bukan satu-satunya struktur Redis yang menyampaikan pesan, dan pemilihan struktur yang tepat menuntut pemahaman atas perbedaan jaminan yang diberikan masing-masing. Topik ini membandingkan stream dengan pub/sub dan list melalui empat aspek, yaitu persistensi, jaminan pengiriman, dukungan consumer berganda, dan rentang baca. Perbandingan dilanjutkan dengan posisi stream di hadapan Kafka secara konseptual untuk kebutuhan nyata. Setelah membacanya, pemilihan struktur untuk antrean maupun log peristiwa dapat diputuskan berdasarkan jaminan yang dibutuhkan, bukan berdasarkan kebiasaan.
Perbandingan stream, pub/sub, dan list#
Ketiga struktur menyampaikan data dari pengirim kepada penerima, tetapi ketiganya berbeda pada nasib pesan setelah dikirim. List menyimpan pesan sampai diambil, lalu pesan itu hilang dari list pada saat pengambilannya. Pub/sub menyampaikan pesan hanya kepada pelanggan yang aktif pada saat pengiriman dan tidak menyimpan apa pun. Stream menyimpan setiap entri dengan ID tetap sampai dipangkas, sehingga pesan dapat dibaca ulang dan posisi baca setiap pembaca tidak saling mengganggu.
| Aspek | List | Pub/sub | Stream |
|---|---|---|---|
| Persistensi | tersimpan sampai diambil atau dihapus | tidak tersimpan, hanya selama langganan aktif | tersimpan sampai dipangkas dengan XTRIM atau MAXLEN |
| Jaminan pengiriman | pengambilan memusnahkan pesan, tanpa konfirmasi selesai (at-most-once) | tanpa jaminan, pesan terlewat bila tidak ada pelanggan aktif | tetap tercatat sampai di-ack, dapat diserahkan ulang (at-least-once) |
| Consumer berganda | satu pesan hanya untuk satu pengambil | setiap pelanggan aktif menerima salinan | setiap group membaca seluruh stream dengan posisinya sendiri |
| Rentang baca | indeks yang bergeser setiap isi berubah | tidak ada pembacaan ulang | rentang ID yang tetap dan stabil |
Empat aspek pada tabel saling berkaitan. Persistensi dan rentang baca menentukan apakah pesan dapat dibaca ulang setelah diterima, sedangkan jaminan pengiriman menentukan apa yang terjadi ketika penerima gagal. Consumer berganda menentukan bentuk penskalaannya, yaitu pesan dibagi rata kepada beberapa pekerja sebagaimana list dan consumer group, atau disalin kepada seluruh penerima sebagaimana pub/sub. Baris jaminan pengiriman menjadi pembeda yang paling sering menentukan pilihan untuk tugas yang tidak boleh hilang.
List menghabiskan pesan pada saat diambil#
Keluaran RPOP berupa nilai elemen itu sendiri, dan elemen yang sama hilang dari list pada saat yang bersamaan. Proses yang mati setelah pengambilan tetapi sebelum pemrosesan meninggalkan tugas yang sudah tidak dapat diperoleh kembali. List tidak menyimpan catatan siapa mengambil elemen apa, sehingga tidak ada dasar untuk menyerahkan ulang elemen yang nasibnya tidak jelas. Pengambilan yang berhasil dan pemrosesan yang berhasil merupakan dua peristiwa yang berbeda, dan list tidak menyediakan jembatan di antara keduanya. Contoh berikut memperlihatkan perilaku tersebut pada list tugas pencetakan.
# menyiapkan ulang list tugas, keluarannya diabaikan
redis-cli del banding:tugas >/dev/null
# dua tugas masuk ke list
redis-cli lpush banding:tugas cetak-halaman-1 cetak-halaman-2
# tugas diambil satu per satu hingga habis
redis-cli rpop banding:tugas
redis-cli rpop banding:tugas
# sisa isi list setelah dua pengambilan
redis-cli llen banding:tugas2
cetak-halaman-1
cetak-halaman-2
0Kedua tugas berhasil diambil, dan panjang list yang kembali nol menegaskan bahwa tidak ada lagi yang tersimpan. Pembacaan ulang tidak mungkin dilakukan karena elemennya memang sudah tidak ada, bukan karena posisi bacanya keliru. Pola ini memadai untuk pekerjaan yang boleh hilang, tetapi tidak memadai untuk peristiwa yang harus tercatat.
Stream menyimpan pesan untuk pembacaan ulang#
Stream memperlakukan pesan sebagai entri ber-ID yang tersimpan sampai dipangkas, sehingga pembacaan ulang merupakan operasi biasa dan bukan pengecualian. Entri yang sama dapat dibaca pembaca berbeda pada waktu berbeda tanpa saling menggeser, karena posisi baca disimpan oleh masing-masing pembaca atau group, bukan oleh stream-nya. Sifat ini menopang consumer group, karena group dapat melanjutkan baca dari ID terakhirnya setelah mati tanpa kehilangan akses atas entri sebelumnya. Consumer group juga melengkapi sifat ini dengan daftar pending, sehingga pesan yang sudah diserahkan tetap dapat dilacak sampai konfirmasinya masuk. Contoh berikut membaca log perpustakaan yang sama dua kali.
# menyiapkan ulang log perpustakaan, keluarannya diabaikan
redis-cli del banding:log >/dev/null
redis-cli xadd banding:log 1-1 peristiwa peminjaman koleksi k-101
redis-cli xadd banding:log 1-2 peristiwa pengembalian koleksi k-102
# pembacaan pertama
redis-cli xrange banding:log - +
# pembacaan kedua mengembalikan isi yang sama
redis-cli xrange banding:log - +1-1
1-2
1-1
peristiwa
peminjaman
koleksi
k-101
1-2
peristiwa
pengembalian
koleksi
k-102
1-1
peristiwa
peminjaman
koleksi
k-101
1-2
peristiwa
pengembalian
koleksi
k-102Kedua pemanggilan XRANGE mengembalikan entri yang identik karena pembacaan tidak mengubah apa pun. Perilaku ini juga berlaku bagi pembaca baru yang mengikuti log dari awal, tanpa mengganggu pembaca lama yang sedang berjalan di depan. Sifat inilah yang tidak dimiliki list maupun pub/sub, dan yang menjadikan stream pilihan yang tepat ketika pesan tidak boleh hilang.
Posisi stream dibandingkan Kafka#
Kafka dan stream Redis berbagi fondasi yang sama, yaitu log berurutan yang tahan lama, consumer group, dan posisi baca yang dapat dilanjutkan. Perbedaannya menyentuh skala dan kelengkapan ekosistem. Kafka membagi log menjadi partisi yang tersebar di banyak mesin, menyimpannya pada disk dengan retensi panjang, dan mendampinginya dengan ekosistem untuk menghubungkan, mengolah, dan menstandarkan data. Stream Redis hidup dalam memori satu server Redis beserta replikanya, sehingga skalanya terikat pada memori dan satu titik tulis.
Perbandingan yang jujur menempatkan keduanya pada kelas kebutuhan yang berbeda. Untuk laju peristiwa sedang, jendela retensi pendek hingga menengah, dan tumpukan aplikasi yang sudah menggunakan Redis, stream menghindarkan biaya mengoperasikan satu sistem terdistribusi baru. Untuk laju peristiwa tinggi, retensi berhari-hari hingga berbulan-bulan, paralelisme lintas partisi, dan ekosistem pemrosesan yang matang, Kafka tetap pilihan yang lebih sesuai. Tidak ada pengukuran kinerja yang diklaim di sini, karena angkanya bergantung pada perangkat keras dan pola beban masing-masing.
# tidak-dijalankan
# Kafka tidak tersedia pada sandbox ini, perintah hanya menggambarkan bentuk operasinya
kafka-topics.sh --create --topic log-perpustakaan --partitions 3 --replication-factor 1 --bootstrap-server localhost:9092
kafka-console-producer.sh --topic log-perpustakaan --bootstrap-server localhost:9092
kafka-console-consumer.sh --topic log-perpustakaan --from-beginning --bootstrap-server localhost:9092Tiga perintah di atas memperlihatkan bentuk operasi Kafka, yaitu topic dibuat dengan jumlah partisi tertentu, lalu producer dan consumer dijalankan sebagai proses terpisah. Partisi inilah unit penskalaan yang tidak dimiliki stream Redis, karena satu stream seluruhnya berada pada satu key. Sebagai gantinya, stream menawarkan keterpaduan, yaitu log, group, dan struktur data aplikasi lain berjalan pada satu server yang sama.
Ringkasan#
- List memusnahkan pesan pada saat diambil, pub/sub menyampaikan hanya kepada pelanggan aktif tanpa penyimpanan, sedangkan stream menyimpan entri ber-ID sampai dipangkas.
- Jaminan pengiriman menjadi pembeda utama, yaitu stream dengan consumer group menawarkan at-least-once, sedangkan list dan pub/sub tidak menawarkan konfirmasi pemrosesan.
- Kafka unggul pada partisi lintas mesin, retensi panjang berbasis disk, dan ekosistemnya, sedangkan stream menang pada keterpaduan dan kesederhanaan operasi untuk laju peristiwa sedang.
- Pemilihan struktur ditentukan oleh nasib pesan yang dibutuhkan, bukan oleh kebiasaan atau ketersediaan fitur semata.
Referensi#
- Streams — Redis — Dokumentasi tipe data stream beserta pola consumer group dan pemangkasannya.
- Pub/Sub — Redis — Dokumentasi pola pub/sub beserta sifat pengirimannya yang tanpa penyimpanan.
- List — Redis — Dokumentasi tipe data list beserta operasi pada kedua ujungnya.
- Apache Kafka Documentation — Apache — Dokumentasi resmi Kafka beserta konsep partisi, retensi, dan consumer group-nya.