1 पॉइंट द्वारा GN⁺ 4 시간 전 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • कैश का उपयोग डेटाबेस पर लोड कम करने के लिए किया जाता है, लेकिन Redis जैसे इस्तेमाल में आसान टूल समय के साथ persistent storage की तरह निर्भर किए जाने लगते हैं
  • समस्या Redis की persistence feature में नहीं है, बल्कि उस operational flow में है जहाँ शुरुआत में volatile cache के रूप में लाया गया कॉम्पोनेंट एप्लिकेशन के मुख्य state के साथ जुड़ जाता है
  • memcached अपनी आधिकारिक परिभाषा से ही distributed memory object caching system है, और यह डिस्क स्टोरेज को आधार नहीं मानता, इसलिए इसे stateless cache workload की तरह संभालना आसान है
  • कई memcached instances को सर्वर नहीं बल्कि क्लाइंट URL सूची और key hash के आधार पर बाँटता है, और failure node hash ring से हट जाता है फिर बाद में reconnect की कोशिश करता है
  • “डेटाबेस धीमा है” कहकर पहले कैश जोड़ने के बजाय, पहले slow queries और missing indexes की जाँच करनी चाहिए

Redis के cache से storage में बदलने का क्षण

  • इन्फ्रास्ट्रक्चर चलाते समय “हमें कैश चाहिए” जैसी माँग अक्सर आती है, और परिचित व feature-rich Redis सबसे पहले याद आ जाता है
  • Redis होमपेज AI apps के लिए real-time context engine Redis Iris को प्रमुखता से दिखाता है, लेकिन Redis एक ऐसी कंपनी है जिसे revenue कमाना है, इस लिहाज़ से यह दिशा समझ में आती है
  • Redis deploy करके connection string दे देने पर शुरुआत में यह एक विश्वसनीय cache की तरह काम करता है

कुछ महीनों बाद आने वाली समस्या

  • समय बीतने पर cache.set("key", "value"), INSERT INTO table VALUES ('key', 'value') की तुलना में बहुत सरल लगता है, इसलिए लोग Redis को इस तरह मानने लगते हैं
    • एक ऐसा कॉम्पोनेंट जो हमेशा मौजूद रहेगा और डेटा संभालकर रखेगा। व्यवहार में एक डेटाबेस
    • REmote DIctionary Server को volatile cache नहीं बल्कि permanent storage की तरह समझा जाने लगता है
  • आपको और आपकी ops टीम के साथियों को भी यह बात पता नहीं चलती, और क्योंकि सब मानते हैं कि कैश volatile ही माना जाएगा, alerting system भी इसे पकड़ नहीं पाता
    • Redis पर upgrade, node migration, या RAID0 सर्वर के HDD tray के निकल जाने जैसी कोई घटना होने पर ही समस्या सामने आती है
  • असली समस्या यह नहीं कि Redis में persistence feature नहीं है, बल्कि यह है कि cache के रूप में लाए गए Redis को लोग cache की तरह नहीं चलाते
  • जब निर्भरता का पता देर से चलता है, तब तक Redis एप्लिकेशन में बहुत गहराई से जुड़ चुका होता है और उसे हटाना मुश्किल हो जाता है, और अंत में उसे एक “pet” की तरह maintain और monitor करना पड़ता है

memcached cache की भूमिका के लिए अधिक सीधा क्यों है

  • memcached एक “free open source, high-performance, distributed memory object caching system” है, और यह डेटाबेस लोड कम करके dynamic web applications को तेज़ बनाने के लिए एक general-purpose cache है
  • Django जैसे plug-in caching को support करने वाले framework में caching backend बदला जा सकता है
  • Redis की तुलना में कम features होने पर भी memcached चुनने का कारण इसकी operational characteristics का सरल होना है
    • downtime handling आसान है: client libraries अक्सर connection exceptions को ignore कर देती हैं, और साधारण get में सर्वर डाउन होने पर default value या None लौट सकता है
    • memcached में built-in clustering feature नहीं है, और इसी वजह से clustering उल्टा अधिक सुविधाजनक हो जाती है
      • client library में कई URL सेट करने पर key hash के आधार पर target instance चुना जाता है
      • अगर client call किसी instance के down होने का पता लगाती है, तो node को hasher से हटा देती है और कुछ समय बाद अपने-आप reconnect की कोशिश करती है
    • persistence का बोझ संरचनात्मक रूप से कम हो जाता है: memcached डिस्क पर स्टोर नहीं करता, इसलिए इसे stateless workload की तरह जहाँ चाहें schedule करना आसान है
  • Redis से भी ऐसा ही operational model बनाया जा सकता है, लेकिन memcached की architecture इस दिशा के अधिक करीब है, इसलिए इसे cache की तरह संभालना अधिक सहज है
  • memcached अपेक्षाकृत सरल application है, और लगभग 64MB cache size वाले दर्जनों instances चलाने पर भी overhead लगभग नहीं होता, यही इसे चुनने का एक कारण है
  • “डेटाबेस धीमा है” वाली कई समस्याएँ वास्तव में slow queries या missing indexes से शुरू होती हैं, इसलिए कैश जोड़ने के साथ query optimization भी देखनी चाहिए
  • अगर memcached के design decisions में रुचि हो, तो memcached blog पर बहुत से दिलचस्प लेख मिलेंगे। उनमें से एक मई में प्रकाशित “उत्तर मिलने में वास्तव में कितना समय लगता है? (How Long Does That Response Take… For Real?)” है

1 टिप्पणियां

 
GN⁺ 4 시간 전
Hacker News राय
  • Redis एक शानदार तकनीक है, लेकिन मेरा मानना है कि persistent data structure और volatile cache जैसी दो अलग भूमिकाएँ एक साथ अच्छी तरह निभाने की कोशिश में इसे दिक्कत होती है
    Redis में भी ये दोनों अच्छी तरह घुलते-मिलते नहीं हैं, इसलिए persistence को global स्तर पर on या off करना पड़ता है
    pure cache के लिए मैं memcached या उसके बराबर कुछ इस्तेमाल करूंगा, और केवल scoreboard जैसे data structure की ज़रूरत होने पर persistence enabled Redis चुनूंगा
    $WORK में हमने दोनों में से कोई भी नहीं अपनाया, और slow task के लिए cache layer में data को filesystem और key-value store की तरह इस्तेमाल की गई DB table, दोनों जगह रखते हैं
    DB thundering herd को coordinate करने में मदद करता है, उसी server से होने वाले read केवल filesystem को hit करते हैं, और दूसरे server से होने वाले read पहले DB को एक बार देखते हैं, फिर filesystem में बनाए रखते हैं
    filesystem layer को memcached से बदला जा सकता है, लेकिन अभी तक यह बहुत अच्छी तरह काम कर रहा है

    • 2000 के दशक के आखिर में Memcachedb (memcache + persistence के लिए bdb) के साथ काम करने के बाद मैं लगभग इसी निष्कर्ष पर पहुँचा था
      Redis में निश्चित रूप से ज़्यादा features थे, और antirez भी आकर्षक तथा हैरान कर देने वाले स्तर तक विनम्र व्यक्ति थे, इसलिए Redis के ज़्यादा लोकप्रिय होने की वजह समझ में आती है
      फिर भी मेरे लिए memcached हमेशा उबाऊ तकनीक चुनो का सबसे बेहतरीन उदाहरण रहा है
      platform engineer के रूप में मैं दोनों को support कर सकता हूँ, लेकिन जब developer Redis के advanced feature जैसे persistence, replication, clustering इस्तेमाल करने लगते हैं, तो मैं यह सुनिश्चित करना चाहता हूँ कि वे उस फैसले के downsides सच में समझते हों
    • DB table को key-value store की तरह इस्तेमाल करके और साथ में filesystem जोड़कर भी, dedicated cache store सेटअप करने की लागत उठाने से पहले बहुत कुछ किया जा सकता है
      हर बार जब मैंने ऐसा समाधान सुझाया, मुझे अनगिनत बार ऐसे अनुभवहीन लोगों और engineering माहौल में काम करने वालों से भिड़ना पड़ा जिन्हें लगता था कि cache ज़रूर किसी dedicated store में ही होना चाहिए
  • memcache होने भर से इन समस्याओं से बचाव बिल्कुल नहीं हो जाता
    2000 के दशक के मध्य में मैंने memcache इस्तेमाल करने वाले एक scalable system पर काम किया था, और developers ठीक उन्हीं जालों में फँसे थे जिनका लेख में Redis के उदाहरण से ज़िक्र है
    उन्होंने memcache के सहारे distributed system के नियमों को bypass करने की कोशिश की, और cache addiction के कारण server fleet का आकार इस धारणा पर तय किया कि memcache हमेशा up रहेगा; जैसे ही outage हुआ, सब कुछ अचानक DDoS जैसा फट पड़ा
    जब कोई host high-TPS key को evict कर देता था, तो दूसरे सभी host उस key को फिर से भरने के लिए dependent service पर टूट पड़ते थे; यानी write amplification होता था, hot key से hot host बनते थे, और memcached को service daemon के साथ चलाने से रहस्यमय CPU spike भी आते थे
    पुराने DNS entry के चिपके रहने के कारण memcache calls blackhole में भी चली जाती थीं
    ये सब memcache को बेहतर तरीके से इस्तेमाल करके टाला जा सकता था, लेकिन इसके दुरुपयोग का लालच बहुत ज़्यादा था

  • लेखक ने Redis/Valkey के जिन मुद्दों का ज़िक्र किया, उनमें से लगभग सभी मैंने production में देखे हैं
    Valkey में memory policy न होने के कारण उसने पूरी memory खा ली और append-only file write error पैदा कर दिया; ऐसे मामले भी हुए जहाँ disk पूरी भर गई और AOF write fail हो गया
    Redis के जीवित, चल रहे, और सारे user data से भरे होने की पूरी अपेक्षा रखते हुए, slow path पर लौटने का कोई fallback न होने की वजह से 500 error भी देखे
    sorted set और दूसरे data structure को रचनात्मक ढंग से इस्तेमाल करते हुए, इस बात पर निर्भर रहना भी देखा कि वह set कभी evict नहीं होगा
    इन सब field observations के बावजूद Redis से पहले memcache की सिफारिश करना अब भी मुश्किल लगता है
    app को memcache-friendly cache layout के साथ design करना पेचीदा हो सकता है, और अगर कोई काफ़ी बड़ी team memcache इस्तेमाल करती है, तो बहुत संभव है कि वह अंततः Redis की ज़रूरत तक पहुँचने का रास्ता खोज ले
    तब आपको 2 cache technologies maintain करनी पड़ती हैं

    • अगर कोई Redis को cache के अलावा किसी और काम के लिए इस्तेमाल करने का फैसला करता है, तो असल में उसके पास 2 cache technologies होती हैं
      cache के लिए configured Redis instance को किसी और मकसद के लिए इस्तेमाल नहीं किया जा सकता, cache instance में eviction होना चाहिए, और non-cache instance में eviction नहीं होना चाहिए
      आखिरकार अलग configuration वाला दूसरा Redis चाहिए ही होगा
      सच कहूँ तो app को memcache-friendly cache layout के लिए design करना, Redis-friendly cache layout के लिए design करने जैसा ही है
      इस तरह के application cache pattern एक जैसे होते हैं: fetch करो, नहीं मिले तो calculate करके set करो
    • अगर पहले से नहीं है, तो मैं एक abstraction interface बनाऊँगा, जिसमें key माँगते समय cache miss होने पर source से value लाने वाला async function या lambda पास किया जाए
      var value = cache.lookup( keyname, () => db.query(...), TimeSpan.FromMinutes(5) // or CacheOptions );
      इससे cache miss होने पर तुरंत fallback path पर जाया जा सकता है या insertion किया जा सकता है
    • 2 cache technologies maintain न करना, यह तर्क लगभग हमेशा जीतता है
  • memcache की एक और कम चर्चित विशेषता यह है कि इसके सभी operation design के अनुसार O(1) होते हैं
    यह authors द्वारा जानबूझकर चुना गया design है, इसलिए constraints तो हैं, लेकिन यह गारंटी देता है कि simple operation के दौरान सिस्टम अचानक randomly नहीं अटकेगा
    दूसरी ओर Redis का core design single-threaded है, इसलिए वह मनमानी complexity वाले operation चला सकता है; developer के नज़रिए से यह इस्तेमाल करते समय स्मार्ट महसूस हो सकता है, लेकिन जब तक वह operation पूरा नहीं होता, बाकी सबको इंतज़ार करना पड़ता है

  • open source प्रोजेक्ट्स या लंबे समय तक मेंटेन किए जाने वाले प्रोग्रामों में ऐसा अक्सर होता है
    जब codebase बड़ा हो जाता है, तो वह आखिरकार उन चीज़ों को भी support करना शुरू कर देता है जो मूल योजना में नहीं थीं
    features बढ़ते हैं तो users भी बढ़ते हैं; कोई पुरानी features ही इस्तेमाल करता है, कोई नई features अपनाता है, और आखिर में कोई खास value de facto default बन जाती है, इसलिए वह अब विकल्प जैसी दिखती ही नहीं
    Redis को उदाहरण लें, तो AOF बंद करने पर वह volatile in-memory cache की तरह काम करता है, लेकिन ज़्यादातर लोग उसे ऐसे सोचते भी नहीं हैं
    इसलिए यह तर्क आता है कि कम features और ज़्यादा simplicity बेहतर है, और इस संदर्भ में Memcached उस straitjacket approach का उदाहरण है
    बड़ी teams के लिए यह पूरी तरह समझ में आता है, लेकिन open source projects को funding या contributions लगातार मिलते रहने के लिए नियमित updates चाहिए, इसलिए इसमें एक अंतर्निहित तनाव रहता है
    कभी-कभी इसका परिणाम किसी niche क्षेत्र में विशेषज्ञता रखने वाले fork या derivative project के रूप में निकलता है
    मेरी राय में इसका कोई एक सही जवाब नहीं है; यह context पर निर्भर करता है
    क्योंकि communication भी मुफ़्त नहीं होती

    • यही कि communication मुफ़्त नहीं है, microservices के बारे में मेरी समस्या है
      लगता है developers को इसका बिल्कुल एहसास ही नहीं है
    • सबसे साफ़ उदाहरण यह है कि लोग सोचते हैं Redis सिर्फ़ ऐसा cache है जो crash या shutdown पर data खो देता है
      मेरा मानना है कि ऐसा इसलिए है क्योंकि उन्होंने Memcached को Redis से replace किया और उसी behavior की उम्मीद की
    • बड़े scale पर AOF failures का कारण बनता है, इसलिए लोग उसे बंद कर देते हैं
      फिर भी यह एक शानदार cache है
  • पिछले कुछ वर्षों में मैंने Flask पर काफ़ी काम किया है, और full-time नहीं सही, लेकिन इसे एक छोटे e-commerce business के tech stack के हिस्से के रूप में इस्तेमाल किया है
    MongoEngine, SQLAlchemy, Celery, और Google/eBay/Shopify के लिए Python stack में मुझे तरह-तरह की landmines और अजीब समस्याएँ मिलीं, लेकिन Redis में ऐसा कभी नहीं हुआ
    शायद इसलिए कि मैंने Redis को persistent store समझने वाले किसी भी व्यक्ति को admin access नहीं दिया, लेकिन ईमानदारी से कहूँ तो मैं Redis को बेहद मज़बूत और अच्छी तरह डिज़ाइन की गई तकनीक कहूँगा
    इसका API बेहद सरल है, और जब भी आपको कुछ थोड़ा अजीब करना होता है, उसके लिए कोई न कोई reasonable और अच्छी तरह सोचा गया तरीका मौजूद होता है

    • मैं अभी Flask, SQLAlchemy और Celery के साथ एक project शुरू कर रहा हूँ, इसलिए मैं और सुनना चाहूँगा कि Celery से क्यों बचना चाहिए और उसकी जगह क्या इस्तेमाल करना चाहिए
    • मेरी दुनिया में memcached और Redis जैसे cache systems बस put-and-get cache हैं
      tagging जैसी invalidation system का इस्तेमाल किया जा सकता है
      लेकिन data cache करने के अलावा लोग cache के साथ और कौन-सी अजीब चीज़ें करते हैं, यह जानने की मुझे सच में जिज्ञासा है
  • मुझे memcached पसंद है, लेकिन अगर Redis को volatile cache की तरह configure किया गया है और लोग उसे persistent data store की तरह treat कर रहे हैं, तो यह Redis की गलती नहीं है
    memcached भी persistent नहीं है, इसलिए यह तुलना खास तौर पर अजीब लगती है

    • बहुत-सी कंपनियों में, शायद ज़्यादातर में, Redis को ऐसा cache नहीं माना जाता जो कभी भी गायब हो सकता है, बल्कि एक असली durable production database समझकर वैसे ही चलाया जाता है
      अगर अलग से न बताया जाए, तो नए developer का ऐसा मान लेना भी अनुचित नहीं है
  • Memcached अपने लॉन्च के समय caching का उद्धारक था
    यह बात भी अच्छी लगती है कि इसे 2003 में Brad Fitzpatrick ने LiveJournal के लिए बनाया था
    user feed की हर post पर access restrictions अलग हो सकती थीं, और इसी वजह से posts या पूरे pages को cache किया जा सकता था
    मैंने इसे Ruby on Rails के साथ कई वर्षों तक इस्तेमाल किया, pages तेज़ हो गए, और यह बस ठीक से काम करता था
    इसकी कमी, और speed के लिहाज़ से इसकी ताकत, यह थी कि cache disk पर नहीं बल्कि memory में store होता था
    अगर cache किया जाने वाला data बहुत बड़ा हो और site बड़े scale की हो, तो hosting cost महँगी पड़ सकती है
    ऐसे मामलों में Solid Cache मेरे लिए उद्धारक रहा
    जिस project पर मैं अभी काम कर रहा हूँ, उसमें 100GB से ज़्यादा cache है, जो PostgreSQL disk पर store होता है, index की मदद से तेज़ी से lookup होता है, और Rails expiry को अपने आप handle करके उस row को हटा देता है
    अगर cache का आकार छोटा हो और आप पहले से Redis इस्तेमाल कर रहे हों, तो शायद मैं बस Redis ही इस्तेमाल करूँगा
    लेकिन अगर speed पहली प्राथमिकता हो, तो मैं Memcached और Redis का benchmark करूँगा

  • memcached का ephemeral होना और लोग उसे persistent चीज़ की तरह इस्तेमाल करेंगे या नहीं, ये दो अलग बातें हैं
    अगर cache hit rate 99.9% जैसा दिखे और वह हमेशा मौजूद लगे, तो देर-सबेर कोई न कोई उस behavior पर निर्भर code लिख ही देगा
    मुझे लगता है कि development mode में client library शायद 10% बार null लौटाने में मदद कर सकती है

  • memcached साधारण key-value cache कामों में Redis से हास्यास्पद रूप से तेज़ है
    इसमें threads हैं, और इसे एक काम बहुत अच्छी तरह करने के लिए बेहद optimize किया गया है
    दूसरी ओर Redis ज़्यादा किसी shared Python heap जैसा लगता है, जिसमें हर तरह के data structures हैं और single-threaded वगैरह है
    Notion में Redis कई कामों के लिए इस्तेमाल होता है, लेकिन असली caching memcached पर छोड़ी जाती है

    • आप देख सकते हैं कि key-value में यह इतना भी तेज़ नहीं है
      औसतन 300 microseconds बनाम 350 microseconds प्रति read जैसा कुछ है
      single-threaded होना भी इतना मायने नहीं रखता, क्योंकि bottleneck CPU नहीं बल्कि responsive I/O है
    • threads मुफ़्त नहीं आते
      वे आपको ज़्यादा CPU cores इस्तेमाल करने देते हैं, लेकिन अगर load बहुत ज़्यादा न हो, तो single-threaded memcached multi-threaded की तुलना में कम CPU इस्तेमाल करता है