12/04/2026 18:16น.

EP.113 การสร้างระบบ Chat Multi-room ขั้นสูง (Advanced Multi-room Chat System)
#Golang The Series
#redis pubsub
#Multi-room Chat
#WebSocket
#Go
ในระบบแชทแบบเรียลไทม์ทั่วไป ผู้ใช้มักสามารถพูดคุยกันได้ใน "ห้องเดียว" เท่านั้น แต่เมื่อระบบเติบโต เช่น การสนทนาในทีม, ห้อง Support, ห้องเล่นเกม หรือกลุ่มลูกค้า เราต้องออกแบบให้ระบบรองรับ “หลายห้อง (Multi-room)” พร้อมการควบคุมแยกกันชัดเจน
EP นี้จะพาคุณเรียนรู้การสร้างระบบแชทที่รองรับหลายห้อง พร้อมฟีเจอร์ระดับ production เช่น:
- การกระจายข้อความ (Broadcast)
- การจัดการสมาชิกในแต่ละห้อง
- การสื่อสารข้ามเครื่อง (multi-instance) ด้วย Redis Pub/Sub
🧩 โครงสร้างระบบ Chat หลายห้อง
Client → WebSocket Gateway → Redis Pub/Sub → Chat Rooms
องค์ประกอบหลัก:
- Room Manager: จัดการห้องทั้งหมด (สร้าง, ลบ, ตรวจสอบสมาชิก)
- Connection Manager: จัดการการเชื่อมต่อของผู้ใช้ในแต่ละห้อง
- Redis Pub/Sub: ใช้กระจายข้อความข้าม instance
⚙️ โครงสร้างข้อมูลพื้นฐาน
type Client struct {
ID string
Conn *websocket.Conn
RoomID string
}
type Room struct {
ID string
Clients map[*Client]bool
}
สร้างตัวจัดการห้อง:
type RoomManager struct {
Rooms map[string]*Room
mu sync.Mutex
}
func NewRoomManager() *RoomManager {
return &RoomManager{
Rooms: make(map[string]*Room),
}
}
💡 ฟังก์ชันจัดการห้องและสมาชิก
func (rm *RoomManager) JoinRoom(roomID string, client *Client) {
rm.mu.Lock()
defer rm.mu.Unlock()
room, ok := rm.Rooms[roomID]
if !ok {
room = &Room{ID: roomID, Clients: make(map[*Client]bool)}
rm.Rooms[roomID] = room
}
room.Clients[client] = true
client.RoomID = roomID
}
func (rm *RoomManager) LeaveRoom(roomID string, client *Client) {
rm.mu.Lock()
defer rm.mu.Unlock()
if room, ok := rm.Rooms[roomID]; ok {
delete(room.Clients, client)
if len(room.Clients) == 0 {
delete(rm.Rooms, roomID)
}
}
}
✅ หากผู้ใช้เข้าห้อง ระบบจะตรวจสอบห้องนั้น — หากยังไม่มีจะสร้างให้ทันที
📡 การ Broadcast ข้อความภายในห้อง
func (rm *RoomManager) Broadcast(roomID string, msg string) {
rm.mu.Lock()
defer rm.mu.Unlock()
if room, ok := rm.Rooms[roomID]; ok {
for c := range room.Clients {
c.Conn.WriteMessage(websocket.TextMessage, []byte(msg))
}
}
}
✅ ผู้ใช้ทุกคนในห้องจะได้รับข้อความพร้อมกันแบบเรียลไทม์
🔄 การขยายระบบด้วย Redis Pub/Sub
หากระบบมีหลาย instance การ broadcast ต้องใช้ Redis Pub/Sub:
func subscribeRedis(rm *RoomManager, rdb *redis.Client) {
sub := rdb.Subscribe(context.Background(), "chat_channel")
for msg := range sub.Channel() {
var data struct {
RoomID string `json:"room_id"`
Message string `json:"message"`
}
json.Unmarshal([]byte(msg.Payload), &data)
rm.Broadcast(data.RoomID, data.Message)
}
}
func publishMessage(rdb *redis.Client, roomID, msg string) {
data, _ := json.Marshal(map[string]string{
"room_id": roomID,
"message": msg,
})
rdb.Publish(context.Background(), "chat_channel", data)
}
✅ ไม่ว่า client จะเชื่อมกับเครื่องไหน ข้อความก็ถึงทุกคนทันที!
🧠 เทคนิคเพิ่มประสิทธิภาพ
| หมวด | แนวทาง |
|---|---|
| Scalability | ใช้ Redis หรือ NATS สำหรับกระจายข้อความ |
| Room Type | แยกประเภทห้อง เช่น global, private, team |
| User Management | เก็บข้อมูลผู้ใช้ต่อห้องใน Redis hash |
| Persistence | เก็บ message ลงฐานข้อมูลเพื่อดูย้อนหลัง |
| Monitoring | ติดตาม metric เช่น จำนวน connection ต่อห้อง |
🚀 ท้าให้ลอง!
ลองสร้างระบบ Chat หลายห้องด้วย Go + WebSocket ต่อ Redis เพื่อรองรับการทำงานแบบกระจาย (Distributed System)
ถ้าคุณทำได้ นี่คือโครงสร้างระดับ Enterprise Chat ที่ใช้ได้จริงใน Production ✅
🌟 Next EP: EP.114 การจัดการ Multi-device & Multi-session
ใน EP.114 เราจะเข้าสู่โลกของการออนไลน์พร้อมกันหลายอุปกรณ์ของผู้ใช้เดียวกัน เรียนรู้การออกแบบ Session, ป้องกันซ้ำซ้อน, และรองรับ Mobile/Desktop ได้พร้อมกัน แบบเสถียร ปลอดภัย และใช้ได้จริงบน WebSocket! 📱💻