ไม่ว่าคุณจะเพิ่งเริ่ม Redis หรือแค่ต้องการรีเฟรชฟีเจอร์ที่มีอยู่ คู่มือนี้ช่วยให้คุณเข้าใจโครงสร้างข้อมูลทั้งหมดที่ Redis ให้มา
เลือกโครงสร้างที่เหมาะสม
โครงสร้างข้อมูลของ Redis เรียบง่าย — ไหนก็ตามไม่ค่อยจะเป็น perfect match กับปัญหาที่คุณแก้ แต่ถ้าเลือกโครงสร้างเริ่มต้นที่เหมาะสมสำหรับข้อมูลของคุณ คำสั่ง Redis จะนำคุณไปสู่วิธีที่มีประสิทธิภาพในการได้สิ่งที่ต้องการ คำสั่ง Redis หลายตัวมี prefix บ่งชี้ชนิดโครงสร้างข้อมูลพื้นฐานที่ทำงานร่วมกับมัน
โครงสร้างข้อมูล General-purpose
| Prefix | ใช้งาน | ข้อควรระวังและการใช้งานผิดทั่วไป | |
|---|---|---|---|
| Hash | H | เก็บออบเจ็กต์; อะไรก็ตามที่คุณใช้ dictionary object | เหมือน Redis เอง ปัญหาใหญ่ที่สุดที่ผู้ใช้เจอกับ Hashes คือ key accounting ให้แน่ใจว่ามีระบบป้องกันไม่ให้ hashes เต็มไปด้วย keys และ values ที่ไม่ต้องการ |
| List | L | คิว, สแต็ก, และ circular lists | อย่าพยายาม random access บน lists ใหญ่ และระวังคิวสะสม |
| Set | S | ระบบแท็ก, buckets สำหรับ time-series data | Intersections และ unions ต้องใช้ระวัง – เก็บ sets ให้เล็ก Sets ไม่ใช่วิธีดีที่สุดนับ uniques ใช้ HyperLogLog แทน! |
| Sorted Set | Z | Scoreboards, lexicographical searches, random-access lists | Zsets เป็นโครงสร้างหลากหลายที่สุด และแพงที่สุดด้วย ระวัง big O! ถ้าใช้ sorted sets สำหรับ autocomplete ควรสำรวจ ZRANGEBYLEX ที่จัดการ lexicographical searching (แต่ระวัง UTF-8!) |
| Stream | X | Time series, queues, message distribution | การไม่ cap streams พบบ่อย พวกมันก็บางทับสับสนกับความสามารถของ distributed messaging systems (โดยเฉพาะ Apache Kafka) |
| String | (none) | Simple caches, counters, bit manipulation | ระวังค่าขนาดใหญ่เกินไป GET หรือ SET อาจทำให้เกิด failures ยากต่อการค้นหาในเครือข่ายและ Redis clients บางตัว ง่ายต่อการทำลายตัวเองโดยใช้ SETNX สร้างระบบ locking |
โครงสร้างข้อมูลเฉพาะทาง (Specialized Data Structures)
Redis ให้ operations หลายอย่างสำหรับจัดการกรณีพิเศษของชนิดเฉพาะ ในขณะที่ "under-the-hood" type เป็นหนึ่งใน general-purpose data types ข้างต้น:
| Prefix | Underlying Type | ใช้งาน | ข้อควรระวังและการใช้งานผิดทั่วไป | |
|---|---|---|---|---|
| Bitmap | BIT | String | Flags ประหยัดพื้นที่สำหรับ analytics | สับสนเกี่ยวความสามารถ หรือเลิกติดตาม complexities ของ accounting ในระบบ bitmap-based |
| Counter | INCR, DECR | String | Analytics ประหยัดพื้นที่ | Overflow ของ 64-bit signed range จะคืน error |
| Geohash | GEO | Sorted Set | เก็บ locators, หา users ใกล้เคียง | การคำนวณระยะไกล ที่ต้องการ projections หรือ geographical functions ขั้นสูง |
| HyperLogLog | PF | String | นับ uniques สำหรับ analytics | การ merge HLLs หลายตัวราคาแพง ให้แน่ใจว่ามี cap จำนวน parameters ใน PFMERGE |
| Pub/Sub | PUB, SUB, PSUB | (none) | Message passing แบบชั่วคราว | Simple, fast message-passing ไม่มี durability Stream type เลือกดีกว่าสำหรับกรณีใช้งานส่วนใหญ่ |
ใช้ Big O ของคุณ
การใช้ access patterns ของโครงสร้างข้อมูลผิด เหมือนใช้พจนานุกรมผิด: อย่าพลิกหน้าทุกหน้าค้นหาคำ! Time complexity ของทุกคำสั่ง Redis มีในเอกสาร redis.io
Big O เป็นวิธีแสดง "limiting behavior" ของประสิทธิภาพ วิคิดง่ายๆ คือ operation จะ perform ยังไงเมื่อข้อมูลในระบบเพิ่มขึ้น ถ้า operation เป็น O(1) ใช้เวลาคงที่เสมอ ไม่ว่าข้อมูลจะมากแค่ไหน Operation ที่เป็น O(n) ขยายแบบเส้นตรงกับข้อมูล และ O(n²) ช้าลงแบบ exponential เมื่อข้อมูลเพิ่ม
สำหรับการอธิบายลึกกว่า ดู easy introduction to big O พร้อมโค้ดตัวอย่างและกราฟ
System design ที่ดีต้องการมากกว่าการวิเคราะห์อัลกอริทึมพื้นฐาน แต่มีค่าที่จะปัดฝุ่นพื้นฐานบ้าง และคิดเกี่ยวกับ total complexity ของ data access ในแอปของคุณ
เก็บ Operations ให้เล็ก
Redis เป็น single-threaded ทำให้ง่ายต่อการให้เหตุผล แต่ก็ทำให้คนที่คุ้นแค่ multithreaded data access ประหลาดใจได้ Long-running operations อันตรายกว่าใน Redis เทียบกับ databases อื่นๆ: เนื่องจาก Redis ทำทีละอย่าง Long-running operations อาจทำให้ระบบล้มทั้งระบบ
การทำให้ data access operations ไม่ละเอียด (granular) เป็นกุญแจสู่ประสิทธิภาพดีกับ Redis 100,000 O(1) operations ใน Redis อาจดีกว่า 1 O(N) operation บน collection 100,000 elements แม้คุณจ่ายค่า penalty จาก network และ protocol parsing
หาจุดเจ็บปวดในระบบยังไง? เช็ค SLOWLOG บ่อยๆ (หรือถ้าคุณลูกค้า RedisGreen แค่มองแท็บ "Slow Queries" บนแดชบอร์ด) ยิ่ง single operation รันนาน ยิ่งช่าทุกอย่างที่ระบบพยายามทำ ดังนั้นให้สั้น!