2012-01-16 10 views
13

एक node.js ऐप में मैं क्यू क्यूइंग लाइब्रेरी का उपयोग कर रहा हूं, जिसे रेडिस द्वारा समर्थित किया जाता है। जब कोई काम पूरा हो जाता है तो मैं इसे कतार से हटा देता हूं। रातोंरात लगभग 70,000 नौकरियां चलाने के बाद रेडिस मेमोरी उपयोग लगभग 30 एमबी है। डेटाबेस में अभी भी 18 असफल नौकरियां थीं, और कतार की लंबाई वर्तमान में शून्य है - कतारों की तुलना में नौकरियों को अधिक तेज़ी से संसाधित किया जाता है। किसी अन्य तरीके से रेडिस का उपयोग नहीं किया जा रहा है।node.js में रेडिस-समर्थित "क्यू" लाइब्रेरी का उपयोग करना - मेरा रेडिस मेमोरी उपयोग क्यों बढ़ता जा रहा है?

कोई विचार क्यों रेडिस मेमोरी उपयोग बढ़ता रहता है भले ही मैं पूर्ण नौकरियों को हटा रहा हूं? Coffeescript कोड:

gaemodel.update = (params) -> 
    job = jobs.create "gaemodel-update", params 
    job.attempts 2 
    job.save() 
    job.on "complete", -> 
    job.remove (err) -> 
     throw err if err 
     console.log 'completed job #%d', job.id 

उत्तर

0

वास्तव में समस्या नोड के पुराने संस्करण के साथ थी। 0.6.x श्रृंखला में अपग्रेडिंग मेम खपत की समस्याएं हल हो गईं।

19

आप एक कतार प्रणाली के साथ एक स्मृति की खपत समस्या होती है और आप 100% सकारात्मक है कि सभी कतारबद्ध आइटम की दुकान से हटा दिया गया है और एक अपवाद/त्रुटि कतार में बैठने नहीं है कर रहे हैं, तो सबसे संभावित कारण यह है कि क्यूइंग दर डेक्यूइंग दर से काफी अधिक है।

रेडिस एक सामान्य उद्देश्य स्मृति आवंटक (जेमलोक, ptmalloc, tcmalloc, आदि ...) का उपयोग करता है। ये आवंटक आवश्यक रूप से स्मृति को सिस्टम को वापस नहीं देते हैं। जब कुछ स्मृति मुक्त हो जाती है, तो आवंटक इसे रखने के लिए रहता है (इसे भविष्य के आवंटन के लिए पुन: उपयोग करने के लिए)। यह विशेष रूप से सच है जब कई छोटी वस्तुओं को यादृच्छिक रूप से आवंटित किया जाता है, जो आम तौर पर रेडिस के मामले में होता है।

परिणाम समय पर किसी दिए गए बिंदु पर स्मृति खपत का एक शिखर है, रेडिस स्मृति को जमा करने और इसे बनाए रखने का कारण बनता है। यह स्मृति खो नहीं जाती है, अगर पुन: उपयोग किया जाएगा तो स्मृति की खपत का एक और शिखर होता है। लेकिन सिस्टम के दृष्टिकोण से, स्मृति अभी भी रेडिस को सौंपा गया है। एक कतार प्रणाली के लिए, यदि आप वस्तुओं को तेज़ी से कतार में डालते हैं, तो आप स्मृति की खपत में ऐसे चरम होंगे।

मेरी सलाह कतार में वस्तुओं की संख्या के विकास की जांच करने के लिए नियमित समय अंतराल पर कतार की लंबाई लाने और लॉग करने के लिए आपके आवेदन को मापना होगा (और चरम मूल्य की पहचान करें)।

अपडेट किया गया:

मैं समझने के लिए यह Redis में संग्रहीत करता है kue साथ कुछ चीजें का परीक्षण किया है। असल में, डेटा संरचना काफी जटिल है (स्ट्रिंग्स, सेट्स, जेसेट्स और हैश का मिश्रण)। आप Redis में देखो, तो आप निम्नलिखित मिलेगा:

q:job:nnn    (hash, job definition and properties) 

q:search:object:nnn (set, metaphone tokens associated to job nnn) 
q:search:word:XXXXX (set, reverse index to support job full-text indexing) 

q:jobs:inactive  (zset, all the unprocessed jobs) 
q:jobs:X:inactive  (zset, all the unprocessed jobs of job type X) 

q:jobs:active   (zset, all the on-going jobs) 
q:jobs:X:active  (zset, all the on-going jobs of job type X) 

q:jobs:complete  (zset, all the completed jobs) 
q:jobs:X:complete  (zset, all the completed jobs of job type X) 

q:jobs:failed   (zset, all the failed jobs) 
q:jobs:X:failed  (zset, all the failed jobs of job type X) 

q:jobs:delayed  (zset, all the delayed jobs) 
q:jobs:X:delayed  (zset, all the delayed jobs of job type X) 

q:job:types   (set, all the job types) 
q:jobs    (zset, all the jobs) 

q:stats:work-time  (string, work time statistic) 
q:ids     (string, job id sequence) 

मैं Coffeescript बिल्कुल पता नहीं है, तो मैं सादे पुराने जावास्क्रिप्ट का उपयोग कर समस्या को पुन: करने की कोशिश की:

var kue = require('kue'), 
    jobs = kue.createQueue(); 

jobs.process('email', function(job,done) { 
    console.log('Processing email '+JSON.stringify(job)) 
    done(); 
}); 

function create_email(i) { 
    var j = jobs.create('email', { 
    title: 'This is email '+i 
    , to: 'didier' 
    , template: 'Bla bla bla' 
    }); 
    j.on('complete', function() { 
    console.log('complete email job #%d', j.id); 
    j.remove(function(err){ 
     if (err) throw err; 
     console.log('removed completed job #%d', j.id); 
    }); 
    }); 
    j.save(); 
} 

for (i=0; i<5; ++i) 
{ 
    create_email(i); 
} 

kue.app.listen(8080); 

मैं इस भाग गया कोड, जाँच क्या प्रसंस्करण के बाद Redis में बने रहे:

redis 127.0.0.1:6379> keys * 
1) "q:ids" 
2) "q:jobs:complete" 
3) "q:jobs:email:complete" 
4) "q:stats:work-time" 
5) "q:job:types" 
redis 127.0.0.1:6379> zrange q:jobs:complete 0 -1 
1) "1" 
2) "2" 
3) "3" 
4) "4" 
5) "5" 

तो यह पूरा लगता नौकरियों क्ष में रखा जाता है: नौकरियों: पूर्ण और q: नौकरियों: एक्स: पूरा नौकरियों के बावजूद हटा दिया गया है। मेरा सुझाव है कि आप अपने खुद के रेडिस उदाहरण में इन zsets की कार्डिनालिटी की जांच करें।

मेरा स्पष्टीकरण इन जेसेट का प्रबंधन के बाद 'पूर्ण' ईवेंट उत्सर्जित होता है। तो नौकरियों को सही ढंग से हटा दिया जाता है, लेकिन उनके आईडी सिर्फ उन zsets में डाले जाते हैं।

प्रति-कार्य कार्यक्रमों पर भरोसा करने से बचने के लिए एक कामकाज है, बल्कि नौकरियों को हटाने के लिए प्रति-पंक्ति कार्यक्रमों का उपयोग करना है।उदाहरण के लिए, निम्न संशोधन किया जा सकता है:

// added this 
jobs.on('job complete', function(id) { 
    console.log('Job complete '+id) 
    kue.Job.get(id, function(err, job) { 
    if (err) return; 
    job.remove(function(err){ 
     if (err) throw err; 
     console.log('removed completed job #%d', job.id); 
    }); 
    }); 
}); 

// updated that 
function create_email(i) { 
    var j = jobs.create('email', { 
    title: 'This is email '+i 
    , to: 'didier' 
    , template: 'Bla bla bla' 
    }); 
    j.save(); 
} 

कार्यक्रम तय करने के बाद, Redis में सामग्री बेहतर है:

redis 127.0.0.1:6379> keys * 
1) "q:stats:work-time" 
2) "q:ids" 
3) "q:job:types" 

आप शायद Coffescript से एक समान रणनीति का उपयोग कर सकते हैं।

+0

हाय डिडिएर - इस उत्तर के लिए धन्यवाद, लेकिन मुझे नहीं लगता कि यह समस्या की पहचान करता है। मुझे यह उल्लेख करना चाहिए था कि कतार की लंबाई शून्य है। इस क्यू लाइब्रेरी के साथ कतार स्थिति की निगरानी करना आसान है - इसमें एक अंतर्निहित व्यवस्थापक सर्वर और फ्रंट एंड शामिल है। मैं इस जानकारी को जोड़ने के लिए अपना प्रश्न संपादित करूंगा। – mainsocial

+0

मैंने तदनुसार अपना जवाब अपडेट किया है। –

+0

डिडिएर - आपकी जांच के लिए धन्यवाद। मैं स्वतंत्र रूप से एक ही निष्कर्ष पर आया था। वास्तव में क्यू कोड में कुछ बग थे जिन्हें मैं ठीक करने में सक्षम था। मैंने अपने कांटे में फिक्स में चेक किया है और पुल अनुरोध किया है। – mainsocial

2

आपको अपनी समस्या का समाधान करने के लिए खुशी हुई। किसी भी मामले में, अगली बार जब आपको रेडिस के साथ मेमोरी समस्या हो, तो कॉल का पहला पोर्ट "INFO" रेडिस कमांड होना चाहिए। यह कमांड आपको बहुमूल्य जानकारी बता देंगे ऐसे

रूप

मेमोरी

used_memory: 3,223,928 used_memory_human: 3.07M used_memory_rss: 1,916,928 used_memory_peak: 3,512,536 used_memory_peak_human: 3.35M used_memory_lua: 37888 mem_fragmentation_ratio: 0.59

या

कीस्पेस

db0: keys = 282, expires = 27, avg_ttl = 11335089640

जो किसी भी पल में आपकी स्मृति और कुंजीपटल की स्थिति को समझने के लिए बहुत आसान है।

संबंधित मुद्दे