मुझे संदेह है कि रेडिस के सीपीयू उपयोग को अधिकतम करने से आपके बैकएंड डिज़ाइन को लाभ होगा। सही सवाल यह है कि क्या रेडिस किसी निश्चित विलंबता पर आपके थ्रूपुट को बनाए रखने के लिए पर्याप्त कुशल है। Redis एक सिंगल-थ्रेडेड सर्वर है:80% CPU खपत पर, विलंबता बहुत खराब हो सकती है।
मेरा सुझाव है कि आप विलंबता को मापें जबकि रेडिस-बेंचमार्क यह देखने के लिए काम कर रहा है कि क्या यह रेडिस सीपीयू खपत को बढ़ाने की कोशिश करने से पहले आपकी आवश्यकताओं के लिए स्वीकार्य है। इसके लिए रेडिस-क्ली के --लेटेंसी विकल्प का उपयोग किया जा सकता है:
- रेडिस-सर्वर लॉन्च करें
- redis-cli --latency आज़माएं, औसत मान नोट करें, इसे रोकें
- किसी अन्य विंडो में, बेंचमार्क प्रारंभ करें, और सुनिश्चित करें कि यह कुछ समय तक चलता है
- redis-cli --latency आज़माएं, औसत मान नोट करें, इसे रोकें
- बेंचमार्क बंद करें
- दो औसत मानों की तुलना करें
अब, यदि आप वास्तव में Redis CPU खपत को बढ़ाना चाहते हैं, तो आपको या तो एक कुशल क्लाइंट प्रोग्राम (जैसे redis-benchmark) की आवश्यकता होगी, जो एक साथ कई कनेक्शनों को संभालने में सक्षम हो, या तो आपके क्लाइंट प्रोग्राम के कई उदाहरण।
लुआ एक तेजी से व्याख्या की जाने वाली भाषा है, लेकिन यह अभी भी एक व्याख्या की गई भाषा है। यह सी कोड की तुलना में धीमी परिमाण के एक या दो आदेश होंगे। रेडिस, लुआ-रेडिस की तुलना में अपने प्रोटोकॉल को पार्स/जनरेट करने में बहुत तेज है, इसलिए आप रेडिस को एक अद्वितीय लुआ क्लाइंट के साथ संतृप्त करने में सक्षम नहीं होंगे (सिवाय इसके कि आप ओ (एन) रेडिस कमांड का उपयोग करते हैं - बाद में देखें)।
वेबडिस को एक कुशल क्लाइंट लाइब्रेरी के साथ सी में कार्यान्वित किया जाता है, लेकिन http/json प्रोटोकॉल को पार्स करना पड़ता है जो रेडिस प्रोटोकॉल की तुलना में अधिक वर्बोज़ और जटिल होते हैं। यह संभवतः अधिकांश कार्यों के लिए रेडिस की तुलना में अधिक सीपीयू की खपत करता है। तो फिर, आप एक वेबडिस इंस्टेंस के साथ रेडिस को संतृप्त नहीं करेंगे।
कई Lua क्लाइंट के साथ Redis को संतृप्त करने के लिए यहां कुछ उदाहरण दिए गए हैं।
यदि यह पहले से नहीं किया गया है, तो मेरा सुझाव है कि आप पहले रेडिस बेंचमार्क पृष्ठ देखें।
यदि आप अपना बेंचमार्क उसी बॉक्स पर चलाते हैं जिस पर Redis:
मुख्य बिंदु रेडिस को एक कोर समर्पित करना है, और क्लाइंट प्रोग्राम को अन्य कोर पर चलाना है। लिनक्स पर, आप इसके लिए टास्कसेट कमांड का उपयोग कर सकते हैं।
# Start Redis on core 0
taskset -c 0 redis-server redis.conf
# Start Lua programs on the other cores
for x in `seq 1 10` ; do taskset -c 1,2,3 luajit example.lua & done
लुआ कार्यक्रम को थ्रूपुट को अधिकतम करने और सिस्टम गतिविधि को कम करने के लिए पाइपलाइनिंग का उपयोग करना चाहिए।
local redis = require 'redis'
local client = redis.connect('127.0.0.1', 6379)
for i=1,1000000 do
local replies = client:pipeline(function(p)
for j=1,1000 do
local key = 'counter:'..tostring(j)
p:incrby(key,1)
end
end)
end
मेरे सिस्टम पर, लुआ प्रोग्राम रेडिस के सीपीयू से 4 गुना अधिक लेता है, इसलिए आपको इस विधि के साथ रेडिस को संतृप्त करने के लिए 4 कोर से अधिक की आवश्यकता है (6 कोर बॉक्स ठीक होना चाहिए)।
यदि आप अपना बेंचमार्क Redis से भिन्न बॉक्स पर चलाते हैं:
सिवाय अगर आप सीपीयू भूखे आभासी मशीनों पर चलते हैं, तो उस स्थिति में बाधा नेटवर्क की संभावना होगी। मुझे नहीं लगता कि आप 1 GbE लिंक से कम किसी भी चीज़ से Redis को संतृप्त कर सकते हैं।
नेटवर्क विलंबता बाधा से बचने के लिए, और सीपीयू (ईथरनेट पैकेट भरने) पर नेटवर्क इंटरप्ट की लागत को कम करने के लिए जहां तक आप कर सकते हैं (पिछला लुआ प्रोग्राम देखें) अपने प्रश्नों को पाइपलाइन करना सुनिश्चित करें। रेडिस को एक ऐसे कोर पर चलाने का प्रयास करें जो नेटवर्क कार्ड के लिए बाध्य नहीं है (और नेटवर्क इंटरप्ट को संसाधित करता है)। इस अंतिम बिंदु को जांचने के लिए आप htop जैसे टूल का उपयोग कर सकते हैं।
यदि आप कर सकते हैं तो नेटवर्क की विभिन्न अन्य मशीनों पर अपने लुआ क्लाइंट को चलाने का प्रयास करें। रेडिस को संतृप्त करने के लिए आपको फिर से लुआ ग्राहकों की एक अच्छी संख्या की आवश्यकता होगी (6-10 ठीक होना चाहिए)।
कुछ मामलों में, एक अद्वितीय Lua प्रक्रिया पर्याप्त होती है:
अब, यदि प्रत्येक क्वेरी काफी महंगी है, तो रेडिस को एकल लुआ क्लाइंट के साथ संतृप्त करना संभव है। यहां एक उदाहरण दिया गया है:
local redis = require 'redis'
local client = redis.connect('127.0.0.1', 6379)
for i=1,1000 do
local replies = client:pipeline(function(p)
for j=1,1000 do
p:rpush("toto",i*1000+j)
end
end)
end
N = 500000
for i=1,100000 do
local replies = client:pipeline(function(p)
for j=1,10 do
p:lrange("toto",N, N+10)
end
end)
end
यह प्रोग्राम 1M आइटम के साथ एक सूची को पॉप्युलेट करता है, और फिर सूची के बीच से 10 आइटम लाने के लिए lrange कमांड का उपयोग करता है (Redis के लिए सबसे खराब स्थिति)। इसलिए हर बार जब कोई क्वेरी निष्पादित की जाती है, तो सर्वर द्वारा 500K आइटम स्कैन किए जाते हैं। क्योंकि केवल 10 आइटम लौटाए जाते हैं, वे लुआ-रेडिस द्वारा पार्स करने के लिए तेज़ होते हैं जो सीपीयू का उपभोग नहीं करेंगे। इस स्थिति में, CPU की सारी खपत सर्वर साइड पर होगी।
अंतिम शब्द
रेडिस-लुआ की तुलना में शायद तेज़ रेडिस क्लाइंट हैं:
- https://github.com/agladysh/lua-hiredis (किरायेदारों पर आधारित)
- https://github.com/agladysh/ljffi-hiredis (लूजित एफएफआई का उपयोग करते हुए किराए पर लेने वालों पर आधारित)
आप उन्हें आजमाना चाह सकते हैं।