बड़े पैमाने पर रियल-टाइम फ्रॉड स्कोरिंग
tracio.ai कैसे स्ट्रीम प्रोसेसिंग, पहले से गणना किए गए सिग्नल वेक्टर और एज कैशिंग के साथ 50K इवेंट/सेकंड को 50ms से कम स्कोरिंग में प्रोसेस करता है।
बड़े पैमाने पर फ्रॉड स्कोरिंग के लिए batch प्रोसेसिंग की तुलना में मूल रूप से अलग आर्किटेक्चर की ज़रूरत होती है। जब किसी पेमेंट को अधिकृत किया जा रहा हो या कोई अकाउंट बनाया जा रहा हो, तब आपके पास रिस्क स्कोर देने के लिए मिनट नहीं, बल्कि मिलीसेकंड होते हैं। tracio.ai पर हम 50,000 से अधिक इवेंट प्रति सेकंड प्रोसेस करते हैं, जिसमें मीडियन स्कोरिंग लेटेंसी 22ms रहती है। यह लेख उस आर्किटेक्चर को समझाता है जो इसे संभव बनाता है।
स्कोरिंग पाइपलाइन
हर आने वाला इवेंट एक तीन-चरणीय पाइपलाइन में प्रवेश करता है: सिग्नल enrichment, वेक्टर गणना, और रिस्क स्कोरिंग। सिग्नल enrichment कच्चे इवेंट के साथ डिवाइस इंटेलिजेंस डेटा जोड़ता है — विज़िटर का फ़िंगरप्रिंट, bot डिटेक्शन परिणाम, IP इंटेलिजेंस, और ऐतिहासिक व्यवहार। वेक्टर गणना इन समृद्ध सिग्नलों को हमारे स्कोरिंग मॉडल के लिए अनुकूलित एक निश्चित-लंबाई वाले फीचर वेक्टर में बदल देती है। रिस्क स्कोरिंग वेक्टर को हमारे प्रशिक्षित मॉडल से गुजारती है और 0.0 से 1.0 के बीच एक स्कोर लौटाती है।
मुख्य डिज़ाइन निर्णय यह है कि enrichment और वेक्टर गणना को स्कोरिंग से अलग रखा गया है। Enrichment डेटा पहले से गणना करके कैश किया जाता है। जब कोई विज़िटर पेज लोड करता है, तब हम उसका डिवाइस प्रोफाइल गणना करके उसे 60 मिनट की TTL के साथ Redis में स्टोर करते हैं। जब कोई स्कोरिंग रिक्वेस्ट आती है — आमतौर पर किसी पेमेंट या लॉगिन से ट्रिगर होकर — तब हम प्रोफाइल को दोबारा गणना करने के बजाय पहले से गणना किया गया प्रोफाइल प्राप्त कर लेते हैं। इससे स्कोरिंग लेटेंसी 200ms+ से घटकर 30ms से कम रह जाती है।
Go के साथ स्ट्रीम प्रोसेसिंग
हमारी इनजेशन लेयर Go में लिखी गई है और एक fan-out आर्किटेक्चर का उपयोग करती है। आने वाले इवेंट HTTP POST के ज़रिए आते हैं और तुरंत एक आंतरिक channel पर रख दिए जाते हैं। वर्कर goroutines का एक pool इस channel से पढ़ता है, enrichment करता है, और समृद्ध इवेंट को एनालिटिक्स के लिए ClickHouse तथा रियल-टाइम प्रोसेसिंग के लिए एक स्कोरिंग queue में लिखता है। fan-out pool queue की गहराई के आधार पर गतिशील रूप से स्केल करता है।
हमने इनजेशन लेयर के लिए Go इसलिए चुना क्योंकि इसके concurrency primitives उत्कृष्ट हैं और मेमोरी आवंटन पूर्वानुमेय है। प्रत्येक वर्कर goroutine लगभग 4KB स्टैक स्पेस लेती है, जिससे हम एक ही नोड पर हज़ारों समवर्ती वर्कर चला सकते हैं। garbage collector के मिलीसेकंड से कम के pause उच्च throughput पर एकसमान लेटेंसी बनाए रखने के लिए अहम हैं।
एज कैशिंग और सिग्नल वेक्टर
अपने सबसे अधिक वॉल्यूम वाले ग्राहकों के लिए, हम पहले से गणना किए गए सिग्नल वेक्टर कैश का उपयोग करते हुए स्कोरिंग मॉडल एज पर तैनात करते हैं। जब कोई डिवाइस पहली बार दिखता है, तब हम उसका पूर्ण सिग्नल वेक्टर गणना करके उसे अपने एज कैश (Cloudflare Workers KV पर तैनात) में स्टोर करते हैं। उसी डिवाइस के लिए आगे की स्कोरिंग रिक्वेस्ट कैश किए गए वेक्टर को प्राप्त करती हैं और स्कोरिंग को स्थानीय रूप से एज पर चलाती हैं, जिससे 10ms से कम लेटेंसी हासिल होती है।
एज स्कोरिंग मॉडल हमारे पूर्ण मॉडल का एक distilled संस्करण है — छोटा और तेज़, लेकिन उन्हीं accuracy लक्ष्यों के लिए अनुकूलित। हम एज मॉडल को साप्ताहिक रूप से रिट्रेन करते हैं और cache invalidation storm से बचने के लिए अपडेट rolling deployment के ज़रिए तैनात करते हैं। जिन मामलों में एज मॉडल की confidence एक कॉन्फ़िगर करने योग्य threshold से नीचे होती है, वहाँ पूर्ण मॉडल सर्वर-साइड चलता है।
एनालिटिक्स के लिए ClickHouse
सभी समृद्ध इवेंट ClickHouse में स्टोर किए जाते हैं, जो हमारा columnar एनालिटिक्स डेटाबेस है। ClickHouse का compression और query परफ़ॉर्मेंस हमें अरबों इवेंट स्टोर करने देता है और साथ ही रियल-टाइम एनालिटिकल queries को सपोर्ट करता है। हमारे ग्राहक इन एनालिटिक्स का उपयोग फ्रॉड पैटर्न समझने, स्कोरिंग threshold ट्यून करने, और अलग-अलग इवेंट की जाँच करने के लिए करते हैं।
हम पहले से समुच्चयित मेट्रिक्स बनाए रखने के लिए ClickHouse में materialized views का उपयोग करते हैं: देश के अनुसार फ्रॉड दर, डिवाइस प्रकार के अनुसार स्कोरिंग वितरण, और threshold के अनुसार false positive दरें। ये materialized views इवेंट आने के साथ ही रियल-टाइम में अपडेट होते हैं, जिससे महँगी समुच्चयन queries के बिना डैशबोर्ड-तैयार मेट्रिक्स मिलते हैं।
सीखे गए सबक
एक रियल-टाइम स्कोरिंग सिस्टम बनाने से हमने कई सबक सीखे। पहला, पूर्व-गणना सबसे महत्वपूर्ण अनुकूलन है — जो भी काम आप स्कोरिंग रिक्वेस्ट आने से पहले कर सकते हैं, वह ऐसा काम है जो आपके लेटेंसी बजट में नहीं गिना जाता। दूसरा, Go का concurrency मॉडल उच्च-throughput इवेंट प्रोसेसिंग के लिए बहुत उपयुक्त है, लेकिन GC दबाव से बचने के लिए आपको मेमोरी आवंटन को लेकर अनुशासित रहना होगा। तीसरा, एज तैनाती लेटेंसी के लिए रूपांतरकारी है, लेकिन पुरानी भविष्यवाणियों से बचने के लिए सावधानीपूर्वक मॉडल प्रबंधन की ज़रूरत होती है।