ข้ามไปยังเนื้อหา

การ Subscribe ด้วย Pattern

PSUBSCRIBE ทำงานเหมือน SUBSCRIBE แต่รับ glob pattern แทนชื่อช่องที่ระบุตายตัว การเรียก PSUBSCRIBE ครั้งเดียวจึงสามารถจับคู่กับช่องได้หลายสิบช่องพร้อมกันโดยไม่ต้องระบุทีละชื่อ

wildcard แบบ glob ที่ Redis รองรับมีสามแบบ:

Patternความหมาย
*จับคู่กับอักขระใดก็ได้ (รวมถึงไม่มีเลย)
?จับคู่กับอักขระหนึ่งตัวอักษรเท่านั้น
[abc]จับคู่กับอักขระหนึ่งตัวจากกลุ่มที่กำหนด — เช่น [abc] จับคู่กับ a, b, หรือ c

ตัวอย่างเช่น news.* จับคู่กับ news.sports, news.tech, news.finance และช่องอื่น ๆ ที่ขึ้นต้นด้วย news.

การโต้ตอบด้านล่างใช้สอง terminal Terminal 1 subscribe ด้วย pattern ส่วน Terminal 2 publish ไปยังหลายช่อง

-- Terminal 1 --
127.0.0.1:6379> PSUBSCRIBE news.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "news.*"
3) (integer) 1
-- Terminal 2 --
127.0.0.1:6379> PUBLISH news.sports "score update"
(integer) 1
127.0.0.1:6379> PUBLISH news.tech "new release"
(integer) 1
-- Terminal 1 receives --
1) "pmessage"
2) "news.*"
3) "news.sports"
4) "score update"
1) "pmessage"
2) "news.*"
3) "news.tech"
4) "new release"

สังเกตรูปแบบการตอบกลับ: pmessage ส่งกลับมาสี่ส่วน — ประเภทของ event, pattern ที่จับคู่ได้, ช่องจริงที่รับข้อมูล, และ payload ซึ่งต่างจากการตอบกลับแบบ message ธรรมดาที่มีเพียงสามส่วน

PUBLISH news.sports "score update"
PUBLISH news.tech "new release"
PUBLISH weather.today "sunny"

PUNSUBSCRIBE pattern ยกเลิกการ subscribe แบบ pattern การเรียกโดยไม่ระบุ argument จะยกเลิก pattern ทั้งหมดที่ active อยู่

127.0.0.1:6379> PUNSUBSCRIBE news.*
1) "punsubscribe"
2) "news.*"
3) (integer) 0

element ที่สามคือจำนวน pattern subscription ที่เหลืออยู่ เมื่อค่าถึง 0 client จะออกจากโหมด pattern-subscribe และสามารถออกคำสั่งปกติได้อีกครั้ง

Redis ใช้กลไก Pub/Sub ภายในเพื่อส่ง event เกี่ยวกับกิจกรรมใน keyspace เมื่อเปิดใช้งาน Redis จะ publish ไปยังช่องพิเศษที่มีอยู่ในตัว เช่น:

  • __keyevent@0__:expired — ทำงานทุกครั้งที่ key ใน database 0 หมดอายุ
  • __keyspace@0__:mykey — ทำงานทุกครั้งที่มีคำสั่งใดก็ตามแตะ mykey

คุณสามารถเปิดใช้งาน notification เหล่านี้ได้ด้วย:

127.0.0.1:6379> CONFIG SET notify-keyspace-events KEA
OK

จากนั้น subscribe ด้วย PSUBSCRIBE __keyevent@0__:* เพื่อรับทุก keyspace event บน database 0 นี่เป็น pattern ขั้นสูงที่มีประโยชน์สำหรับ cache invalidation และ audit logging — เนื้อหาเชิงลึกสมควรอยู่ในบทเรียนของตัวเอง

ตัวเลือกBenefitCost
PSUBSCRIBE ด้วย glob patternsubscribe หลาย channel ด้วยคำสั่งเดียว ไม่ต้องรู้ชื่อ channel ล่วงหน้าทั้งหมดRedis ต้องจับคู่ pattern กับทุกข้อความที่ publish เพิ่ม overhead เมื่อมี pattern จำนวนมาก
Keyspace notifications ผ่าน Pub/Subได้ event แบบ real-time โดยไม่ต้อง pollเพิ่มโหลดให้ Pub/Sub ของ Redis เอง และยังเป็น fire-and-forget เหมือน Pub/Sub ทั่วไป
  • ตั้ง pattern กว้างเกินไปเช่น * — ทำให้ต้องจับคู่ทุกข้อความในระบบกับ pattern นี้ เปลือง CPU โดยไม่จำเป็น ควรจำกัด pattern ให้แคบเท่าที่ใช้งานจริง
  • สับสนระหว่าง message กับ pmessage — client ที่ subscribe ด้วย PSUBSCRIBE ต้อง parse reply แบบสี่ส่วน (มี pattern เพิ่มมา) ถ้าเขียนโค้ด parse แบบเดียวกับ SUBSCRIBE ธรรมดาจะอ่านฟิลด์ผิดตำแหน่ง
  • เปิด keyspace notifications แล้วลืมปิดใน production ที่มี throughput สูงnotify-keyspace-events เพิ่ม CPU overhead ให้ทุกคำสั่งที่แตะ key ควรเปิดเฉพาะ event type ที่ต้องใช้จริง ไม่ใช่ KEA (ทุก event) เสมอไป

💡 ตัวอย่างจากของจริง

ระบบแจ้งเตือนหลายหมวดหมู่ — ใช้ PSUBSCRIBE alerts.* เพื่อรับ alert จากทุกหมวด (alerts.security, alerts.billing, ฯลฯ) ด้วย subscription เดียวแทนที่จะ subscribe ทีละ channel

Cache invalidation ผ่าน keyspace notifications — บริการที่ cache ข้อมูลไว้ในเลเยอร์อื่น subscribe __keyevent@0__:expired เพื่อรู้ทันทีเมื่อ key ต้นทางหมดอายุ แล้วไป invalidate cache ที่เกี่ยวข้อง

glob wildcard ตัวใดจับคู่กับอักขระหนึ่งตัวเท่านั้นใน PSUBSCRIBE pattern?
pmessage reply มีกี่ส่วน?
element ที่สองใน pmessage reply คืออะไร?
คำสั่งใดที่คุณจะใช้รับข้อความจากทั้ง `alerts.low` และ `alerts.high` ด้วย subscription เดียว?