Leaderboards
รูปแบบ leaderboard
หัวข้อที่มีชื่อว่า “รูปแบบ leaderboard”Leaderboard ของเกมหรือแอปต้องการสามสิ่ง: เก็บคะแนน, จัดอันดับผู้เล่น, และ เพิ่มคะแนนเมื่อเวลาผ่านไป Redis Sorted Sets จัดการทั้งสามแบบ native ด้วย O(log N) สำหรับการเขียนและ O(log N + M) สำหรับ range read
ขั้นตอนที่ 1 — เพิ่มคะแนนเริ่มต้นด้วย ZADD
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 1 — เพิ่มคะแนนเริ่มต้นด้วย ZADD”เริ่มด้วยการ insert ผู้เล่นและคะแนน คะแนนเป็น float64 จึงแทนได้ทั้งแต้ม, เปอร์เซ็นต์, timestamp, หรือค่าตัวเลขใดก็ได้
127.0.0.1:6379> ZADD game:lb 3200 "alice" 4100 "bob" 1750 "carol" 5800 "dave" 2900 "eve"(integer) 5ZADD game:lb 3200 "alice" 4100 "bob" 1750 "carol" 5800 "dave" 2900 "eve"ขั้นตอนที่ 2 — ดึง top 10 ด้วย ZREVRANGE
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 2 — ดึง top 10 ด้วย ZREVRANGE”ZREVRANGE key 0 9 WITHSCORES คืนผู้เล่น 10 อันดับแรกตามลำดับคะแนนจากมากไปน้อย Index เป็น rank offset ดังนั้น 0 9 หมายถึงตำแหน่ง 1 ถึง 10 เสมอ
127.0.0.1:6379> ZREVRANGE game:lb 0 9 WITHSCORES1) "dave"2) "5800"3) "bob"4) "4100"5) "alice"6) "3200"7) "eve"8) "2900"9) "carol"10) "1750"ZREVRANGE game:lb 0 9 WITHSCORESขั้นตอนที่ 3 — ดูอันดับผู้เล่นด้วย ZREVRANK
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 3 — ดูอันดับผู้เล่นด้วย ZREVRANK”ZREVRANK key member คืน rank แบบ 0-based ตามลำดับจากมากไปน้อย — 0 คืออันดับหนึ่ง บวก 1 เพื่อให้อ่านง่ายขึ้นสำหรับมนุษย์
127.0.0.1:6379> ZREVRANK game:lb "alice"(integer) 2127.0.0.1:6379> ZREVRANK game:lb "carol"(integer) 4127.0.0.1:6379> ZSCORE game:lb "alice""3200"ZREVRANK game:lb "alice"
ZREVRANK game:lb "carol"
ZSCORE game:lb "alice"ขั้นตอนที่ 4 — มอบแต้มด้วย ZINCRBY
หัวข้อที่มีชื่อว่า “ขั้นตอนที่ 4 — มอบแต้มด้วย ZINCRBY”เมื่อผู้เล่นได้แต้มเพิ่ม ใช้ ZINCRBY เพื่อบวกเข้ากับคะแนนที่มีอยู่แบบ atomic ไม่ต้องทำ read-modify-write cycle
127.0.0.1:6379> ZINCRBY game:lb 1500 "carol""3250"127.0.0.1:6379> ZINCRBY game:lb 800 "alice""4000"127.0.0.1:6379> ZREVRANGE game:lb 0 4 WITHSCORES1) "dave"2) "5800"3) "bob"4) "4100"5) "alice"6) "4000"7) "carol"8) "3250"9) "eve"10) "2900"ZINCRBY game:lb 1500 "carol"
ZINCRBY game:lb 800 "alice"
ZREVRANGE game:lb 0 4 WITHSCORESworkflow leaderboard ครบวงจรในการ paste เดียว
หัวข้อที่มีชื่อว่า “workflow leaderboard ครบวงจรในการ paste เดียว”127.0.0.1:6379> ZADD lb 3200 "alice" 4100 "bob" 1750 "carol" 5800 "dave" 2900 "eve"(integer) 5127.0.0.1:6379> ZREVRANGE lb 0 9 WITHSCORES1) "dave"2) "5800"3) "bob"4) "4100"5) "alice"6) "3200"7) "eve"8) "2900"9) "carol"10) "1750"127.0.0.1:6379> ZREVRANK lb "carol"(integer) 4127.0.0.1:6379> ZINCRBY lb 2500 "carol""4250"127.0.0.1:6379> ZREVRANK lb "carol"(integer) 1ZADD lb 3200 "alice" 4100 "bob" 1750 "carol" 5800 "dave" 2900 "eve"
ZREVRANGE lb 0 9 WITHSCORES
ZREVRANK lb "carol"
ZINCRBY lb 2500 "carol"
ZREVRANK lb "carol"ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Sorted Set สำหรับ leaderboard | ranking แบบ real-time โดยไม่ต้อง JOIN หรือ ORDER BY, เขียนและอ่าน O(log N) | คะแนนเป็น float64 เท่านั้น ต้อง encode tie-breaker เองถ้าต้องการ ranking ที่ซับซ้อนกว่าคะแนนตัวเลข |
ZINCRBY แบบ atomic | อัปเดตคะแนนโดยไม่ต้อง read-modify-write, ปลอดภัยเมื่อมีหลาย client เขียนพร้อมกัน | ไม่มี event log ของการเปลี่ยนแปลง ถ้าต้องการ audit trail ว่าใครมอบแต้มเมื่อไรต้องเก็บแยกเอง |
ดึง top N ด้วย ZREVRANGE | เร็วและง่าย ไม่ต้อง cache ผลลัพธ์แยก | เรียก fresh ทุกครั้งบน leaderboard ขนาดใหญ่ที่ traffic สูงมากอาจยังต้องมี cache layer เพิ่มเติม |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ใช้คะแนนเดียวกันสำหรับผู้เล่นหลายคนโดยไม่ตั้งใจ —
ZRANGE/ZREVRANGEจะเรียงลำดับ tie ด้วย lexicographic order ของ member ทำให้อันดับดูสุ่มถ้าไม่ได้ตั้งใจออกแบบไว้ ควรผูก timestamp เข้ากับคะแนนเพื่อ break tie อย่างมีความหมาย - ลืมว่า
ZREVRANKเป็นแบบ 0-based — อันดับหนึ่งคืนค่า 0 ไม่ใช่ 1 ถ้าแสดงผลตรงๆ ให้ผู้ใช้ต้องบวก 1 เอง มิฉะนั้นอันดับจะเพี้ยนไปหนึ่งตำแหน่งเสมอ - ใช้
ZADDแทนZINCRBYเมื่อต้องการมอบแต้มเพิ่ม —ZADDตั้งคะแนนใหม่ทับของเดิมทันที ไม่ใช่บวกเพิ่ม ถ้าใช้ผิดจะทำให้คะแนนเดิมหายไปแทนที่จะสะสม
💡 ตัวอย่างจากของจริง
เกมออนไลน์หลายค่าย — ใช้ Redis Sorted Set เป็น backend ของ leaderboard real-time เพราะ
ZADD/ZREVRANGE/ZREVRANKให้ ranking ที่อัปเดตทันทีโดยไม่ต้อง batch job มาคำนวณใหม่Reddit-style ranking — ใช้แนวคิดเดียวกันกับ Sorted Set โดยผูก “hot score” (คำนวณจาก vote และเวลา) เป็น score เพื่อจัดเรียงโพสต์แบบ real-time โดยไม่ต้อง query ฐานข้อมูลหลักซ้ำ