पायथन एप्लिकेशन लिखते समय, कैशिंग महत्वपूर्ण है। डेटा की पुनर्गणना से बचने के लिए या धीमे डेटाबेस तक पहुँचने से बचने के लिए कैशे का उपयोग करने से आपको शानदार प्रदर्शन को बढ़ावा मिल सकता है।
पायथन कैशिंग के लिए एक सरल शब्दकोश से लेकर अधिक संपूर्ण डेटा संरचना जैसे functools.lru_cache
तक अंतर्निहित संभावनाएं प्रदान करता है। . बाद वाला कैश आकार को सीमित करने के लिए कम से कम हाल ही में उपयोग किए गए एल्गोरिदम का उपयोग करके किसी भी आइटम को कैश कर सकता है।
हालांकि, वे डेटा संरचनाएं स्थानीय . परिभाषा के अनुसार हैं आपकी पायथन प्रक्रिया के लिए। जब आपके एप्लिकेशन की कई प्रतियां एक बड़े प्लेटफॉर्म पर चलती हैं, तो इन-मेमोरी डेटा संरचना का उपयोग करके कैश्ड सामग्री को साझा करने की अनुमति नहीं दी जाती है। यह बड़े पैमाने पर और वितरित अनुप्रयोगों के लिए एक समस्या हो सकती है।
इसलिए, जब एक सिस्टम को पूरे नेटवर्क में वितरित किया जाता है, तो उसे एक कैश की भी आवश्यकता होती है जो पूरे नेटवर्क में वितरित किया जाता है। आजकल, बहुत सारे नेटवर्क सर्वर हैं जो कैशिंग क्षमता प्रदान करते हैं—हमने पहले ही कवर कर लिया है कि Django के साथ कैशिंग के लिए Redis का उपयोग कैसे करें।
जैसा कि आप इस ट्यूटोरियल में देखेंगे, वितरित कैशिंग के लिए memcached एक और बढ़िया विकल्प है। बुनियादी मेमकैच्ड उपयोग के लिए एक त्वरित परिचय के बाद, आप "कैश और सेट" जैसे उन्नत पैटर्न और कोल्ड कैश प्रदर्शन समस्याओं से बचने के लिए फ़ॉलबैक कैश का उपयोग करने के बारे में जानेंगे।
मेमकैच्ड इंस्टाल करना
मेमकैश्ड कई प्लेटफार्मों के लिए उपलब्ध है:
- यदि आप लिनक्स चलाते हैं , आप इसे
apt-get install memcached
. का उपयोग करके इंस्टॉल कर सकते हैं याyum install memcached
. यह एक पूर्व-निर्मित पैकेज से memcached स्थापित करेगा लेकिन आप स्रोत से memcached भी बना सकते हैं, जैसा कि यहां बताया गया है। - macOS के लिए , Homebrew का उपयोग करना सबसे सरल विकल्प है। बस
brew install memcached
चलाएं Homebrew पैकेज मैनेजर स्थापित करने के बाद। - Windows . पर , आपको स्वयं memcached को संकलित करना होगा या पूर्व-संकलित बायनेरिज़ को खोजना होगा।
एक बार इंस्टाल हो जाने पर, memcached बस memcached
. पर कॉल करके लॉन्च किया जा सकता है आदेश:
$ memcached
इससे पहले कि आप Python-land से memcached के साथ बातचीत कर सकें, आपको एक memcached क्लाइंट इंस्टॉल करना होगा पुस्तकालय। कुछ बुनियादी कैश एक्सेस संचालनों के साथ, आप अगले भाग में इसे कैसे करें, यह देखेंगे।
पायथन का उपयोग करके कैश्ड मानों को संग्रहीत करना और पुनर्प्राप्त करना
यदि आपने कभी भी memcached . का उपयोग नहीं किया है , इसे समझना काफी आसान है। यह मूल रूप से एक विशाल नेटवर्क-उपलब्ध शब्दकोश प्रदान करता है। इस शब्दकोश में कुछ गुण हैं जो शास्त्रीय पायथन शब्दकोश से भिन्न हैं, मुख्यतः:
- कुंजी और मान बाइट होने चाहिए
- कुंजी और मान समाप्ति समय के बाद स्वचालित रूप से हटा दिए जाते हैं
इसलिए, memcached . के साथ इंटरैक्ट करने के लिए दो बुनियादी ऑपरेशन set
हैं और get
. जैसा कि आपने अनुमान लगाया होगा, उनका उपयोग क्रमशः किसी कुंजी को मान निर्दिष्ट करने या किसी कुंजी से मान प्राप्त करने के लिए किया जाता है।
memcached . के साथ इंटरैक्ट करने के लिए मेरी पसंदीदा पायथन लाइब्रेरी pymemcache
है - मैं इसका इस्तेमाल करने की सलाह देता हूं। आप बस इसे पाइप का उपयोग करके स्थापित कर सकते हैं:
$ pip install pymemcache
निम्न कोड दिखाता है कि आप memcached . से कैसे जुड़ सकते हैं और इसे अपने पायथन अनुप्रयोगों में नेटवर्क-वितरित कैश के रूप में उपयोग करें:
>>> from pymemcache.client import base
# Don't forget to run `memcached' before running this next line:
>>> client = base.Client(('localhost', 11211))
# Once the client is instantiated, you can access the cache:
>>> client.set('some_key', 'some value')
# Retrieve previously set data again:
>>> client.get('some_key')
'some value'
मेमकैश्ड नेटवर्क प्रोटोकॉल वास्तव में सरल है और इसका कार्यान्वयन बहुत तेज़ है, जो डेटा को संग्रहीत करने के लिए उपयोगी बनाता है जो अन्यथा डेटा के विहित स्रोत से पुनर्प्राप्त करने या फिर से गणना करने के लिए धीमा होगा:
हालांकि यह काफी सरल है, यह उदाहरण पूरे नेटवर्क में कुंजी/मूल्य टुपल्स को संग्रहीत करने और आपके एप्लिकेशन की कई, वितरित, चल रही प्रतियों के माध्यम से उन तक पहुंचने की अनुमति देता है। यह सरल है, फिर भी शक्तिशाली है। और यह आपके एप्लिकेशन को अनुकूलित करने की दिशा में एक बेहतरीन पहला कदम है।
कैश्ड डेटा अपने आप समाप्त हो रहा है
memcached . में डेटा संग्रहीत करते समय , आप समाप्ति समय सेट कर सकते हैं—memcached . के लिए अधिकतम सेकंड कुंजी और मूल्य को चारों ओर रखने के लिए। उस देरी के बाद, memcached अपने कैश से कुंजी को स्वचालित रूप से हटा देता है।
आपको इस कैशे समय को किस पर सेट करना चाहिए? इस देरी के लिए कोई जादुई संख्या नहीं है, और यह पूरी तरह से उस डेटा और एप्लिकेशन के प्रकार पर निर्भर करेगा जिसके साथ आप काम कर रहे हैं। यह कुछ सेकंड हो सकता है, या यह कुछ घंटे हो सकता है।
कैश अमान्यकरण , जो परिभाषित करता है कि कैश को कब निकालना है क्योंकि यह वर्तमान डेटा के साथ सिंक से बाहर है, यह भी कुछ ऐसा है जिसे आपके एप्लिकेशन को संभालना होगा। विशेष रूप से यदि डेटा प्रस्तुत किया जा रहा है जो बहुत पुराना है या बासी . है बचना है।
यहाँ फिर से, कोई जादुई नुस्खा नहीं है; यह आपके द्वारा बनाए जा रहे एप्लिकेशन के प्रकार पर निर्भर करता है। हालांकि, ऐसे कई मामले हैं, जिन पर ध्यान दिया जाना चाहिए—जिन्हें हमने अभी तक उपरोक्त उदाहरण में शामिल नहीं किया है।
एक कैशिंग सर्वर असीमित रूप से विकसित नहीं हो सकता-स्मृति एक सीमित संसाधन है। इसलिए, जैसे ही कैशिंग सर्वर को अन्य चीजों को स्टोर करने के लिए अधिक स्थान की आवश्यकता होगी, कुंजी को फ्लश कर दिया जाएगा।
कुछ कुंजियों की समय-सीमा भी समाप्त हो सकती है क्योंकि वे अपने समाप्ति समय (जिसे कभी-कभी "टाइम-टू-लाइव" या टीटीएल भी कहा जाता है) तक पहुंच जाती है। उन मामलों में डेटा खो जाता है, और विहित डेटा स्रोत को फिर से पूछताछ की जानी चाहिए।
यह वास्तव में जितना जटिल है उससे कहीं अधिक जटिल लगता है। पायथन में मेम्केड के साथ काम करते समय आप आम तौर पर निम्नलिखित पैटर्न के साथ काम कर सकते हैं:
from pymemcache.client import base
def do_some_query():
# Replace with actual querying code to a database,
# a remote REST API, etc.
return 42
# Don't forget to run `memcached' before running this code
client = base.Client(('localhost', 11211))
result = client.get('some_key')
if result is None:
# The cache is empty, need to get the value
# from the canonical source:
result = do_some_query()
# Cache the result for next time:
client.set('some_key', result)
# Whether we needed to update the cache or not,
# at this point you can work with the data
# stored in the `result` variable:
print(result)
<ब्लॉकक्वॉट> नोट: सामान्य फ्लश-आउट संचालन के कारण गुम चाबियों को संभालना अनिवार्य है। कोल्ड कैश परिदृश्य को संभालना भी अनिवार्य है, अर्थात जब memcached अभी शुरू किया गया है। उस स्थिति में, कैश पूरी तरह से खाली हो जाएगा और कैश को पूरी तरह से फिर से भरना होगा, एक बार में एक अनुरोध।
इसका मतलब है कि आपको किसी भी संचित डेटा को अल्पकालिक के रूप में देखना चाहिए। और आपको कभी भी यह उम्मीद नहीं करनी चाहिए कि कैश में वह मान होगा जिसे आपने पहले लिखा था।
कोल्ड कैशे को गर्म करना
कुछ कोल्ड कैश परिदृश्यों को रोका नहीं जा सकता, उदाहरण के लिए एक memcached टकरा जाना। लेकिन कुछ, उदाहरण के लिए, एक नए memcached . में माइग्रेट कर सकते हैं सर्वर।
जब यह भविष्यवाणी करना संभव है कि एक ठंडा कैश परिदृश्य होगा, तो इससे बचना बेहतर है। एक कैश जिसे फिर से भरने की आवश्यकता होती है, इसका मतलब है कि अचानक, कैश किए गए डेटा के कैननिकल स्टोरेज को उन सभी कैश उपयोगकर्ताओं द्वारा बड़े पैमाने पर प्रभावित किया जाएगा जिनके पास कैश डेटा की कमी है (जिसे थंडरिंग हर्ड समस्या भी कहा जाता है।)
पायमेमकेश FallbackClient
. नामक एक वर्ग प्रदान करता है जो इस परिदृश्य को लागू करने में मदद करता है जैसा कि यहां दिखाया गया है:
from pymemcache.client import base
from pymemcache import fallback
def do_some_query():
# Replace with actual querying code to a database,
# a remote REST API, etc.
return 42
# Set `ignore_exc=True` so it is possible to shut down
# the old cache before removing its usage from
# the program, if ever necessary.
old_cache = base.Client(('localhost', 11211), ignore_exc=True)
new_cache = base.Client(('localhost', 11212))
client = fallback.FallbackClient((new_cache, old_cache))
result = client.get('some_key')
if result is None:
# The cache is empty, need to get the value
# from the canonical source:
result = do_some_query()
# Cache the result for next time:
client.set('some_key', result)
print(result)
FallbackClient
ऑर्डर का सम्मान करते हुए, पुराने कैश को उसके कंस्ट्रक्टर को दिया गया। इस मामले में, नया कैश सर्वर हमेशा पहले पूछताछ करेगा, और कैश मिस के मामले में, पुराने को पूछताछ की जाएगी-डेटा के प्राथमिक स्रोत पर संभावित वापसी-यात्रा से बचने के लिए।
यदि कोई कुंजी सेट है, तो यह केवल नए कैश पर सेट की जाएगी। कुछ समय बाद, पुराने कैश को निष्क्रिय किया जा सकता है और FallbackClient
new_cache
. से निर्देशित बदला जा सकता है ग्राहक।
जांचें और सेट करें
रिमोट कैश के साथ संचार करते समय, सामान्य समवर्ती समस्या वापस आती है:एक ही समय में एक ही कुंजी तक पहुंचने का प्रयास करने वाले कई क्लाइंट हो सकते हैं। मेमकैश्ड एक चेक और सेट प्रदान करता है ऑपरेशन, छोटा कर दिया गया CAS , जो इस समस्या को हल करने में मदद करता है।
सबसे सरल उदाहरण एक ऐसा एप्लिकेशन है जो अपने उपयोगकर्ताओं की संख्या गिनना चाहता है। हर बार जब कोई विज़िटर कनेक्ट होता है, तो काउंटर 1 से बढ़ जाता है। memcached . का उपयोग करना , एक सरल कार्यान्वयन होगा:
def on_visit(client):
result = client.get('visitors')
if result is None:
result = 1
else:
result += 1
client.set('visitors', result)
हालांकि, क्या होता है यदि एप्लिकेशन के दो उदाहरण एक ही समय में इस काउंटर को अपडेट करने का प्रयास करते हैं?
पहला कॉल client.get('visitors')
उन दोनों के लिए आगंतुकों की समान संख्या लौटाएगा, मान लें कि यह 42 है। फिर दोनों 1 जोड़ेंगे, 43 की गणना करेंगे, और आगंतुकों की संख्या 43 पर सेट करेंगे। वह संख्या गलत है, और परिणाम 44 होना चाहिए, अर्थात 42 + 1 + 1.
इस समवर्ती समस्या को हल करने के लिए, memcached . का CAS संचालन आसान है। निम्नलिखित स्निपेट एक सही समाधान लागू करता है:
def on_visit(client):
while True:
result, cas = client.gets('visitors')
if result is None:
result = 1
else:
result += 1
if client.cas('visitors', result, cas):
break
gets
विधि मान लौटाती है, ठीक वैसे ही जैसे get
विधि, लेकिन यह एक CAS मान . भी देता है .
इस मान में जो है वह प्रासंगिक नहीं है, लेकिन इसका उपयोग अगली विधि के लिए किया जाता है cas
बुलाना। यह विधि set
. के बराबर है ऑपरेशन, सिवाय इसके कि यह विफल हो जाता है यदि gets
कार्यवाही। सफलता के मामले में, लूप टूट जाता है। अन्यथा, ऑपरेशन शुरुआत से ही फिर से शुरू हो जाता है।
उस परिदृश्य में जहां एप्लिकेशन के दो उदाहरण एक ही समय में काउंटर को अपडेट करने का प्रयास करते हैं, केवल एक काउंटर को 42 से 43 तक ले जाने में सफल होता है। दूसरे इंस्टेंस को False
मिलता है client.cas
. द्वारा लौटाया गया मान कॉल करें, और लूप को पुनः प्रयास करना होगा। यह इस बार मूल्य के रूप में 43 को पुनः प्राप्त करेगा, इसे 44 तक बढ़ा देगा, और इसका cas
कॉल सफल होगी, इस प्रकार हमारी समस्या का समाधान होगा।
एक काउंटर को बढ़ाना एक उदाहरण के रूप में दिलचस्प है, यह समझाने के लिए कि कैस कैसे काम करता है क्योंकि यह सरल है। हालांकि, memcached incr
. भी प्रदान करता है और decr
एक से अधिक gets
करने के बजाय, एक अनुरोध में एक पूर्णांक को बढ़ाने या घटाने के तरीके /cas
कॉल। वास्तविक दुनिया के अनुप्रयोगों में gets
और cas
अधिक जटिल डेटा प्रकार या संचालन के लिए उपयोग किया जाता है
अधिकांश दूरस्थ कैशिंग सर्वर और डेटा स्टोर समवर्ती मुद्दों को रोकने के लिए ऐसा तंत्र प्रदान करते हैं। उन मामलों के बारे में उनकी सुविधाओं का उचित उपयोग करने के लिए जागरूक होना महत्वपूर्ण है।
कैशिंग से परे
इस लेख में वर्णित सरल तकनीकों ने आपको दिखाया है कि memcached . का लाभ उठाना कितना आसान है अपने पायथन एप्लिकेशन के प्रदर्शन को तेज करने के लिए।
बस दो बुनियादी "सेट" और "प्राप्त" संचालन का उपयोग करके आप अक्सर डेटा पुनर्प्राप्ति में तेजी ला सकते हैं या बार-बार परिणामों की पुन:गणना करने से बच सकते हैं। Memcached के साथ आप कैश को बड़ी संख्या में वितरित नोड्स में साझा कर सकते हैं।
अन्य, अधिक उन्नत पैटर्न जो आपने इस ट्यूटोरियल में देखे, जैसे चेक एंड सेट (CAS) ऑपरेशन आपको डेटा भ्रष्टाचार से बचने के दौरान कैश में संग्रहीत डेटा को एक साथ कई पायथन थ्रेड्स या प्रक्रियाओं में अपडेट करने की अनुमति देता है।
यदि आप तेज़ और अधिक स्केलेबल पायथन एप्लिकेशन लिखने के लिए उन्नत तकनीकों के बारे में अधिक जानने में रुचि रखते हैं, तो स्केलिंग पायथन देखें। इसमें नेटवर्क वितरण, कतार प्रणाली, वितरित हैशिंग और कोड प्रोफाइलिंग जैसे कई उन्नत विषय शामिल हैं।