PostgreSQL Advisory Locks לתזמון משימות מבוזר
הפסיקו להוסיף Redis או SQS ל-stack שלכם רק לצורך תזמון משימות.
אתם יכולים להשתמש ב-PostgreSQL advisory locks במקום זאת. גישה זו מסירה את הצורך בתשתית חדשה.
בבדיקות שלי, ההגדרה הזו מטפלת ב-10,000 משימות לדקה במופע (instance) בודד של בסיס הנתונים. היא לרוב מנצחת את Redis ב-latency מכיוון שה-workers שלכם כבר מחזיקים בחיבורי בסיס הנתונים. אתם נמנעים מ-network hop נוסף.
איך ליישם זאת:
• השתמשו ב-pg_try_advisory_xact_lock לצורך תפיסת משימות (job claiming).
• השתמשו ב-FOR UPDATE SKIP LOCKED כדי לטפל בתחרות על שורות (row contention).
• השתמשו בגרסה הטרנזקציונית (transactional variant) כדי למנוע דליפות מנעולים (lock leaks).
למה מנעולים טרנזקציוניים חשובים:
מנעולים טרנזקציוניים משתחררים באופן אוטומטי כאשר טרנזקציה עוברת commit או rollback. זה מונע מנעולים יתומים (orphaned locks) אם האפליקציה שלכם קורסת. זה גם עובד בצורה בטוחה עם PgBouncer במצב טרנזקציה (transaction mode).
הימנעו מנעולי סשן (session locks) אם אתם משתמשים ב-PgBouncer. PgBouncer מקצה מחדש חיבורים בין טרנזקציות. זה שובר מנעולים ברמת הסשן וגורם לכשלים שקטים (silent failures).
אם אתם זקוקים למנעולי סשן, צרו pool חיבורים נפרד עבור ה-workers שלכם. אל תערבבו תעבורת web עם תעבורת job workers באותו pool.
סקיילביליות באמצעות מפתחות:
advisory locks משתמשים ב-bigint או בשני מספרים שלמים (integers). שימוש בשני מספרים שלמים מספק namespacing טבעי. אם אתם מבצעים hash למפתחות טקסט ל-bigint, שימו לב להתנגשויות (collisions). מספר ההתנגשויות נשאר נמוך עד שתגיעו ל-100,000 מזהי מנעול (lock IDs) ייחודיים. מעבר לכך, השתמשו בצורה של שני מספרים שלמים כדי להישאר בטוחים.
הפשרה (The Tradeoff):
• advisory locks מנצחים בפשטות ובעלות תפעולית נמוכה. • Redis מנצח ב-throughput גולמי ובסקיילביליות אופקית.
רוב הצוותים לא זקוקים ליותר מ-10,000 משימות לדקה. אם אתם מתחת למגבלה הזו, היצמדו ל-Post