Session Store
ทำไมต้องใช้ Redis สำหรับเซสชัน?
หัวข้อที่มีชื่อว่า “ทำไมต้องใช้ Redis สำหรับเซสชัน?”Application server ทำงานแบบ stateless ดังนั้นเซสชันต้องถูกจัดเก็บไว้ที่ใดที่หนึ่งภายนอก Redis เหมาะสมอย่างมาก เพราะทำงานได้รวดเร็ว รองรับ expiration ของ key โดยธรรมชาติ และ hash type ของ Redis สอดรับกับ session object ที่มีหลายฟิลด์ได้เป็นอย่างดี
เก็บเซสชันในรูปแบบ hash
หัวข้อที่มีชื่อว่า “เก็บเซสชันในรูปแบบ hash”เซสชันแต่ละอันถูกจัดเก็บที่ key ชื่อ session:<id> ฟิลด์ต่างๆ เช่น userId, email และ role จะถูกแมปตรงไปยัง hash fields คำสั่ง EXPIRE กำหนด idle timeout และการรีเซ็ต expiry ในทุกคำขอที่ผ่านการยืนยันตัวตนจะสร้าง sliding TTL
ตัวอย่างใน Redis CLI
หัวข้อที่มีชื่อว่า “ตัวอย่างใน Redis CLI”127.0.0.1:6379> HSET session:abc123 userId 42 email "[email protected]" role "admin"(integer) 3127.0.0.1:6379> EXPIRE session:abc123 1800(integer) 1127.0.0.1:6379> HGETALL session:abc1231) "userId"2) "42"3) "email"4) "[email protected]"5) "role"6) "admin"127.0.0.1:6379> HGET session:abc123 role"admin"127.0.0.1:6379> EXPIRE session:abc123 1800(integer) 1127.0.0.1:6379> TTL session:abc123(integer) 1799HSET ที่ระบุ field-value หลายคู่จะสร้างเซสชันใน round trip เดียว HGETALL คืนทุก field และ HGET ดึงเฉพาะ field ที่ต้องการ การเรียก EXPIRE อีกครั้งจะรีเซ็ตการนับถอยหลัง ที่เป็นการสร้าง sliding idle timeout
HSET session:abc123 userId 42 email "[email protected]" role "admin"
EXPIRE session:abc123 1800
HGETALL session:abc123
HGET session:abc123 role
EXPIRE session:abc123 1800
TTL session:abc123Hashes กับ JSON แบบ serialise
หัวข้อที่มีชื่อว่า “Hashes กับ JSON แบบ serialise”การเก็บเซสชันเป็น JSON string เดียวอาจดูน่าสะดวก แต่บังคับให้ต้อง deserialise ทั้ง blob เพียงเพื่ออ่านหรือเปลี่ยนแปลงฟิลด์เดียว เมื่อใช้ hash คำสั่ง HGET ดึงเฉพาะฟิลด์ที่ต้องการ และ HSET อัปเดตเฉพาะฟิลด์ที่เปลี่ยน โดยไม่ต้องรับส่งค่าทั้งหมดของเซสชัน และไม่มีความเสี่ยงที่การเขียนจะทับการอัปเดตพร้อมกันของฟิลด์อื่น
การอัปเดต field เดียว
หัวข้อที่มีชื่อว่า “การอัปเดต field เดียว”127.0.0.1:6379> HSET session:abc123 role "superadmin"(integer) 0127.0.0.1:6379> HGET session:abc123 role"superadmin"HSET คืนค่า 0 เมื่ออัปเดต field ที่มีอยู่แล้ว (ไม่มีการเพิ่ม field ใหม่) เฉพาะ field role เท่านั้นที่ถูกแก้ไข ทุก field อื่นยังคงไม่เปลี่ยนแปลง
HSET session:abc123 role "superadmin"
HGET session:abc123 roleข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Hash ต่อเซสชัน | อ่าน/อัปเดตทีละ field ได้ ไม่ต้อง deserialize ทั้งก้อน | ต้องรู้ชื่อ field ล่วงหน้า schema ไม่บังคับใน Redis เอง |
| JSON string เดียว | เขียนอ่านง่าย เก็บโครงสร้างซับซ้อนได้ | ต้อง deserialize/serialize ทั้ง blob แม้แก้แค่ field เดียว |
Sliding TTL (EXPIRE ทุก request) | เซสชันที่ active ไม่หมดอายุกลางคัน | ต้องเรียก EXPIRE เพิ่มทุก request ซึ่งเพิ่ม round-trip |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ลืมเรียก
EXPIREซ้ำในทุกคำขอ — ถ้าตั้ง TTL แค่ตอน login ครั้งเดียว ผู้ใช้ที่ active อยู่จะถูก logout กลางคันเมื่อ TTL เดิมหมดอายุ - ไม่
DELsession key ตอน logout — ถ้าปล่อยให้หมดอายุเองตาม TTL เท่านั้น session token ที่ถูกขโมยจะยังใช้งานได้จนกว่า TTL จะหมด แม้ผู้ใช้จะกด logout ไปแล้ว - เก็บข้อมูลอ่อนไหว (เช่น password) ไว้ใน session hash — session store ควรเก็บเฉพาะข้อมูลที่จำเป็นสำหรับ authorization ไม่ใช่ credential ดิบ
💡 ตัวอย่างจากของจริง
Express + connect-redis — ใช้ Redis hash เก็บ session ของแอป Node.js แบบเดียวกับบทนี้ พร้อม sliding TTL ต่อ request
Instagram — ใช้ Redis เป็น session store ระดับ production เพื่อรองรับ session lookup ที่รวดเร็วในสเกลผู้ใช้จำนวนมาก