प्रोडक्शन में ClickHouse चलाना: 2 अरब रोज़ पर इंजेशन, मर्ज और लागत
प्रोडक्शन में ClickHouse चलाने का हमारा अनुभव: स्कीमा डिज़ाइन, क्वेरी ऑप्टिमाइज़ेशन, और 100M+ डिवाइस इवेंट्स पर सब-सेकंड एनालिटिक्स कैसे हासिल करते हैं।
जब हमने tracio.ai का एनालिटिक्स टियर बनाना शुरू किया, तो हमें एक ऐसा डेटाबेस चाहिए था जो हमारे खास वर्कलोड को संभाल सके: प्रति सेकंड 50,000 डिवाइस आइडेंटिफिकेशन इवेंट्स इंजेस्ट करे, 2+ अरब रोज़ स्टोर करे, और एनालिटिकल क्वेरीज़ का जवाब एक सेकंड से कम में दे। हमने PostgreSQL (इस स्केल पर एग्रीगेशन के लिए बहुत धीमा), Elasticsearch (टाइम-सीरीज़ एनालिटिक्स के लिए बहुत महंगा), और ClickHouse का मूल्यांकन किया। ClickHouse ने निर्णायक रूप से बाज़ी मारी।
ClickHouse ही क्यों
ClickHouse एक कॉलम-ओरिएंटेड OLAP डेटाबेस है जो रियल-टाइम एनालिटिक्स के लिए डिज़ाइन किया गया है। हमारे वर्कलोड के लिए इसका मुख्य फ़ायदा यह है कि यह हर क्वेरी के लिए केवल ज़रूरी कॉलम ही पढ़ता है। जब कोई fraud analyst पूछता है "पिछले 7 दिनों की देश-वार फ्रॉड रेट दिखाओ," तो ClickHouse केवल country, timestamp और risk_score कॉलम पढ़ता है — इवेंट टेबल के बाकी 40+ कॉलम को नज़रअंदाज़ करते हुए। 2 अरब रो वाली टेबल पर इससे I/O 95% कम हो जाता है।
ClickHouse डेटा को बेहद अच्छी तरह कम्प्रेस भी करता है। हमारी 2 अरब रो वाली events टेबल डिस्क पर 340 GB घेरती है — कम्प्रेस्ड रूप में करीब 170 बाइट प्रति रो, जबकि बिना कम्प्रेस किए 1.2 KB प्रति रो। 7:1 का कम्प्रेशन अनुपात यानी अधिक डेटा मेमोरी में समा जाता है, जो सीधे तौर पर तेज़ क्वेरीज़ में तब्दील होता है।
स्कीमा डिज़ाइन
हमारी प्राथमिक टेबल प्रति आइडेंटिफिकेशन इवेंट एक रो स्टोर करती है:
यह टेबल MergeTree इंजन का उपयोग करती है, जो (workspace_id, toDate(timestamp), visitor_hash) से ऑर्डर की गई है। यह ऑर्डरिंग अहम है — इसका मतलब है कि workspace और date range से फ़िल्टर की गई क्वेरीज़ न्यूनतम डेटा पढ़ती हैं। visitor_hash कॉलम बिना किसी सेकंडरी इंडेक्स के visitor ID से तेज़ लुकअप संभव बनाता है।
हमने country, device_type, browser_family और os_family के लिए LowCardinality(String) चुना क्योंकि इन कॉलम में 10,000 से कम विशिष्ट मान होते हैं। ClickHouse LowCardinality कॉलम को डिक्शनरी-एन्कोडेड इंटिजर के रूप में स्टोर करता है, जिससे सादे स्ट्रिंग की तुलना में स्टोरेज 80% घट जाता है और GROUP BY ऑपरेशन तेज़ हो जाते हैं।
शार्डिंग रणनीति
हम events टेबल को workspace_id के हैश का उपयोग करके 6 नोड्स पर शार्ड करते हैं। इससे यह सुनिश्चित होता है कि किसी दिए गए ग्राहक के सभी इवेंट्स एक ही शार्ड पर हों, यानी अधिकांश क्वेरीज़ (workspace_id से फ़िल्टर की गई) एक ही शार्ड पर पड़ती हैं। क्रॉस-शार्ड क्वेरीज़ की ज़रूरत केवल आंतरिक एनालिटिक्स के लिए पड़ती है।
हर शार्ड में हाई अवेलेबिलिटी के लिए 2 रेप्लिका होती हैं। रेप्लिकेशन ClickHouse के अंतर्निहित ReplicatedMergeTree इंजन और ZooKeeper कोऑर्डिनेशन का उपयोग करता है। फ़ेलओवर स्वचालित है — अगर कोई शार्ड डाउन हो जाता है, तो क्वेरीज़ बिना किसी क्लाइंट-साइड बदलाव के रेप्लिका पर रूट कर दी जाती हैं।
इंजेशन पाइपलाइन
इवेंट्स हमारे Kafka टॉपिक से एक कस्टम Go सर्विस के ज़रिए ClickHouse में प्रवाहित होते हैं जो इंसर्ट को बैच में बांधती है। हम हर 500ms में 10,000 रोज़ के बैच में इंसर्ट करते हैं — इससे इंजेशन लेटेंसी (सब-सेकंड) और इंसर्ट दक्षता (ClickHouse बड़े बैच के साथ सबसे बेहतर काम करता है) के बीच संतुलन बनता है।
इंजेशन सर्विस बैक-प्रेशर को सहजता से संभालती है। अगर ClickHouse इंसर्ट स्वीकार करने में धीमा हो (मर्ज या भारी क्वेरी लोड के दौरान), तो सर्विस मेमोरी में 10 लाख इवेंट्स तक बफ़र करती है और Kafka कंज़्यूमर पर बैक-प्रेशर लागू करती है। प्रोडक्शन के 18 महीनों में हमने कभी कोई इवेंट नहीं खोया।
क्वेरी ऑप्टिमाइज़ेशन
मटीरियलाइज़्ड व्यूज़
आम डैशबोर्ड क्वेरीज़ के लिए हम मटीरियलाइज़्ड व्यूज़ का उपयोग करते हैं जो डेटा को पहले से एग्रीगेट कर देते हैं। मिसाल के तौर पर, हमारा फ्रॉड रेट डैशबोर्ड एक मटीरियलाइज़्ड व्यू से पढ़ता है जो fraud_detected काउंट को workspace, country और घंटे के अनुसार एग्रीगेट करता है। यह व्यू इस क्वेरी के लिए स्कैन किए जाने वाले डेटा को 2 अरब रो से घटाकर 5M (50 लाख) रो कर देता है।
प्रोजेक्शन ऑर्डरिंग
ClickHouse प्रोजेक्शन्स हमें डेटा को डुप्लिकेट किए बिना किसी टेबल के लिए वैकल्पिक सॉर्ट ऑर्डर परिभाषित करने देते हैं। हमने visitor timeline क्वेरीज़ के लिए (workspace_id, visitor_hash, timestamp) से ऑर्डर किया गया एक प्रोजेक्शन जोड़ा। प्रोजेक्शन के बिना ये क्वेरीज़ पूरी date range स्कैन करती थीं। इसके साथ, वे केवल उन्हीं ब्लॉक्स को पढ़ती हैं जिनमें लक्षित visitor होता है।
अनुमानित फंक्शन
जिन डैशबोर्ड क्वेरीज़ में सटीक काउंट अहम नहीं है, वहां हम ClickHouse के अनुमानित फंक्शन उपयोग करते हैं: विशिष्ट काउंट के लिए uniqCombined (2% त्रुटि मार्जिन, uniqExact से 10x तेज़) और परसेंटाइल गणना के लिए quantileTDigest। फ्रॉड एनालिटिक्स डैशबोर्ड केवल अनुमानित फंक्शन इस्तेमाल करता है, जिससे सभी डैशबोर्ड क्वेरीज़ 200ms से नीचे रहती हैं।
परफ़ॉर्मेंस आंकड़े
यहां हमारे 2 अरब रो वाले प्रोडक्शन क्लस्टर पर प्रतिनिधि क्वेरी बेंचमार्क दिए गए हैं:
देश-वार फ्रॉड रेट, पिछले 7 दिन: 120ms। विज़िटर टाइमलाइन (50 इवेंट्स): 8ms। प्रति दिन विशिष्ट विज़िटर, पिछले 30 दिन: 340ms। रिस्क स्कोर वितरण, पिछले 24 घंटे: 95ms। इवेंट काउंट के आधार पर टॉप 100 डिवाइस, पिछले 30 दिन: 210ms।
इन आंकड़ों में हमारे एप्लिकेशन सर्वर से ClickHouse क्लस्टर तक का नेटवर्क राउंड-ट्रिप शामिल है। शुद्ध क्वेरी एग्ज़िक्यूशन समय आमतौर पर 30-50% कम होता है।
ऑपरेशनल सबक
सबक 1: मर्ज लैग की निगरानी करें
ClickHouse का MergeTree इंजन छोटे डेटा पार्ट्स को लगातार बड़े पार्ट्स में मर्ज करता रहता है। अगर मर्ज पिछड़ जाते हैं (ऊंची इंसर्ट दर या डिस्क I/O प्रतिस्पर्धा के कारण), तो क्वेरी परफ़ॉर्मेंस गिर जाती है क्योंकि क्वेरीज़ को अधिक पार्ट्स स्कैन करने पड़ते हैं। हम प्रति पार्टीशन पार्ट्स की गिनती की निगरानी करते हैं और 300 से अधिक होने पर अलर्ट देते हैं।
सबक 2: बड़े ALTER TABLE ऑपरेशन से बचें
ClickHouse में 2 अरब रो वाली टेबल में कॉलम जोड़ना तत्काल होता है (यह केवल मेटाडेटा का मामला है)। लेकिन कॉलम का टाइप बदलने के लिए सभी डेटा पार्ट्स को दोबारा लिखना पड़ता है — यह प्रक्रिया हमारे क्लस्टर पर 6 घंटे तक चली। अब हम स्कीमा को केवल-अपेंड (append-only) मानते हैं: नए कॉलम स्वतंत्र रूप से जोड़े जाते हैं, लेकिन टाइप बदलाव एक माइग्रेशन टेबल से होकर गुज़रते हैं।
सबक 3: TTL सावधानी से
ClickHouse TTL के ज़रिए स्वचालित डेटा एक्सपायरी को सपोर्ट करता है। हमने अपनी events टेबल पर 90-दिन का TTL सेट किया है। पेच यह है: TTL डिलीशन मर्ज के दौरान होता है, यानी TTL एक्सपायर होने के घंटों या दिनों बाद तक डिलीट किया गया डेटा बना रह सकता है। कम्प्लायंस-क्रिटिकल डिलीशन के लिए हम एक शेड्यूल पर स्पष्ट ALTER TABLE DELETE क्वेरीज़ चलाते हैं।
लागत
हमारे 6-नोड ClickHouse क्लस्टर (हर नोड: 32 vCPU, 128 GB RAM, 2 TB NVMe) की लागत बेयर-मेटल होस्टिंग पर लगभग $8,400/माह है। यह 90-दिन रिटेंशन के साथ 2 अरब रो स्टोर करता है और 50K इंसर्ट/सेकंड के साथ-साथ 200 समवर्ती डैशबोर्ड क्वेरीज़ संभालता है। प्रति संग्रहीत इवेंट लागत $0.0000042 है — मैनेज्ड क्लाउड डेटाबेस पर तुलनीय एनालिटिक्स से कई गुना सस्ता।