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

Sets

Redis Set คือ collection ของ string ที่ไม่มีลำดับและไม่ซ้ำกัน การเพิ่มสมาชิกที่มีอยู่แล้วไม่มีผล Redis จะไม่สร้าง duplicate ทำให้ Set เหมาะสำหรับการติดตาม tags, หน้าที่เคยเข้าชม, หรือกลุ่มใดก็ตามที่แต่ละค่าควรปรากฏเพียงครั้งเดียว

SADD key member [member ...] เพิ่มสมาชิกหนึ่งตัวหรือมากกว่า คืนจำนวน สมาชิกใหม่ ที่เพิ่มเข้าไป (ไม่นับ duplicate) SREM key member [member ...] ลบสมาชิกและคืนจำนวนที่มีอยู่จริง

127.0.0.1:6379> SADD article:1:tags "redis" "database" "caching"
(integer) 3
127.0.0.1:6379> SADD article:1:tags "redis"
(integer) 0
127.0.0.1:6379> SREM article:1:tags "caching"
(integer) 1
127.0.0.1:6379> SREM article:1:tags "nosql"
(integer) 0
SADD article:1:tags "redis" "database" "caching"
SADD article:1:tags "redis"
SREM article:1:tags "caching"
SREM article:1:tags "nosql"

SMEMBERS key คืนสมาชิกทั้งหมด (ลำดับไม่รับประกัน) SCARD key คืน cardinality (จำนวนสมาชิก) โดยไม่ต้องดึงทั้งหมด

127.0.0.1:6379> SADD user:42:interests "music" "hiking" "redis" "coffee"
(integer) 4
127.0.0.1:6379> SMEMBERS user:42:interests
1) "coffee"
2) "redis"
3) "music"
4) "hiking"
127.0.0.1:6379> SCARD user:42:interests
(integer) 4
SADD user:42:interests "music" "hiking" "redis" "coffee"
SMEMBERS user:42:interests
SCARD user:42:interests

SISMEMBER key member คืน 1 ถ้าสมาชิกมีอยู่, 0 ถ้าไม่มี เป็นการ lookup แบบ O(1) ไม่ว่า Set จะมีขนาดเท่าไร

127.0.0.1:6379> SADD seen:urls "https://redis.io" "https://astro.build"
(integer) 2
127.0.0.1:6379> SISMEMBER seen:urls "https://redis.io"
(integer) 1
127.0.0.1:6379> SISMEMBER seen:urls "https://example.com"
(integer) 0
SADD seen:urls "https://redis.io" "https://astro.build"
SISMEMBER seen:urls "https://redis.io"
SISMEMBER seen:urls "https://example.com"

SRANDMEMBER key [count] คืนสมาชิกแบบสุ่ม โดยไม่ลบออก SPOP key [count] ลบและคืนสมาชิกแบบสุ่ม ทั้งคู่มีประโยชน์สำหรับการ sampling, ของรางวัล, หรือการมอบหมายงาน

127.0.0.1:6379> SADD prize:pool "alpha" "beta" "gamma" "delta" "epsilon"
(integer) 5
127.0.0.1:6379> SRANDMEMBER prize:pool 2
1) "delta"
2) "gamma"
127.0.0.1:6379> SCARD prize:pool
(integer) 5
127.0.0.1:6379> SPOP prize:pool 1
1) "alpha"
127.0.0.1:6379> SCARD prize:pool
(integer) 4
SADD prize:pool "alpha" "beta" "gamma" "delta" "epsilon"
SRANDMEMBER prize:pool 2
SCARD prize:pool
SPOP prize:pool 1
SCARD prize:pool
ตัวเลือกBenefitCost
Set สำหรับ tags/deduplicationรับประกันความไม่ซ้ำโดยไม่ต้องเช็คก่อน insert, SADD ทำหน้าที่เป็น upsert ในตัวไม่มีลำดับ (unordered) ถ้าต้องการลำดับการเพิ่มหรือการเรียงตามค่า ต้องใช้ List หรือ Sorted Set แทน
SISMEMBER สำหรับ membership checklookup แบบ O(1) ไม่ว่า Set จะมีสมาชิกกี่ล้านตัวตอบได้แค่ “มีหรือไม่มี” ไม่คืนข้อมูลอื่นเกี่ยวกับสมาชิกนั้น ต้องเก็บ metadata แยกใน key อื่น
SPOP สำหรับ random samplingสุ่มและลบพร้อมกันแบบ atomic เหมาะกับของรางวัลหรือ job assignmentสมาชิกที่ pop แล้วหายไปถาวร ถ้าต้องการเก็บ history การสุ่มต้อง log แยกเอง
  • เรียก SMEMBERS บน Set ที่มีสมาชิกระดับล้าน — คำสั่งนี้ดึงสมาชิกทั้งหมดกลับมาในครั้งเดียวและ block เซิร์ฟเวอร์ระหว่างทำงาน ควรใช้ SSCAN แทนเพื่อ iterate แบบ cursor-based บน Set ขนาดใหญ่
  • สับสนว่า SADD คืนค่าจำนวนสมาชิกทั้งหมดSADD คืนแค่จำนวนสมาชิก ใหม่ ที่เพิ่มสำเร็จ ไม่ใช่ขนาดของ Set ทั้งหมด ถ้าต้องการขนาด Set ต้องเรียก SCARD แยก
  • ใช้ Set เมื่อจริงๆ ต้องการลำดับ — ถ้า business logic ต้องพึ่งลำดับการเพิ่มสมาชิก (เช่น “รายการล่าสุดก่อน”) Set จะไม่ตอบโจทย์เพราะไม่รับประกันลำดับ ควรใช้ List หรือ Sorted Set (ผูก timestamp เป็นคะแนน) แทน

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

ระบบ tag บทความ/สินค้า — เว็บข่าวและ e-commerce จำนวนมากใช้ Set เก็บ tag ต่อ item เพราะ SADD ป้องกัน tag ซ้ำโดยอัตโนมัติ และ SISMEMBER ตรวจสอบได้เร็วว่า item มี tag ใดบ้าง

การติดตาม URL/event ที่เคยประมวลผลแล้ว — ระบบ deduplication ใช้ Set เก็บ ID ของ event ที่ประมวลผลแล้ว แล้วเช็คด้วย SISMEMBER ก่อนประมวลผลซ้ำ ป้องกัน duplicate processing ใน pipeline แบบ at-least-once delivery

SADD คืนค่าอะไรเมื่อเพิ่มสมาชิกที่มีอยู่แล้ว?
คำสั่งใดตรวจสอบสมาชิกแบบ O(1) โดยไม่ดึงสมาชิกทั้งหมด?
SRANDMEMBER ต่างจาก SPOP อย่างไร?
SCARD คืนค่าอะไร?