Redis मध्ये Sliding Window Rate Limiter तयार करणे
गेल्या तिमाहीत दोनदा सकाळी ९:०० च्या आधी आमचा YouTube API कोटा शून्य झाला. यामुळे आमच्या अर्ध्या क्षेत्रांमधील (regions) ट्रेंडिंग फीड्स कालबाह्य झाले.
समस्या ट्रॅफिक वाढण्याची नव्हती. ती आमच्या rate limiter मध्ये होती.
आम्ही fixed-window counter वापरत होतो. जर API कॉल्स विंडोच्या सीमेवर (boundary) आले, तर यामुळे दोन मोठ्या प्रमाणात कॉल्स एकाच वेळी जाऊ शकत होते. ८ क्षेत्रांच्या जागतिक पाइपलाइनसाठी, ही सीमा ओव्हरलॅप होण्याची घटना वारंवार घडत होती. यामुळे आमचा दैनंदिन कोटा (daily quota) अपयशी ठरत होता.
मी fixed window च्या जागी Redis sorted sets वापरून sliding window log वापरला.
ते कसे कार्य करते ते खालीलप्रमाणे आहे:
- टाइमस्टॅम्पसह विनंती (request) रेकॉर्ड करण्यासाठी ZADD वापरा.
- विंडोच्या बाहेरच्या जुन्या नोंदी (entries) काढण्यासाठी ZREMRANGEBYSCORE वापरा.
- विंडोमध्ये नेमक्या किती विनंत्या शिल्लक आहेत हे मोजण्यासाठी ZCARD वापरा.
- निष्क्रिय कीज (idle keys) आपोआप साफ करण्यासाठी PEXPIRE वापरा.
ही पद्धत अचूक आहे. यात सीमेचा अडथळा येत नाही.
मी हे Redis मधील Lua script वापरून लागू केले. यामुळे संपूर्ण तपासणी आणि रेकॉर्ड करण्याची प्रक्रिया atomic राहते. जर तुम्ही हे पायऱ्या ॲप्लिकेशन कोडमध्ये चालवल्या, तर race conditions मुळे अतिरिक्त विनंत्या जाऊ शकतात.
प्रोडक्शनसाठी महत्त्वाचे तांत्रिक निर्णय:
- Redis TIME वापरा: तुमच्या ॲप्लिकेशन सर्व्हरवरील टाइमस्टॅम्प वापरू नका. सर्व्हरमधील क्लॉक स्क्यू (clock skew) विंडोची अचूकता खराब करू शकतो.
- वेटेड कॉस्ट (Weighted costs): सर्व API कॉल्स सारखे नसतात. एक सर्च कॉल १०० युनिट्स खर्च करू शकतो, तर व्हिडिओ लिस्ट १ युनिट खर्च करू शकते. माझे स्क्रिप्ट एका कॉलसाठी अनेक मेंबर्स इन्सर्ट करून हे हाताळते.
- अचूक Retry-After: सॉर्टेड सेटमधील सर्वात जुनी नोंद पाहून, सिस्टम क्षमता (capacity) कधी उपलब्ध होईल याचे अचूक गणित करते.
- फेल-सेफ लॉजिक (Fail-safe logic): मी EVALSHA सोबत EVAL fallback वापरतो. जर रीस्टार्ट दरम्यान Redis स्क्रिप्ट कॅशे क्लिअर झाला, तर ॲप्लिकेशन ते व्यवस्थित हाताळते.
याचा तोटा मेमरीच्या स्वरूपात आहे. प्रत्येक विनंती साधारण १०० बाईट्स घेते. १०,००० युनिट्सच्या दैनंदिन कोट्यासाठी, हे केवळ १ MB मेमरी आहे. बहुतेक वापरांसाठी, ही अचूकता या खर्चासाठी योग्य आहे.
या बदलामुळे आमचा कोटा एकदाही संपलेला नाही. आमची ജോब्स (jobs) ४०३ एरर येण्याऐवजी व्यवस्थित थांबतात.
जर तुमचा rate limiter घड्याळाच्या ठराविक वेळेवर (round number) रिसेट होत असेल, तर तुमच्याकडे मर्यादा नाही. तुमच्याकडे एक लूपहोल (loophole) आहे.