परिचय: Rust में कैशिंग क्यों ज़रूरी है?
\nगति Rust की सबसे बड़ी ताकत है। लेकिन सबसे तेज़ कोड भी धीमे इनपुट/आउटपुट (I/O) में फंस सकता है: डेटाबेस क्वेरी, बाहरी API, या जटिल डेटा की गणना। कैशिंग इस समस्या को हल करता है, महंगे ऑपरेशनों के परिणामों को तेज़ स्टोरेज में सहेजकर। Rust कैशिंग के लिए लचीले टूल्स प्रदान करता है: सरल इन-बिल्ट डेटा स्ट्रक्चर से लेकर Redis और Memcached जैसी शक्तिशाली वितरित प्रणालियों तक।
\nइस लेख में, हम Rust में कैशिंग के सभी स्तरों को कवर करेंगे: सरल HashMap से लेकर TTL (टाइम-टू-लिव) और सिंक्रोनाइज़ेशन वाले प्रोफेशनल समाधानों तक। आप सीखेंगे कि अपने प्रोजेक्ट के लिए सही टूल कैसे चुनें और सामान्य गलतियों से कैसे बचें।
1. इन-बिल्ट कैशिंग: HashMap और इसके वेरिएंट
\nRust में कैशिंग का सबसे सरल तरीका स्टैंडर्ड लाइब्रेरी के HashMap का उपयोग करना है। हालांकि, मल्टी-थ्रेडेड वातावरण में अतिरिक्त सिंक्रोनाइज़ेशन तंत्र की आवश्यकता होती है।
1.1. सरल HashMap (सिंगल-थ्रेडेड)
\nसिंगल-थ्रेडेड एप्लिकेशन के लिए सामान्य HashMap उपयुक्त है। उदाहरण:
use std::collections::HashMap;\n\nfn main() {\n let mut cache: HashMap<String, String> = HashMap::new();\n cache.insert("user:1".to_string(), "Alice".to_string());\n \n if let Some(name) = cache.get("user:1") {\n println!("कैश किया गया मान: {}", name);\n }\n}\nलाभ: न्यूनतम कोड, कोई डिपेंडेंसी नहीं।
\nनुकसान: कोई TTL नहीं, थ्रेड-सेफ नहीं, मेमोरी सीमित नहीं।
1.2. Mutex और Arc के साथ थ्रेड-सेफ कैश
\nमल्टी-थ्रेडेड एप्लिकेशन के लिए Arc<Mutex<HashMap>> का उपयोग करें:
use std::collections::HashMap;\nuse std::sync::{Arc, Mutex};\nuse std::thread;\n\nstruct Cache {\n store: Arc<Mutex<HashMap<String, String>>>,\n}\n\nimpl Cache {\n fn new() -> Self {\n Cache { store: Arc::new(Mutex::new(HashMap::new())) }\n }\n \n fn get(&self, key: &str) -> Option<String> {\n self.store.lock().ok()?.get(key).cloned()\n }\n \n fn set(&self, key: String, value: String) {\n self.store.lock().unwrap().insert(key, value);\n }\n}\n\nfn main() {\n let cache = Cache::new();\n let c1 = cache.clone();\n thread::spawn(move || {\n c1.set("key".to_string(), "value".to_string());\n });\n println!("{:?}", cache.get("key"));\n}\nकमी: उच्च प्रतिस्पर्धा में Mutex लॉकिंग प्रदर्शन को कम कर सकता है।
\n\n1.3. उन्नत लाइब्रेरीज़: lru और cached
\nप्रोडक्शन कोड के लिए तैयार क्रेट्स का उपयोग करना बेहतर है:
\n- \n
lru— LRU (Least Recently Used) एल्गोरिदम लागू करता है। सीमित कैश के लिए उपयुक्त। \n cached— TTL और LRU समर्थन के साथ फंक्शनों की ऑटोमैटिक कैशिंग के लिए मैक्रोज़ प्रदान करता है। \n
cached के साथ उदाहरण:
use cached::proc_macro::cached;\n\n#[cached(size = 100, time = 300)]\nfn expensive_computation(x: u32) -> u32 {\n std::thread::sleep(std::time::Duration::from_secs(2));\n x * x\n}\n\nfn main() {\n let result = expensive_computation(5); // 2 सेकंड लगते हैं\n let cached_result = expensive_computation(5); // तुरंत\n println!("{}", cached_result);\n}\n\n2. Redis: स्केलेबल सिस्टम के लिए वितरित कैश
\nRedis एक इन-मेमोरी डेटा स्टोर है, जो वितरित कैशिंग के लिए आदर्श है। Rust में Redis के साथ काम करने के लिए redis क्रेट का उपयोग किया जाता है।
2.1. कनेक्शन और बुनियादी ऑपरेशन
\nuse redis::Commands;\n\nfn main() -> redis::RedisResult<()> {\n let client = redis::Client::open("redis://127.0.0.1:6379/")?;\n let mut con = client.get_connection()?;\n \n // TTL (टाइम-टू-लिव) के साथ मान सेट करना\n con.set_ex("user:1", "Alice", 3600)?; // 1 घंटे के लिए\n \n let value: String = con.get("user:1")?;\n println!("कैश से मान: {}", value);\n \n Ok(())\n}\n\nRedis कैशिंग के लिए उन्नत सुविधाएँ प्रदान करता है जैसे कि डेटा स्थायित्व, पब/सब मैसेजिंग, और लुआ स्क्रिप्टिंग। यह बड़े पैमाने के एप्लिकेशन के लिए एक शक्तिशाली विकल्प है।