Redis Data Types และ Commands: คู่มือโครงสร้างข้อมูลและคำสั่งครบทุกประเภท

Redis รองรับโครงสร้างข้อมูลหลายประเภทที่ออกแบบมาเพื่อตอบโจทย์การใช้งานที่แตกต่างกัน ตั้งแต่การเก็บค่าง่าย ๆ ด้วย String ไปจนถึงการจัดอันดับด้วย Sorted Set ความเข้าใจโครงสร้างข้อมูลเหล่านี้เป็นกุญแจสำคัญในการใช้ Redis ได้อย่างมีประสิทธิภาพ

บทความนี้จะอธิบายโครงสร้างข้อมูลทุกประเภทของ Redis พร้อมคำสั่งที่ใช้บ่อยและตัวอย่างการใช้งานจริง เหมาะสำหรับทั้งผู้เริ่มต้นและผู้ที่ต้องการทบทวนความรู้เกี่ยวกับ Redis Commands

String

String เป็นโครงสร้างข้อมูลพื้นฐานที่สุดของ Redis สามารถเก็บได้ทั้งข้อความ ตัวเลข และข้อมูล Binary ขนาดสูงสุด 512 MB ต่อ Key เหมาะสำหรับ Caching, Counter, Session Token และค่า Configuration

# SET — กำหนดค่า
SET name "Somchai"
SET counter 100

# GET — อ่านค่า
GET name           # "Somchai"
GET counter        # "100"

# SET พร้อม Options
SET session:abc "data" EX 3600      # หมดอายุใน 3600 วินาที
SET session:xyz "data" PX 60000     # หมดอายุใน 60000 มิลลิวินาที
SET lock:order NX                   # SET เฉพาะเมื่อ Key ยังไม่มี (ใช้ทำ Lock)
SET config:ver "2.0" XX             # SET เฉพาะเมื่อ Key มีอยู่แล้ว

# MSET / MGET — SET/GET หลาย Key พร้อมกัน
MSET key1 "val1" key2 "val2" key3 "val3"
MGET key1 key2 key3

# INCR / DECR — เพิ่ม/ลดค่าตัวเลข
SET visitors 0
INCR visitors          # 1
INCR visitors          # 2
INCRBY visitors 10     # 12
DECR visitors          # 11
DECRBY visitors 5      # 6

# INCRBYFLOAT — เพิ่มค่าทศนิยม
SET price 19.99
INCRBYFLOAT price 0.50    # "20.49"

# APPEND — ต่อข้อความ
SET greeting "Hello"
APPEND greeting " World"   # "Hello World"

# STRLEN — ความยาว
STRLEN greeting            # 11

# GETRANGE / SETRANGE — จัดการ Substring
GETRANGE greeting 0 4      # "Hello"
SETRANGE greeting 6 "Redis" # "Hello Redis"

Hash

Hash เก็บข้อมูลเป็นคู่ Field-Value ภายใน Key เดียว เหมาะสำหรับแทน Object หรือ Record เช่น ข้อมูลผู้ใช้ สินค้า หรือ Configuration ที่มีหลายค่า ประหยัด Memory มากกว่าการใช้ Key แยกสำหรับแต่ละ Field

# HSET — กำหนดค่า Field
HSET user:1001 name "Somchai" email "[email protected]" age 30

# HGET — อ่านค่า Field เดียว
HGET user:1001 name        # "Somchai"

# HMGET — อ่านหลาย Field
HMGET user:1001 name email  # "Somchai" "[email protected]"

# HGETALL — อ่านทุก Field
HGETALL user:1001
# 1) "name"       2) "Somchai"
# 3) "email"      4) "[email protected]"
# 5) "age"        6) "30"

# HDEL — ลบ Field
HDEL user:1001 age

# HEXISTS — ตรวจสอบว่า Field มีอยู่หรือไม่
HEXISTS user:1001 email    # (integer) 1

# HKEYS / HVALS — ดูเฉพาะ Key หรือ Value
HKEYS user:1001            # "name" "email"
HVALS user:1001            # "Somchai" "[email protected]"

# HLEN — จำนวน Field
HLEN user:1001             # (integer) 2

# HINCRBY — เพิ่มค่าตัวเลขใน Field
HSET product:5001 name "Keyboard" price 990 stock 50
HINCRBY product:5001 stock -1    # 49 (ลด Stock)
HINCRBYFLOAT product:5001 price 10.50  # "1000.50"

# HSETNX — SET เฉพาะเมื่อ Field ยังไม่มี
HSETNX user:1001 name "NewName"  # (integer) 0 (ไม่เปลี่ยนเพราะมีอยู่แล้ว)

List

List เก็บข้อมูลเป็นลำดับ (Ordered) โดยสามารถเพิ่มและลบข้อมูลจากทั้งหัวและท้าย ภายในเป็น Doubly Linked List ทำให้การเพิ่ม/ลบที่ปลายทั้งสองฝั่งเร็วมาก เหมาะสำหรับ Queue, Stack, Timeline และ Recent Items

# LPUSH / RPUSH — เพิ่มจากซ้าย/ขวา
RPUSH queue:tasks "task1" "task2" "task3"   # เพิ่มท้ายแถว
LPUSH queue:tasks "task0"                   # เพิ่มหน้าแถว
# ผลลัพธ์: task0, task1, task2, task3

# LPOP / RPOP — ดึงออกจากซ้าย/ขวา
LPOP queue:tasks           # "task0" (FIFO Queue)
RPOP queue:tasks           # "task3" (LIFO Stack)

# LRANGE — ดูข้อมูลตามช่วง
LRANGE queue:tasks 0 -1    # ดูทั้งหมด
LRANGE queue:tasks 0 2     # ดู 3 ตัวแรก

# LLEN — จำนวนสมาชิก
LLEN queue:tasks

# LINDEX — ดูตำแหน่งที่ระบุ
LINDEX queue:tasks 0       # ตัวแรก

# LSET — เปลี่ยนค่าตำแหน่งที่ระบุ
LSET queue:tasks 0 "updated_task"

# LREM — ลบสมาชิกที่ตรงกับค่า
LREM queue:tasks 1 "task2"   # ลบ "task2" จำนวน 1 ตัว

# LTRIM — ตัดให้เหลือตามช่วง (ใช้ทำ Capped List)
RPUSH recent:logs "log1" "log2" "log3" "log4" "log5"
LTRIM recent:logs 0 99    # เก็บแค่ 100 รายการล่าสุด

# BLPOP / BRPOP — Blocking Pop (รอจนกว่าจะมีข้อมูล)
BLPOP queue:tasks 30       # รอสูงสุด 30 วินาที (ใช้ทำ Worker Queue)

# LPOS — หาตำแหน่งของค่า (Redis 6.0.6+)
RPUSH colors "red" "blue" "green" "blue"
LPOS colors "blue"         # (integer) 1

Set

Set เก็บข้อมูลแบบไม่ซ้ำ (Unique) และไม่มีลำดับ รองรับการดำเนินการทางเซต เช่น Union, Intersection และ Difference เหมาะสำหรับเก็บ Tag, ตรวจสอบสมาชิก, นับจำนวนที่ไม่ซ้ำ และหาความสัมพันธ์ระหว่างกลุ่ม

# SADD — เพิ่มสมาชิก
SADD tags:post:101 "redis" "database" "nosql" "cache"

# SMEMBERS — ดูสมาชิกทั้งหมด
SMEMBERS tags:post:101     # "redis" "database" "nosql" "cache"

# SISMEMBER — ตรวจสอบว่าเป็นสมาชิกหรือไม่
SISMEMBER tags:post:101 "redis"    # (integer) 1
SISMEMBER tags:post:101 "python"   # (integer) 0

# SCARD — จำนวนสมาชิก
SCARD tags:post:101        # (integer) 4

# SREM — ลบสมาชิก
SREM tags:post:101 "cache"

# SPOP — สุ่มดึงสมาชิกออก
SPOP tags:post:101         # สุ่ม 1 ตัว

# SRANDMEMBER — สุ่มดูแต่ไม่ลบ
SRANDMEMBER tags:post:101 2    # สุ่ม 2 ตัว

# Set Operations
SADD set:a "1" "2" "3" "4"
SADD set:b "3" "4" "5" "6"

SUNION set:a set:b         # "1" "2" "3" "4" "5" "6" (รวมกัน)
SINTER set:a set:b         # "3" "4" (ที่ซ้ำกัน)
SDIFF set:a set:b          # "1" "2" (อยู่ใน A แต่ไม่อยู่ใน B)

# เก็บผลลัพธ์ใน Key ใหม่
SUNIONSTORE set:union set:a set:b
SINTERSTORE set:common set:a set:b

# ตัวอย่าง: ติดตามผู้ใช้ Online
SADD online:users "user:1001" "user:1002" "user:1003"
SCARD online:users         # 3 คน Online
SREM online:users "user:1002"   # user:1002 ออฟไลน์

Sorted Set (ZSet)

Sorted Set คล้ายกับ Set แต่สมาชิกแต่ละตัวมี Score กำกับ ทำให้เรียงลำดับได้ เหมาะสำหรับ Leaderboard, Ranking, Priority Queue, Time-series Index และ Rate Limiting แบบ Sliding Window

# ZADD — เพิ่มสมาชิกพร้อม Score
ZADD leaderboard 1500 "player:alice" 1200 "player:bob" 1800 "player:charlie"

# ZRANGE — ดูตามลำดับ Score (น้อย → มาก)
ZRANGE leaderboard 0 -1 WITHSCORES
# 1) "player:bob"     2) "1200"
# 3) "player:alice"   4) "1500"
# 5) "player:charlie" 6) "1800"

# ZREVRANGE — ดูตามลำดับ Score (มาก → น้อย)
ZREVRANGE leaderboard 0 2 WITHSCORES    # Top 3

# ZSCORE — ดู Score ของสมาชิก
ZSCORE leaderboard "player:alice"       # "1500"

# ZRANK / ZREVRANK — ดูอันดับ (เริ่มจาก 0)
ZRANK leaderboard "player:alice"        # (integer) 1 (อันดับ 2 จากล่าง)
ZREVRANK leaderboard "player:alice"     # (integer) 1 (อันดับ 2 จากบน)

# ZINCRBY — เพิ่ม Score
ZINCRBY leaderboard 300 "player:bob"    # 1500

# ZRANGEBYSCORE — ดูตามช่วง Score
ZRANGEBYSCORE leaderboard 1000 1500 WITHSCORES

# ZCOUNT — นับสมาชิกตามช่วง Score
ZCOUNT leaderboard 1000 2000            # (integer) 3

# ZREM — ลบสมาชิก
ZREM leaderboard "player:bob"

# ZCARD — จำนวนสมาชิกทั้งหมด
ZCARD leaderboard

# ตัวอย่าง: Rate Limiting แบบ Sliding Window
# นับ Request ของผู้ใช้ใน 60 วินาที
ZADD ratelimit:user:1001 1712345678 "req:1"
ZADD ratelimit:user:1001 1712345679 "req:2"
ZREMRANGEBYSCORE ratelimit:user:1001 0 1712345618   # ลบที่เก่ากว่า 60 วินาที
ZCARD ratelimit:user:1001                            # นับ Request ที่เหลือ

Stream

Stream เป็นโครงสร้างข้อมูลที่เพิ่มเข้ามาตั้งแต่ Redis 5.0 ออกแบบมาสำหรับ Event Sourcing และ Message Queue ข้อมูลถูกเก็บตามลำดับเวลาและรองรับ Consumer Group สำหรับประมวลผลแบบกระจาย

# XADD — เพิ่มข้อมูลเข้า Stream
XADD events * action "login" user "somchai" ip "10.0.1.50"
# ได้ ID เช่น "1712345678901-0"

XADD events * action "purchase" user "somchai" product "keyboard"

# XLEN — จำนวนข้อความใน Stream
XLEN events

# XRANGE — อ่านตามช่วงเวลา
XRANGE events - +              # อ่านทั้งหมด (- = เริ่มต้น, + = ล่าสุด)
XRANGE events - + COUNT 10     # อ่าน 10 รายการแรก

# XREVRANGE — อ่านย้อนกลับ
XREVRANGE events + - COUNT 5   # 5 รายการล่าสุด

# XREAD — อ่านข้อมูลใหม่ (แบบ Blocking ได้)
XREAD COUNT 10 STREAMS events 0              # อ่านจากต้น
XREAD BLOCK 5000 COUNT 1 STREAMS events $    # รอข้อมูลใหม่สูงสุด 5 วินาที

# Consumer Group — ประมวลผลแบบกระจาย
XGROUP CREATE events mygroup 0               # สร้าง Group เริ่มอ่านจากต้น
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS events >   # อ่านข้อความใหม่
XACK events mygroup "1712345678901-0"        # ยืนยันว่าประมวลผลแล้ว

# XTRIM — จำกัดขนาด Stream
XTRIM events MAXLEN 1000       # เก็บแค่ 1000 รายการล่าสุด

Bitmap และ HyperLogLog

Bitmap

Bitmap ใช้ String เก็บข้อมูลแบบ Bit Array เหมาะสำหรับติดตามสถานะ Boolean จำนวนมาก เช่น ผู้ใช้เข้าใช้งานวันไหนบ้างในเดือนนี้ ประหยัด Memory มากเพราะใช้แค่ 1 Bit ต่อ 1 สถานะ

# SETBIT / GETBIT — กำหนด/อ่าน Bit
# ติดตามการเข้าใช้งานรายวัน (วันที่ 1-31)
SETBIT login:user:1001:202604 1 1    # วันที่ 1 เข้าใช้
SETBIT login:user:1001:202604 2 1    # วันที่ 2 เข้าใช้
SETBIT login:user:1001:202604 5 1    # วันที่ 5 เข้าใช้

GETBIT login:user:1001:202604 2      # (integer) 1 (เข้าใช้)
GETBIT login:user:1001:202604 3      # (integer) 0 (ไม่เข้าใช้)

# BITCOUNT — นับจำนวน Bit ที่เป็น 1
BITCOUNT login:user:1001:202604      # (integer) 3 (เข้าใช้ 3 วัน)

# BITOP — ดำเนินการทางตรรกะระหว่าง Bitmap
BITOP AND active:both login:user:1001:202604 login:user:1002:202604
BITOP OR active:any login:user:1001:202604 login:user:1002:202604

HyperLogLog

HyperLogLog ใช้สำหรับนับจำนวนสมาชิกที่ไม่ซ้ำ (Cardinality) โดยประมาณ ใช้ Memory คงที่เพียง 12 KB ไม่ว่าจะมีสมาชิกกี่ล้านตัว แลกกับความคลาดเคลื่อนประมาณ 0.81% เหมาะสำหรับนับ Unique Visitors, Unique IP หรือ Unique Events

# PFADD — เพิ่มสมาชิก
PFADD visitors:20260407 "user:1001" "user:1002" "user:1003"
PFADD visitors:20260407 "user:1001" "user:1004"   # user:1001 ซ้ำ ไม่นับเพิ่ม

# PFCOUNT — นับจำนวนที่ไม่ซ้ำ (โดยประมาณ)
PFCOUNT visitors:20260407    # (integer) 4

# PFMERGE — รวม HyperLogLog
PFADD visitors:20260408 "user:1002" "user:1005"
PFMERGE visitors:week visitors:20260407 visitors:20260408
PFCOUNT visitors:week        # จำนวน Unique ทั้งสัปดาห์

คำสั่งจัดการ Key

นอกจากคำสั่งเฉพาะของแต่ละ Data Type แล้ว Redis มีคำสั่งสำหรับจัดการ Key ทั่วไปที่ใช้ได้กับทุกประเภท

# EXISTS — ตรวจสอบว่า Key มีอยู่
EXISTS user:1001               # (integer) 1

# DEL — ลบ Key (Blocking)
DEL user:1001                  # (integer) 1

# UNLINK — ลบ Key (Non-Blocking, เร็วกว่าสำหรับ Key ขนาดใหญ่)
UNLINK large:dataset

# TYPE — ดูประเภทของ Key
TYPE user:1001                 # "hash"
TYPE queue:tasks               # "list"

# RENAME — เปลี่ยนชื่อ Key
RENAME old:key new:key

# EXPIRE / PEXPIRE — ตั้งเวลาหมดอายุ
EXPIRE session:abc 3600        # หมดอายุใน 3600 วินาที
PEXPIRE session:abc 3600000    # หมดอายุใน 3600000 มิลลิวินาที

# EXPIREAT — ตั้งเวลาหมดอายุแบบ Unix Timestamp
EXPIREAT session:abc 1712345678

# TTL / PTTL — ดูเวลาที่เหลือก่อนหมดอายุ
TTL session:abc                # วินาทีที่เหลือ
PTTL session:abc               # มิลลิวินาทีที่เหลือ

# PERSIST — ยกเลิกเวลาหมดอายุ
PERSIST session:abc

# SCAN — ค้นหา Key แบบ Cursor (ปลอดภัยสำหรับ Production)
SCAN 0 MATCH user:* COUNT 100
# ห้ามใช้ KEYS * ใน Production เพราะจะ Block Redis

# OBJECT — ดูข้อมูลภายในของ Key
OBJECT ENCODING user:1001      # "listpack" หรือ "hashtable"
OBJECT IDLETIME user:1001      # เวลาที่ไม่ได้ถูกเข้าถึง (วินาที)

Transaction และ Pipeline

Transaction (MULTI/EXEC)

Transaction ใน Redis รับประกันว่าคำสั่งทั้งหมดจะถูกรันต่อเนื่องกันโดยไม่มีคำสั่งอื่นแทรก แต่ไม่รองรับ Rollback เหมือนฐานข้อมูลทั่วไป

# เริ่ม Transaction
MULTI
SET account:a 500
SET account:b 300
DECRBY account:a 100
INCRBY account:b 100
EXEC
# คำสั่งทั้งหมดรันพร้อมกันเป็น Atomic

# ยกเลิก Transaction
MULTI
SET key1 "value1"
DISCARD

# WATCH — Optimistic Locking
WATCH account:a
val = GET account:a
MULTI
SET account:a (val - 100)
EXEC
# ถ้า account:a ถูกเปลี่ยนระหว่าง WATCH กับ EXEC จะคืน nil (ล้มเหลว)

Pipeline

Pipeline ส่งหลายคำสั่งไปยัง Redis พร้อมกันโดยไม่ต้องรอผลลัพธ์ทีละคำสั่ง ลด Round-trip Time ได้มาก เหมาะสำหรับงานที่ต้องรันคำสั่งจำนวนมากต่อเนื่อง

# ตัวอย่าง Pipeline ใน Python
import redis

r = redis.Redis()
pipe = r.pipeline()

# ส่งคำสั่งเข้า Pipeline
for i in range(1000):
    pipe.set(f"key:{i}", f"value:{i}")

# รันทั้งหมดพร้อมกัน
results = pipe.execute()

# Pipeline + Transaction
pipe = r.pipeline(transaction=True)
pipe.multi()
pipe.set("a", "1")
pipe.set("b", "2")
pipe.execute()

Pub/Sub

Pub/Sub เป็นระบบส่งข้อความแบบ Publish/Subscribe ผู้ส่งไม่จำเป็นต้องรู้ว่าใครเป็นผู้รับ เหมาะสำหรับการแจ้งเตือนแบบ Real-time, Chat และ Event Broadcasting แต่ข้อความจะหายไปถ้าไม่มีผู้รับในขณะนั้น ถ้าต้องการ Persistence ให้ใช้ Stream แทน

# ผู้รับ (Subscriber) — เปิด Terminal แรก
SUBSCRIBE notifications
SUBSCRIBE channel:chat channel:alerts

# ผู้รับแบบ Pattern
PSUBSCRIBE news:*          # รับทุก Channel ที่ขึ้นต้นด้วย news:

# ผู้ส่ง (Publisher) — เปิด Terminal อื่น
PUBLISH notifications "New order received!"
PUBLISH channel:chat "Hello everyone"
PUBLISH news:tech "Redis 8.0 released"

# ดูจำนวน Subscriber
PUBSUB NUMSUB notifications
PUBSUB CHANNELS             # ดู Channel ที่มี Subscriber

เลือก Data Type ให้เหมาะกับงาน

การเลือกโครงสร้างข้อมูลให้ถูกต้องส่งผลต่อทั้งประสิทธิภาพและการใช้ Memory อย่างมาก แนวทางการเลือกมีดังนี้ ใช้ String สำหรับ Cache ค่าเดี่ยว, Counter หรือ Session Token ใช้ Hash สำหรับเก็บ Object ที่มีหลาย Field เช่น User Profile หรือ Product Detail ใช้ List สำหรับ Queue, Stack หรือ Activity Feed ที่เรียงตามเวลา ใช้ Set สำหรับเก็บค่าที่ไม่ซ้ำ เช่น Tag, Online Users หรือ Permission ใช้ Sorted Set สำหรับ Ranking, Leaderboard หรือ Scheduled Jobs ใช้ Stream สำหรับ Event Log และ Message Queue ที่ต้องการ Persistence ใช้ Bitmap สำหรับติดตามสถานะ Boolean จำนวนมาก และใช้ HyperLogLog สำหรับนับจำนวน Unique โดยประมาณ

สรุป

Redis มีโครงสร้างข้อมูลหลากหลายที่ออกแบบมาเฉพาะทาง ตั้งแต่ String ที่ใช้งานง่ายไปจนถึง Stream สำหรับ Event Processing การเลือกใช้โครงสร้างข้อมูลที่เหมาะสมกับงานจะช่วยให้ได้ทั้งประสิทธิภาพและการใช้ Memory ที่ดี นอกจากนี้ Transaction, Pipeline และ Pub/Sub ยังเป็นเครื่องมือเสริมที่ช่วยให้สามารถใช้ Redis ได้อย่างเต็มศักยภาพ

แนะนำบริการ DE

การใช้งาน Redis ในระดับ Production ต้องการเซิร์ฟเวอร์ที่มี RAM เพียงพอสำหรับเก็บข้อมูลทั้งหมดใน Memory Cloud VPS ของ DE รองรับการเลือกขนาด RAM ได้ตามต้องการ พร้อม SSD NVMe สำหรับ Persistence ที่เร็ว เหมาะสำหรับรัน Redis ทั้ง Cache, Queue และ Data Store

สำหรับผู้ที่ต้องการโฮสต์เว็บแอปพลิเคชันโดยมี Redis เป็น Backend Cloud Hosting ของ DE ช่วยให้เริ่มต้นได้ง่ายโดยไม่ต้องจัดการเซิร์ฟเวอร์เอง