Bagian 3: Menambahkan Dukungan Pub/Sub
Sumber:https://github.com/kzeiter/build-redis-in-go
Di bagian seri klon Redis ini, kami akan menambahkan dukungan untuk fungsionalitas Pub/Sub (Terbitkan/Berlangganan). Pub/Sub memungkinkan klien untuk berlangganan saluran dan menerima pesan yang dipublikasikan ke saluran tersebut. Fitur ini biasa digunakan pada aplikasi real-time, seperti aplikasi chatting dan update real-time.
Kami akan menerapkan dua perintah baru untuk Pub/Sub:
SUBSCRIBE channel PUBLISH channel message
Perintah SUBSCRIBE
memungkinkan klien untuk berlangganan saluran, sedangkan perintah PUBLISH
memungkinkan klien untuk mempublikasikan pesan ke saluran. Ketika sebuah pesan dipublikasikan ke suatu saluran, semua klien yang berlangganan akan menerima pesan tersebut.
Menerapkan Pub/Sub
Untuk mengimplementasikan Pub/Sub, kita perlu memodifikasi store
struct kita untuk melacak pelanggan setiap saluran. Kita akan menggunakan peta yang kuncinya adalah nama saluran dan nilainya adalah potongan client
struct. Struct client
akan mewakili klien yang berlangganan suatu saluran dan akan berisi referensi ke objek net.Conn
klien, yang akan kita gunakan untuk mengirim pesan ke klien.
type store struct { data map[string]string list map[string][]string sets map[string]map[string]bool subs map[string][]client } func (s *store) subscribe(channel string, conn net.Conn) string { client := client{conn: conn} s.subs[channel] = append(s.subs[channel], client) return "SUBSCRIBED" } func (s *store) publish(channel string, message string) { subs, ok := s.subs[channel] if ok { for _, subscriber := range subs { fmt.Fprintf(subscriber.conn, "+%s\n", message) } } }
Kita juga perlu mendefinisikan client
struct:
type client struct { conn net.Conn }
Saat klien berlangganan suatu saluran, kami akan membuat struct client
baru dan menambahkannya ke daftar pelanggan saluran tersebut. Saat pesan dipublikasikan ke saluran, kami akan menelusuri daftar pelanggan saluran tersebut dan mengirimkan pesan ke masing-masing saluran.
Berikut adalah handleCommand
yang diperbarui dengan fungsi Pub/Sub baru:
func (s *store) handleCommand(command string, args []string) string { switch command { case "SET": // Using Join to save the rest of the received data return s.set(args[0], strings.Join(args[1:], " ")) case "GET": return s.get(args[0]) case "DEL": s.del(args[0]) return "DELETED" case "INCR": return fmt.Sprintf("%v", s.incr(args[0])) case "INCRBY": return fmt.Sprintf("%v", s.incrBy(args[0], args[1])) case "DECR": return fmt.Sprintf("%v", s.decr(args[0])) case "DECRBY": return fmt.Sprintf("%v", s.decrBy(args[0], args[1])) case "LPUSH": return fmt.Sprintf("%v", s.lPush(args[0], args[1])) case "RPUSH": return fmt.Sprintf("%v", s.rPush(args[0], args[1])) case "LPOP": return s.lPop(args[0]) case "RPOP": return s.rPop(args[0]) case "LLEN": return fmt.Sprintf("%v", s.lLen(args[0])) case "LINDEX": index, _ := strconv.Atoi(args[1]) return s.lIndex(args[0], index) case "SADD": return fmt.Sprintf("%v", s.sadd(args[0], args[1])) case "SREM": return fmt.Sprintf("%v", s.srem(args[0], args[1])) case "SMEMBERS": members := s.smembers(args[0]) result := "" for _, member := range members { result += fmt.Sprintf("%v ", member) } return strings.TrimSpace(result) case "SISMEMBER": return fmt.Sprintf("%v", s.sismember(args[0], args[1])) case "SUBSCRIBE": return s.subscribe(args[0], conn) case "PUBLISH": s.publish(args[0], strings.Join(args[1:], " ")) return "PUBLISHED" default: return "ERROR" } }
Kami telah menambahkan dua kasus baru ke pernyataan switch dalam metode handleCommand
untuk menangani perintah SUBSCRIBE
dan PUBLISH
. Kami juga telah menambahkan metode subscribe
dan publish
untuk masing-masing menangani langganan saluran dan penerbitan pesan ke saluran.
Dalam metode subscribe
, kita membuat struct client
baru dengan objek net.Conn
klien dan menambahkannya ke daftar pelanggan untuk saluran yang ditentukan.
Dalam metode publish
, pertama-tama kita periksa apakah ada pelanggan untuk saluran yang ditentukan. Jika ada, kami mengulangi daftar pelanggan dan mengirim pesan ke masing-masing pelanggan menggunakan objek net.Conn
klien.
Kesimpulan
Di bagian seri kloning Redis ini, kami telah menambahkan dukungan untuk fungsi Pub/Sub. Kami telah menerapkan perintah SUBSCRIBE
dan PUBLISH
dan memperbarui struct store
kami untuk menyertakan peta subs
, yang menyimpan daftar pelanggan untuk setiap saluran.
Pub/Sub adalah pola perpesanan canggih yang memungkinkan penerbit mengirim pesan ke banyak pelanggan tanpa mengetahui apa pun tentangnya. Hal ini menjadikannya ideal untuk membangun aplikasi real-time, seperti ruang obrolan atau game online.
Di bagian selanjutnya dari seri kloning Redis, kami akan menambahkan dukungan untuk persistensi dengan mengimplementasikan sistem penyimpanan berbasis disk yang sederhana. Pantau terus!
Sumber:
"https://github.com/kzeiter/build-redis-in-go"
Bagian 1: Membangun Penyimpanan Nilai-Kunci Dasar:
https://khalidzeiter.medium.com/building-a-simple-redis-clone-in-golang-part-1 -7f816f2f61bd
Bagian 2: Menambahkan Dukungan untuk Angka, Daftar, dan Kumpulan:
https://khalidzeiter.medium.com/building-a-simple-redis-clone-in-golang-part -2-9130c0c3ef22
Bagian 4: Menambahkan Persistensi dengan Penyimpanan Disk:
https://khalidzeiter.medium.com/building-a-simple-redis-clone-in-golang-part-4-bf4ff349dad3
Kesimpulan dan Langkah Selanjutnya:
https://khalidzeiter.medium.com/building-a-simple-redis-clone-in-golang-conclusion-and-next-steps-128b0503a55b