Caching คือเทคนิคการเก็บข้อมูลที่ถูกเรียกใช้บ่อยไว้ในหน่วยความจำชั่วคราว (Temporary Storage) เพื่อให้เข้าถึงข้อมูลได้เร็วขึ้น โดยไม่ต้องไปดึงจากแหล่งข้อมูลต้นทาง (Database, API, Disk) ทุกครั้ง ลองนึกภาพว่าคุณมีเว็บไซต์ E-commerce ที่แสดงสินค้า 1000 รายการ ถ้าทุกครั้งที่ User เปิดหน้าแรก ต้อง Query Database ใหม่ทุกครั้ง Database จะรับภาระหนักมาก แต่ถ้าเก็บผลลัพธ์ไว้ใน Cache แล้วตอบจาก Cache แทน จะเร็วกว่าเป็นร้อยเท่า
ทำไม Caching จึงสำคัญ? เหตุผลหลักมี 3 ข้อ ข้อแรกคือ Latency ลดลงอย่างมหาศาล การอ่านจาก Memory ใช้เวลาประมาณ 0.1ms ในขณะที่การ Query Database อาจใช้ 5-50ms และการเรียก External API อาจใช้ 100-500ms ข้อที่สองคือ Throughput เพิ่มขึ้น ระบบสามารถรองรับ Request ได้มากขึ้นหลายเท่า เพราะไม่ต้องรอ Database ทุกครั้ง ข้อที่สามคือ Database Load ลดลง Cache ช่วยดูดซับ Traffic ส่วนใหญ่ ทำให้ Database ไม่ต้องทำงานหนักเกินไป ลด Connection Pool ที่ถูกใช้ และลดค่าใช้จ่ายในการ Scale Database
Redis ย่อมาจาก REmote DIctionary Server เป็น Open-source In-Memory Data Structure Store ที่สามารถใช้เป็น Database, Cache และ Message Broker ได้ในตัวเดียว Redis เก็บข้อมูลทั้งหมดไว้ใน RAM (Memory) ทำให้อ่านเขียนข้อมูลได้เร็วมาก รองรับ 100,000+ operations ต่อวินาที บน Hardware ทั่วไป สร้างโดย Salvatore Sanfilippo ในปี 2009 ปัจจุบันเป็นหนึ่งในซอฟต์แวร์ที่ได้รับความนิยมมากที่สุดในโลก ใช้โดยบริษัทระดับโลกเช่น Twitter, GitHub, Pinterest, Snapchat และ Stack Overflow
จุดเด่นของ Redis ที่ทำให้แตกต่างจาก Cache ทั่วไป คือ Redis ไม่ใช่แค่ Key-Value Store ธรรมดา แต่รองรับ Data Structure ที่หลากหลาย ทั้ง String, Hash, List, Set, Sorted Set และ Stream นอกจากนี้ยังรองรับ Persistence ได้ คือสามารถบันทึกข้อมูลลง Disk เพื่อกู้คืนหลัง Restart รองรับ Replication, Clustering, Pub/Sub, Lua Scripting และ Transaction อีกด้วย
# อัพเดต Package List
sudo apt update
# ติดตั้ง Redis Server
sudo apt install redis-server -y
# แก้ไข Config ให้ Redis รันเป็น Service
sudo nano /etc/redis/redis.conf
# แก้ supervised no -> supervised systemd
# เริ่ม Redis Service
sudo systemctl restart redis.service
sudo systemctl enable redis.service
# ทดสอบ
redis-cli ping
# ผลลัพธ์: PONG
# เช็ค Version
redis-server --version
# Redis server v=7.2.x ...
# รัน Redis Container
docker run -d \
--name redis \
-p 6379:6379 \
redis:7-alpine
# รัน Redis พร้อม Password
docker run -d \
--name redis \
-p 6379:6379 \
redis:7-alpine \
redis-server --requirepass mypassword
# เข้า Redis CLI
docker exec -it redis redis-cli
# ถ้ามี Password
docker exec -it redis redis-cli -a mypassword
# Docker Compose สำหรับ Development
# docker-compose.yml
version: '3.8'
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
volumes:
redis_data:
สำหรับ Production แนะนำใช้ Managed Redis เช่น Redis Cloud (redis.com), AWS ElastiCache, GCP Memorystore หรือ Azure Cache for Redis ข้อดีคือไม่ต้องจัดการ Server เอง มี Auto-scaling, Backup, Monitoring ในตัว Redis Cloud มี Free Tier ให้ทดลองใช้ 30 MB เหมาะสำหรับเรียนรู้และโปรเจกต์เล็ก
Redis รองรับ Data Type หลายแบบ แต่ละแบบเหมาะกับ Use Case ที่แตกต่างกัน นี่คือความแตกต่างสำคัญที่ทำให้ Redis เหนือกว่า Memcached ที่รองรับแค่ String
| Data Type | คำอธิบาย | Use Case |
|---|---|---|
| String | ข้อมูลพื้นฐาน เก็บ Text, Number, Binary ได้สูงสุด 512 MB | Cache, Counter, Session Token |
| Hash | Map ของ Field-Value คล้าย Object/Dict | User Profile, Product Info, Settings |
| List | Linked List เรียงลำดับ เพิ่ม/ลบหัวท้ายเร็ว | Timeline, Queue, Recent Activity |
| Set | กลุ่มข้อมูลไม่ซ้ำ ไม่เรียงลำดับ | Tags, Unique Visitors, Followers |
| Sorted Set | Set ที่มี Score เรียงลำดับอัตโนมัติ | Leaderboard, Ranking, Priority Queue |
| Stream | Append-only Log สำหรับ Event Streaming | Activity Log, Event Sourcing, Message Queue |
# SET — เก็บค่า
SET user:name "สมชาย"
# OK
# GET — อ่านค่า
GET user:name
# "สมชาย"
# SET พร้อม Expiration (EX = วินาที)
SET session:abc123 "user_data_json" EX 3600
# หมดอายุใน 1 ชั่วโมง
# SETNX — SET ถ้ายังไม่มี Key (Set if Not eXists)
SETNX lock:order:1001 "processing"
# 1 (สำเร็จ) หรือ 0 (Key มีอยู่แล้ว)
# MSET / MGET — SET/GET หลาย Key พร้อมกัน
MSET name "สมชาย" age "30" city "กรุงเทพ"
MGET name age city
# 1) "สมชาย" 2) "30" 3) "กรุงเทพ"
# INCR / DECR — เพิ่ม/ลดค่า (Atomic)
SET page:views 0
INCR page:views # 1
INCR page:views # 2
INCRBY page:views 10 # 12
# DEL — ลบ Key
DEL user:name
# 1
# EXISTS — เช็คว่า Key มีอยู่ไหม
EXISTS user:name
# 0 (ไม่มี)
# EXPIRE / TTL — ตั้ง/เช็ค เวลาหมดอายุ
SET token:xyz "valid"
EXPIRE token:xyz 300 # หมดอายุใน 5 นาที
TTL token:xyz # 299 (วินาทีที่เหลือ)
# PERSIST — ยกเลิกเวลาหมดอายุ
PERSIST token:xyz
TTL token:xyz # -1 (ไม่มีเวลาหมดอายุ)
# HSET — เก็บข้อมูลแบบ Hash (คล้าย Object)
HSET user:1001 name "สมชาย" email "somchai@email.com" age 30 role "admin"
# HGET — อ่าน Field เดียว
HGET user:1001 name
# "สมชาย"
# HGETALL — อ่านทุก Field
HGETALL user:1001
# 1) "name" 2) "สมชาย"
# 3) "email" 4) "somchai@email.com"
# 5) "age" 6) "30"
# 7) "role" 8) "admin"
# HMGET — อ่านหลาย Field
HMGET user:1001 name email
# 1) "สมชาย" 2) "somchai@email.com"
# HDEL — ลบ Field
HDEL user:1001 role
# HINCRBY — เพิ่มค่าตัวเลขใน Field
HINCRBY user:1001 age 1 # 31
# LPUSH — เพิ่มข้อมูลที่หัว List
LPUSH notifications:user1 "มีออเดอร์ใหม่"
LPUSH notifications:user1 "สินค้าถูกจัดส่งแล้ว"
# RPUSH — เพิ่มข้อมูลที่ท้าย List
RPUSH queue:emails "email1@test.com"
RPUSH queue:emails "email2@test.com"
# LRANGE — ดูข้อมูลใน List (0 = ตัวแรก, -1 = ตัวสุดท้าย)
LRANGE notifications:user1 0 -1
# 1) "สินค้าถูกจัดส่งแล้ว"
# 2) "มีออเดอร์ใหม่"
# LPOP / RPOP — ดึงข้อมูลออกจากหัว/ท้าย
LPOP queue:emails
# "email1@test.com"
# LLEN — นับจำนวนสมาชิก
LLEN notifications:user1
# 2
# SADD — เพิ่มสมาชิกใน Set (ไม่ซ้ำ)
SADD tags:article:1 "redis" "caching" "database" "nosql"
# SMEMBERS — ดูสมาชิกทั้งหมด
SMEMBERS tags:article:1
# "redis" "caching" "database" "nosql"
# SISMEMBER — เช็คว่าเป็นสมาชิกไหม
SISMEMBER tags:article:1 "redis"
# 1 (ใช่)
# SINTER — หา Intersection ของ 2 Set
SADD user:1:skills "python" "redis" "docker"
SADD user:2:skills "redis" "docker" "kubernetes"
SINTER user:1:skills user:2:skills
# "redis" "docker"
# ZADD — เพิ่มสมาชิกใน Sorted Set พร้อม Score
ZADD leaderboard 1500 "player_a"
ZADD leaderboard 2300 "player_b"
ZADD leaderboard 1800 "player_c"
# ZRANGE — ดูสมาชิกเรียงตาม Score (ต่ำ -> สูง)
ZRANGE leaderboard 0 -1 WITHSCORES
# 1) "player_a" 2) "1500"
# 3) "player_c" 4) "1800"
# 5) "player_b" 6) "2300"
# ZREVRANGE — เรียงจากสูงไปต่ำ (อันดับ 1 ก่อน)
ZREVRANGE leaderboard 0 2 WITHSCORES
# ZRANK — หาอันดับ
ZRANK leaderboard "player_b"
# 2 (อันดับ 3 นับจาก 0)
การใช้ Cache ไม่ใช่แค่ "เก็บ-ดึง" แต่มี Pattern หลายแบบที่เหมาะกับสถานการณ์ต่างกัน การเลือก Pattern ที่ถูกต้องจะส่งผลต่อ Performance, Consistency และ Reliability ของระบบ
Application จัดการ Cache เอง ถ้าไม่มีใน Cache ก็ไปดึงจาก Database แล้วเขียนลง Cache เป็น Pattern ที่ง่ายที่สุดและใช้กันมากที่สุด
import redis
import json
r = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
def get_user(user_id):
# 1. ลองอ่านจาก Cache ก่อน
cache_key = f"user:{user_id}"
cached = r.get(cache_key)
if cached:
print("Cache HIT")
return json.loads(cached)
# 2. Cache MISS — ไปดึงจาก Database
print("Cache MISS — querying DB")
user = db.query(f"SELECT * FROM users WHERE id = {user_id}")
# 3. เขียนลง Cache พร้อม TTL
r.setex(cache_key, 3600, json.dumps(user)) # หมดอายุ 1 ชม.
return user
def update_user(user_id, data):
# อัพเดต Database
db.update("users", user_id, data)
# ลบ Cache (Invalidate)
r.delete(f"user:{user_id}")
ทุกครั้งที่เขียนข้อมูล จะเขียนลงทั้ง Cache และ Database พร้อมกัน ข้อดีคือ Cache จะมีข้อมูลล่าสุดเสมอ ข้อเสียคือ Write ช้าลงเพราะต้องเขียน 2 ที่
def save_product(product_id, data):
cache_key = f"product:{product_id}"
# เขียน Database ก่อน
db.save("products", product_id, data)
# เขียน Cache ทันที
r.setex(cache_key, 7200, json.dumps(data))
return data
เขียนข้อมูลลง Cache ก่อน แล้ว Async เขียนลง Database ทีหลัง ข้อดีคือ Write เร็วมากเพราะเขียนแค่ Cache ข้อเสียคือถ้า Cache ล่มก่อน Sync ข้อมูลจะหาย เหมาะกับข้อมูลที่ยอมเสียได้ เช่น Analytics, Page Views
import threading
def save_analytics(event_key, data):
# 1. เขียน Cache ทันที (เร็ว)
r.lpush(f"analytics:buffer", json.dumps(data))
return True
# Background Worker — sync ลง Database ทุก 30 วินาที
def sync_to_db():
while True:
batch = []
while r.llen("analytics:buffer") > 0:
item = r.rpop("analytics:buffer")
if item:
batch.append(json.loads(item))
if batch:
db.bulk_insert("analytics", batch)
print(f"Synced {len(batch)} records to DB")
time.sleep(30)
คล้าย Cache-Aside แต่ Cache จะจัดการดึงข้อมูลจาก Database เองเมื่อ Cache Miss โดย Application ไม่ต้องเขียน Logic เอง ส่วนใหญ่ใช้กับ Cache Library ที่รองรับ เช่น Spring Cache, Django Cache Framework
"There are only two hard things in Computer Science: cache invalidation and naming things." — Phil Karlton การจัดการ Cache ให้ข้อมูลเป็นปัจจุบันเป็นเรื่องยากที่สุดอย่างหนึ่งใน Software Engineering
# กำหนดเวลาหมดอายุ
r.setex("product:list", 300, json.dumps(products)) # 5 นาที
# ข้อดี: ง่าย ไม่ต้อง Track การเปลี่ยนแปลง
# ข้อเสีย: ข้อมูลอาจ Stale ช่วง TTL ยังไม่หมด
# แนวทางกำหนด TTL:
# - ข้อมูลเปลี่ยนบ่อย (Stock Price): 5-30 วินาที
# - ข้อมูลเปลี่ยนปานกลาง (Product List): 5-15 นาที
# - ข้อมูลเปลี่ยนน้อย (Category, Config): 1-24 ชั่วโมง
# - ข้อมูลไม่ค่อยเปลี่ยน (Country List): 24+ ชั่วโมง
# เมื่อสินค้าถูกแก้ไข ลบ Cache ที่เกี่ยวข้องทั้งหมด
def on_product_updated(product_id):
# ลบ Cache ของสินค้าตัวนี้
r.delete(f"product:{product_id}")
# ลบ Cache รายการสินค้า
r.delete("product:list")
# ลบ Cache หมวดหมู่ที่เกี่ยวข้อง
category = get_product_category(product_id)
r.delete(f"category:{category}:products")
# ใช้ Version Number ใน Cache Key
version = r.incr("product:list:version")
cache_key = f"product:list:v{version}"
r.setex(cache_key, 3600, json.dumps(products))
# เมื่อต้องการ Invalidate ก็แค่เพิ่ม Version
r.incr("product:list:version")
# Key เก่าจะหมดอายุตาม TTL เอง ไม่ต้องลบ
ปัญหาของ Session ที่เก็บใน Memory ของ Application Server คือเมื่อ Scale เป็นหลาย Server ผู้ใช้อาจถูกส่งไปคนละ Server ทำให้ Session หาย Redis แก้ปัญหานี้เป็น Centralized Session Store ที่ทุก Server เข้าถึงร่วมกันได้
// npm install express express-session connect-redis redis
const express = require('express');
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
const redisClient = createClient({ url: 'redis://localhost:6379' });
redisClient.connect();
const app = express();
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
cookie: {
secure: false, // true ใน Production (HTTPS)
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 // 1 วัน
}
}));
app.get('/login', (req, res) => {
req.session.user = { id: 1, name: 'สมชาย', role: 'admin' };
res.json({ message: 'Logged in', session: req.session.user });
});
app.get('/profile', (req, res) => {
if (!req.session.user) return res.status(401).json({ error: 'Not logged in' });
res.json(req.session.user);
});
app.listen(3000);
# pip install flask flask-session redis
from flask import Flask, session
from flask_session import Session
import redis
app = Flask(__name__)
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.Redis(host='localhost', port=6379)
app.config['SESSION_PERMANENT'] = True
app.config['PERMANENT_SESSION_LIFETIME'] = 86400 # 1 วัน
Session(app)
@app.route('/login')
def login():
session['user'] = {'id': 1, 'name': 'สมชาย', 'role': 'admin'}
return {'message': 'Logged in'}
@app.route('/profile')
def profile():
user = session.get('user')
if not user:
return {'error': 'Not logged in'}, 401
return user
# pip install django-redis
# settings.py
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://localhost:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
Redis สามารถใช้เป็น Message Queue ได้โดยไม่ต้องติดตั้ง RabbitMQ หรือ Kafka แยก เหมาะกับระบบขนาดเล็กถึงกลาง หรือต้องการ Queue แบบง่ายๆ รวดเร็ว
# Publisher (ส่งข้อความ)
import redis
r = redis.Redis()
# ส่ง Message ไปยัง Channel
r.publish('notifications', 'ออเดอร์ใหม่ #1001')
r.publish('notifications', 'สินค้าหมด SKU-2345')
# Subscriber (รับข้อความ) — รันใน Process แยก
import redis
r = redis.Redis()
pubsub = r.pubsub()
pubsub.subscribe('notifications')
for message in pubsub.listen():
if message['type'] == 'message':
print(f"ได้รับ: {message['data'].decode()}")
# ได้รับ: ออเดอร์ใหม่ #1001
# ได้รับ: สินค้าหมด SKU-2345
# Producer — เพิ่ม Message ลง Stream
XADD orders * customer_id 1001 product "iPhone 16" quantity 1 total 45900
# Consumer — อ่าน Message จาก Stream
XREAD COUNT 10 STREAMS orders 0
# อ่านตั้งแต่ต้น
# Consumer Group — กระจาย Message ให้ Workers หลายตัว
XGROUP CREATE orders order-processors $ MKSTREAM
XREADGROUP GROUP order-processors worker-1 COUNT 1 STREAMS orders >
# worker-1 ได้ Message ที่ยังไม่มีใครอ่าน
# Acknowledge ว่า Process เสร็จแล้ว
XACK orders order-processors 1234567890-0
// npm install bullmq
// Producer
const { Queue } = require('bullmq');
const emailQueue = new Queue('email', {
connection: { host: 'localhost', port: 6379 }
});
await emailQueue.add('send-welcome', {
to: 'user@email.com',
subject: 'ยินดีต้อนรับ',
template: 'welcome'
}, {
attempts: 3, // retry 3 ครั้ง
backoff: {
type: 'exponential',
delay: 1000 // 1s, 2s, 4s
}
});
// Worker
const { Worker } = require('bullmq');
const worker = new Worker('email', async job => {
console.log(`Sending email to: ${job.data.to}`);
await sendEmail(job.data);
}, {
connection: { host: 'localhost', port: 6379 },
concurrency: 5 // process 5 jobs พร้อมกัน
});
แม้ Redis จะเก็บข้อมูลใน Memory แต่ก็มีกลไกบันทึกข้อมูลลง Disk เพื่อกู้คืนเมื่อ Restart หรือล่ม มี 2 แบบคือ RDB และ AOF ใช้แบบเดียวหรือทั้งสองพร้อมกันก็ได้
| คุณสมบัติ | RDB (Snapshot) | AOF (Append Only File) |
|---|---|---|
| วิธีทำงาน | Snapshot ทั้ง Dataset ณ จุดเวลาหนึ่ง | บันทึกทุก Write Command ต่อท้ายไฟล์ |
| ข้อดี | ไฟล์เล็ก, Restore เร็ว, Performance ดี | ข้อมูลสูญหายน้อยกว่า, อ่านง่าย |
| ข้อเสีย | อาจสูญเสียข้อมูลระหว่าง Snapshot | ไฟล์ใหญ่กว่า, Restore ช้ากว่า |
| ข้อมูลสูญหาย | สูงสุด 5 นาที (default) | สูงสุด 1 วินาที (appendfsync everysec) |
| เหมาะกับ | Backup, Development | Production ที่ต้องการ Durability |
# redis.conf — ตั้งค่า Persistence
# RDB — Snapshot ทุกเงื่อนไข
save 900 1 # 15 นาที ถ้ามีอย่างน้อย 1 key เปลี่ยน
save 300 10 # 5 นาที ถ้ามีอย่างน้อย 10 keys เปลี่ยน
save 60 10000 # 1 นาที ถ้ามีอย่างน้อย 10000 keys เปลี่ยน
# AOF — Append Only File
appendonly yes
appendfsync everysec # sync ทุก 1 วินาที (แนะนำ)
# appendfsync always # sync ทุก write (ปลอดภัยสุด แต่ช้า)
# appendfsync no # ให้ OS จัดการ (เร็วสุด แต่เสี่ยง)
# สำหรับ Production แนะนำเปิดทั้ง RDB + AOF
# Redis จะใช้ AOF ในการ Restore เพราะข้อมูลครบกว่า
Sentinel เป็นระบบ Monitoring และ Automatic Failover สำหรับ Redis ทำหน้าที่ดูแล Master-Replica Topology ถ้า Master ล่ม Sentinel จะ Promote Replica ตัวหนึ่งขึ้นเป็น Master ใหม่อัตโนมัติ
# Architecture: 1 Master + 2 Replicas + 3 Sentinels
# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
# เริ่ม Sentinel
redis-sentinel /etc/redis/sentinel.conf
# เช็คสถานะ
redis-cli -p 26379 SENTINEL masters
redis-cli -p 26379 SENTINEL get-master-addr-by-name mymaster
Redis Cluster แบ่งข้อมูลออกเป็น 16384 Hash Slots กระจายไปหลาย Node แต่ละ Node รับผิดชอบ Slot Range ของตัวเอง ทำให้สามารถเก็บข้อมูลได้มากกว่า Memory ของ Node เดียว และ Scale Horizontally ได้
# สร้าง Redis Cluster (ต้องมีอย่างน้อย 6 Node: 3 Master + 3 Replica)
redis-cli --cluster create \
127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 \
127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 \
--cluster-replicas 1
# เข้าใช้ Cluster Mode
redis-cli -c -p 7001
# เช็ค Cluster Info
redis-cli -p 7001 CLUSTER INFO
redis-cli -p 7001 CLUSTER NODES
# เพิ่ม Node ใหม่
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001
# Reshard — ย้าย Slots
redis-cli --cluster reshard 127.0.0.1:7001
| คุณสมบัติ | Redis | Memcached |
|---|---|---|
| Data Types | String, Hash, List, Set, Sorted Set, Stream, HyperLogLog, Bitmap | String เท่านั้น |
| Persistence | RDB + AOF | ไม่มี (Memory Only) |
| Replication | Master-Replica, Sentinel, Cluster | ไม่มี (ต้องใช้ Client-side) |
| Pub/Sub | รองรับ | ไม่รองรับ |
| Transactions | MULTI/EXEC | CAS (Compare-and-Swap) |
| Scripting | Lua Scripts | ไม่มี |
| Max Value Size | 512 MB | 1 MB (default) |
| Threading | Single-threaded (I/O Threads ใน v6+) | Multi-threaded |
| Memory Efficiency | ดี (มี Memory Optimization) | ดีกว่าสำหรับ Simple Key-Value |
| เหมาะกับ | Complex Data, Session, Queue, Pub/Sub | Simple Caching, Large Scale |
สรุป: ถ้าต้องการแค่ Simple Cache ทั้ง Redis และ Memcached ทำได้ดีเท่ากัน แต่ถ้าต้องการ Feature เพิ่มเติมเช่น Persistence, Pub/Sub, Complex Data Types, Queue หรือ Session Store ให้เลือก Redis เพราะ Memcached ไม่รองรับ ในปี 2026 Redis เป็นตัวเลือกเริ่มต้นสำหรับโปรเจกต์ใหม่เกือบทั้งหมด
# สถานะรวม
redis-cli INFO
# ดูเฉพาะ Section
redis-cli INFO memory
# used_memory: 1234567 (bytes ที่ใช้)
# used_memory_human: 1.18M (อ่านง่าย)
# used_memory_peak: 2345678 (สูงสุดที่เคยใช้)
# maxmemory: 104857600 (limit ที่ตั้ง)
redis-cli INFO stats
# total_connections_received: 1234 (connections ทั้งหมด)
# total_commands_processed: 567890 (commands ทั้งหมด)
# keyspace_hits: 45678 (Cache Hit)
# keyspace_misses: 1234 (Cache Miss)
# คำนวณ Cache Hit Rate
# Hit Rate = keyspace_hits / (keyspace_hits + keyspace_misses) * 100
# ค่าที่ดี: > 90%
redis-cli INFO replication
# role: master
# connected_slaves: 2
# Monitor Commands แบบ Real-time (ระวังใน Production)
redis-cli MONITOR
# ดู Slow Queries
redis-cli SLOWLOG GET 10
# ดูจำนวน Keys
redis-cli DBSIZE
# ดู Memory Usage ของ Key
redis-cli MEMORY USAGE user:1001
RedisInsight เป็น GUI Tool ฟรีจาก Redis Inc. สำหรับ Visualize ข้อมูล, Monitor, Debug และจัดการ Redis ดาวน์โหลดได้ที่ redis.com/redis-enterprise/redis-insight มี Feature หลัก ได้แก่ Browser สำหรับดู Key-Value ทั้งหมด, Profiler สำหรับวิเคราะห์ Command ที่ช้า, CLI ในตัวสำหรับรัน Command, Memory Analysis สำหรับหา Key ที่ใช้ Memory มาก และ Cluster Visualization สำหรับดู Cluster Topology
A: Redis Server ทั่วไปรองรับ 100,000-200,000 operations ต่อวินาทีบน Hardware สมัยใหม่ ใน Cluster Mode สามารถ Scale เป็นล้าน operations ต่อวินาทีได้ ด้วย Pipeline สามารถเพิ่ม Throughput ได้อีก 5-10 เท่า
A: ขึ้นอยู่กับข้อมูล แต่โดยทั่วไป 1 ล้าน Key-Value ขนาดเล็ก ใช้ Memory ประมาณ 70-100 MB ถ้ามี Budget จำกัดเริ่มจาก 256 MB สำหรับ Development และ 1-4 GB สำหรับ Production ขนาดเล็ก
A: Redis เป็น Single-threaded สำหรับ Data Operations (v6+ มี I/O Threads สำหรับ Network) ทุก Command เป็น Atomic อยู่แล้ว ไม่ต้องกังวลเรื่อง Race Condition ในระดับ Command แต่ถ้าต้องการ Atomic หลาย Commands ใช้ MULTI/EXEC หรือ Lua Script
A: ได้ในบางกรณี เช่น Session Store, Leaderboard, Real-time Analytics แต่ไม่แนะนำสำหรับข้อมูลหลักที่ต้องการ ACID Transaction, Complex Query หรือ Relational Data ใช้ Redis เป็น Cache + Queue ร่วมกับ SQL/NoSQL Database เป็นแนวทางที่ดีที่สุด
A: KeyDB เป็น Redis Fork ที่เป็น Multi-threaded ทำให้เร็วกว่าในบางสถานการณ์ Dragonfly เป็น In-Memory Store ที่ Compatible กับ Redis API แต่เขียนใหม่ด้วย C++ และเป็น Multi-threaded ทั้งคู่ใช้ทดแทน Redis ได้แต่ Community และ Ecosystem ยังเล็กกว่า Redis มาก ในปี 2026 Redis ยังคงเป็นตัวเลือกที่ปลอดภัยที่สุด