הערה: כשיש לך אלפי משתמשים, שאילתת ORDER BY score DESC פשוטה מתחילה להעמיס על מסד הנתונים. נתקלנו בזה בפרויקטים ללקוחות FinTech ו-EdTech — העיכובים גדלו ל-5 שניות, ומשתמשים התלוננו על פיגור. לצורך דירוג בזמן אמת בין מיליון משתמשים, אנו משתמשים ב-Redis עם מבני נתונים מיוחדים. במאמר זה, אנו חולקים פתרונות ארכיטקטוניים שהוכחו בעשרות פרויקטים. לוח דירוג מעוצב היטב הוא אחד הכלים היעילים ביותר להגברת מעורבות. אבל גישות היישום משתנות מאוד בהתאם לקנה המידה והדרישות. טעויות ביישום עלולות להוביל לזמן אחזור גבוה ולחוויית משתמש ירודה.
אנו בוחנים שלוש קטגוריות עיקריות: עד 10,000 משתמשים, מ-10,000 עד מיליון, ומעל מיליון. לכל מקרה יש מחסנית טכנולוגית ותצורה אופטימלית. אנו משתמשים ב-Redis עם התמדה מסוג AOF לאמינות, ומפתחות נפרדים עם TTL ללוחות דירוג תקופתיים. חשוב גם להגדיר את סוג לוח הדירוג: גלובלי, תקופתי, חברתי או "סביבי" — כל אחד פותר משימות מוטיבציה שונות.
ואל תשכחו את חוויית המשתמש: אנימציות, שמירת אווטארים במטמון ועדכוני דירוג חלקים הם קריטיים לתפיסה. בחומר זה, אנו מתמקדים בפרטים טכניים ובשיטות עבודה מומלצות שעוזרות להימנע מטעויות נפוצות. בצד הלקוח, אנו משתמשים בשמירת תמונות במטמון ובעדכוני רשימה מצטברים.
בחירת טכנולוגיה ללוח דירוג לפי קנה מידה
עד 10,000 משתמשים: PostgreSQL עם פונקציות חלון RANK() / DENSE_RANK(). שאילתת עמודים רצה מהר גם ללא אינדקסים מיוחדים. אנו שומרים את 100 הראשונים במטמון ב-Redis עם TTL של 5 דקות.
10,000 – 1,000,000 משתמשים: Redis Sorted Sets (ZADD, ZRANK, ZREVRANK, ZREVRANGE). הוספת ניקוד: ZADD leaderboard:global NX <score> <user_id> או ZINCRBY leaderboard:global <delta> <user_id>. קבלת דירוג משתמש: ZREVRANK leaderboard:global <user_id> — O(log N). 100 הראשונים: ZREVRANGE leaderboard:global 0 99 WITHSCORES — O(log N + 100). זה עובד ללא ירידה בביצועים גם על מיליון משתמשים.
מיליוני משתמשים: חלוקת Redis Sorted Sets לפי תקופות זמן ואזורים. לוח דירוג גלובלי הופך למטרה בלתי מושגת עבור רוב המשתמשים — וזה מדכא. עדיף לפלח.
| קנה מידה | טכנולוגיה | ביצועים |
|---|---|---|
| עד 10K | PostgreSQL | מהיר, שמירת 100 הראשונים במטמון |
| 10K – 1M | Redis | O(log N) לכל פעולה |
| >1M | Redis + חלוקה | קנה מידה ליניארי |
סוגי לוחות דירוג ומאפייניהם
| סוג | תיאור | מוטיבציה |
|---|---|---|
| גלובלי (כל הזמנים) | דירוג כולל של כל המשתמשים | גבוהה ל-10 הראשונים, נמוכה לאחרים |
| תקופתי (שבוע/חודש) | איפוס דירוג | שווה לכולם, מרוץ להובלה |
| חברתי (חברים) | רק בין חברים | גבוהה מאוד, תחרות בריאה |
| "סביבי" | המשתמש ומיקומים שכנים | מניע לראות את ההתקדמות האישית |
תקופות זמן ללוחות דירוג
גלובלי "כל הזמנים" — לשחקנים המובילים. שבועי וחודשי — לכל השאר. איפוס בתחילת תקופה: אל תמחקו נתונים, ארכבו אותם. המשתמש צריך לראות את התוצאות הקודמות שלו.
יישום איפוס: מפתח נפרד לכל תקופה leaderboard:weekly:YYYY-WW, leaderboard:monthly:YYYY-MM. כשהתקופה מסתיימת, צרו מפתח חדש — הישן נשאר להיסטוריה. TTL על מפתחות ישנים: 30 יום לשבועי, 90 לחודשי.
למה לוח הדירוג "סביבי" מגביר מעורבות?
הסוג השימושי ביותר למשתמש הממוצע. לא "100 הראשונים", אלא "אתה במקום 4573, הנה 5 אנשים מעליך ו-5 מתחתיך". מניע את אלה שלעולם לא יגיעו לראש.
יישום ב-Redis: ZREVRANK לקבלת דירוג המשתמש, ואז ZREVRANGE(rank-5, rank+5) למיקומים שכנים. שאילתה נוספת ל-PostgreSQL לקבלת שם תצוגה ואווטאר לפי user_id מהתוצאה.
לוחות דירוג חברתיים
לוח דירוג בין חברים מניע לעתים יותר מאשר גלובלי. היישום מסובך יותר: אין טעם בקבוצה ממוינת גלובלית לרשימה של 50 חברים.
אפשרות 1: בפתיחת המסך, שאילתה ל-PostgreSQL: SELECT user_id, score FROM user_scores WHERE user_id IN (:friends_list) ORDER BY score DESC. עובד למספר קטן של חברים (עד 200).
אפשרות 2: קבוצה ממוינת נפרדת לכל משתמש leaderboard:user:<user_id>:friends — עדכון בכל פעם שהניקוד של חבר משתנה. יקר יותר בזיכרון ב-Redis (בערך פי 1.5), אבל קריאות מיידיות.
תצוגה וחוויית משתמש
הדגשת מיקום המשתמש הנוכחי ברשימה היא חובה. עדכון דירוג מונפש בקבלת ניקוד חדש (ScrollTo + הדגשה). חיצי עלייה/ירידה ליד המיקום — "טיפסת 12 מקומות היום". עקומת דירוג היסטורית לתקופה.
ב-Flutter: AnimatedList לעדכונים חלקים. ב-iOS: UITableView עם performBatchUpdates. באנדרואיד: RecyclerView עם DiffUtil. אל תטעינו מחדש את כל הרשימה בעדכון — רק תאים שהשתנו (3-5 בממוצע).
אווטארים בלוח הדירוג — שמרו במטמון באגרסיביות. SDWebImage (iOS) / Glide (Android) / cached_network_image (Flutter) עם מטמון דיסק (עד 50 MB). אל תציגו לוח דירוג ללא שמות ואווטארים — רק שלד במהלך הטעינה.
תהליך פיתוח לוח דירוג במפתח מלא
- ניתוח וארכיטקטורה: בחינת דרישות, בחירת מחסנית (Redis + PostgreSQL), תכנון API.
- יישום צד שרת: הגדרת Redis Sorted Sets, פיתוח נקודות קצה לדירוג ולטופ.
- צד לקוח: אינטגרציה ב-iOS (Swift), אנדרואיד (Kotlin) או Flutter עם אנימציות ושמירה במטמון.
- אינטגרציה עם מערכת אימות: קישור למסד נתוני משתמשים קיים.
- תיעוד ובדיקות: בדיקות עומס (עד 10,000 RPS), בדיקת ביצועים בזמן אמת.
- פריסה ותמיכה: פריסה על שרתים, חודש תחזוקה חינם.
מה כלול
- תיעוד ארכיטקטורה ו-API
- גישה למאגר עם קוד מקור
- הוראות פריסה והתקנה (כולל תצורות Redis)
- הדרכת צוות על תפעול לוח הדירוג
- חודש תמיכה טכנית לאחר ההשקה
הניסיון שלנו
אנו מפתחים יישומי מובייל עם גיימיפיקציה כבר למעלה מ-5 שנים. הפורטפוליו שלנו כולל 50+ פרויקטים, כולל לוחות דירוג לאפליקציות פינטק, אדטק ומשחקים. אנו מבטיחים פעולה יציבה בעומס של עד 10 מיליון משתמשים. — צוות פיתוח מובייל
דוגמה לתצורת Redis ללוח דירוג
# redis.conf save 900 1 save 300 10 save 60 10000 appendonly yes appendfsync everysec מפתחות: # redis.conf save 900 1 save 300 10 save 60 10000 appendonly yes appendfsync everysec , leaderboard:global, leaderboard:weekly:YYYY-WW.
הערכות זמנים
לוח דירוג בסיסי עם תקופה שבועית/חודשית ודירוג משתמש — 2–3 ימים (לקוח) + 2–3 ימים (צד שרת ב-Redis). עם לוח דירוג חברתי, "סביבי", היסטוריית דירוג ועדכונים בזמן אמת — 1–2 שבועות. העלות נקבעת בנפרד לאחר ניתוח. צרו קשר כדי לדון ביישום לוח דירוג באפליקציה שלכם.







