Pengelolaan Slot di Redis Cluster: Mengatasi Masalah CROSS-SLOT

Pengelolaan Slot di Redis Cluster: Mengatasi Masalah CROSS-SLOT

Redis Cluster adalah teknologi distribusi data yang dikembangkan oleh Redis untuk memungkinkan aplikasi menyebar data ke lebih dari satu node. Dalam Redis Cluster, setiap node memiliki slot yang unik dan digunakan untuk menghitung hash slot suatu key. Slot ini penting dalam pengelolaan operasi multi-key, seperti MGET/MSET/DEL/UNLINK.

Pengalaman Awal

Ketika client meminta perintah ke Redis, permintaan tersebut akan di-forward ke node secara acak. Node yang memiliki slot suatu key akan langsung merespon ke client jika perintah tersebut diterima oleh node tersebut. Namun, apabila key tidak ada di node, maka Redis akan melakukan redirection ke node lain yang memiliki slot tersebut.

Masalah CROSS-SLOT

Namun, jika kita mencoba menghapus beberapa key sekaligus menggunakan perintah DEL, maka terjadi masalah CROSS-SLOT. Masalah ini terjadi karena beberapa key tidak memiliki slot yang sama dan Redis tidak dapat langsung merespon ke client.

Menghitung Slot di Redis

Menurut dokumen resmi Redis, slot suatu key dihitung menggunakan algoritma CRC-16 (Cyclic Redundancy Check). Algoritma ini menghasilkan nilai antara 0 dan 16383 yang digunakan sebagai slot untuk setiap key.

Pengelolaan Slot di Aplikasi

Oleh karena itu, kita dapat menghitung slot suatu key secara dini dalam aplikasi dan membuat peta slot-key. Pada saat ini, kita dapat melakukan operasi multi-key dengan membagi keys menjadi beberapa bagian berdasarkan slotnya dan mengirimkan perintah ke node yang memiliki slot tersebut.

Contoh kode TypeScript:

async deleteAll(keys: RedisKey[]) {
 // (1) Grouping keys by slot
 const slotKeysMap = new Map()
 for (const key of keys) {
 // CRC16(key) mod 16384
 const slot = this._redisNodeManager.calculateSlotByKey(key)
 if (!slotKeysMap.has(slot)) slotKeysMap.set(slot, [key])
 else slotKeysMap.get(slot).push(key)
 }
 const batchCommands = []
 for (const [slot, keys] of slotKeysMap) {
 // find master node which has slot
 const targetMasterNode = await this._redisNodeManager.getTargetMasterNodeBySlot(slot)
 batchCommands.push(targetMasterNode.del(keys))
 }
 await Promise.allSettled(batchCommands)
}

Dengan cara ini, kita dapat mengurangi waktu round trip time (RTT) antara client dan Redis-server dengan melakukan operasi multi-key sekaligus. Jumlah perintah yang dapat dilakukan sekitar [1, 16384] yang ditentukan oleh jumlah slot.

Solusi Hashtag

Beberapa artikel atau blog lainnya menawarkan solusi "hash-tag" untuk mengatasi masalah CROSS-SLOT dengan menggunakan tanda hashtag {…} di akhir key. Namun, solusi ini tidak dapat diterapkan pada keys yang sudah ada sebelumnya.

Oleh karena itu, saya telah mengembangkan dan berbagi solusi aplikasi-level untuk mengatasi masalah CROSS-SLOT.

Referensi