Khi bạn có một vấn đề tiêu thụ bộ nhớ với một hệ thống xếp hàng, và bạn là 100% dương tính rằng tất cả các mặt hàng xếp hàng đợi đã được xóa khỏi cửa hàng và không ngồi vào một hàng đợi ngoại lệ/lỗi, thì nguyên nhân có thể xảy ra nhất là tỷ lệ xếp hàng cao hơn nhiều so với tỷ lệ khử.
Redis sử dụng bộ cấp phát bộ nhớ đa năng (jemalloc, ptmalloc, tcmalloc, v.v ...). Các bộ phân bổ này không nhất thiết phải cung cấp bộ nhớ cho hệ thống. Khi một số bộ nhớ được giải phóng, người cấp phát có xu hướng giữ nó (để tái sử dụng nó cho một phân bổ trong tương lai). Điều này đặc biệt đúng khi nhiều đối tượng nhỏ được phân bổ ngẫu nhiên, thường là trường hợp với Redis.
Hậu quả là mức tiêu thụ bộ nhớ cao nhất tại một thời điểm nhất định sẽ làm cho Redis tích lũy bộ nhớ và giữ nó. Bộ nhớ này không bị mất, bộ nhớ này sẽ được sử dụng lại nếu một mức tiêu thụ bộ nhớ khác xuất hiện. Nhưng từ quan điểm hệ thống, bộ nhớ vẫn được gán cho Redis. Đối với một hệ thống xếp hàng, nếu bạn xếp hàng nhanh hơn bạn có thể khử chúng, bạn sẽ có mức tiêu thụ bộ nhớ cao nhất.
Lời khuyên của tôi là đặt công cụ cho ứng dụng của bạn để tìm nạp và ghi lại độ dài hàng đợi vào các khoảng thời gian thường xuyên để kiểm tra sự tiến hóa của số mục trong hàng đợi (và xác định giá trị đỉnh).
Đã cập nhật:
Tôi đã thử nghiệm một vài điều có thể hiểu được những gì nó lưu trữ trong Redis. Trên thực tế, cấu trúc dữ liệu khá phức tạp (kết hợp các chuỗi, tập hợp, zsets và băm). Nếu bạn nhìn vào Redis, bạn sẽ tìm thấy những điều sau đây:
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)
Tôi không biết Coffeescript ở tất cả, vì vậy tôi đã cố gắng để tạo lại vấn đề sử dụng đồng bằng cũ Javascript:
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);
Tôi chạy này mã, kiểm tra những gì còn lại trong Redis sau khi chế biến:
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"
công việc Vì vậy, nó dường như hoàn thành được lưu giữ trong q: việc làm: đầy đủ và q: việc làm: X: hoàn thành mặc dù các công việc đã bị xóa. Tôi đề nghị bạn kiểm tra cardinality của các zsets trong trường hợp Redis của riêng bạn.
Giải thích của tôi là quản lý các zset này xảy ra sau sự kiện 'hoàn thành' được phát ra. Vì vậy, các công việc được gỡ bỏ một cách chính xác, nhưng id của họ được chèn vào trong những zsets ngay sau đó.
Giải pháp thay thế là tránh phải dựa vào các sự kiện cho mỗi công việc, mà là sử dụng các sự kiện trên hàng đợi để xóa công việc.Ví dụ, những sửa đổi sau đây có thể được thực hiện:
// 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();
}
Sau khi sửa chữa các chương trình, nội dung trong Redis là tốt hơn nhiều:
redis 127.0.0.1:6379> keys *
1) "q:stats:work-time"
2) "q:ids"
3) "q:job:types"
Bạn có thể sử dụng một chiến lược tương tự từ Coffescript.
Xin chào Didier - cảm ơn câu trả lời này, nhưng tôi không nghĩ rằng nó xác định được vấn đề. Tôi nên đã đề cập rằng chiều dài hàng đợi là số không. Thật dễ dàng để theo dõi trạng thái hàng đợi với thư viện kue này - nó bao gồm một máy chủ quản trị được tích hợp sẵn và giao diện người dùng. Tôi sẽ chỉnh sửa câu hỏi của mình để thêm thông tin này. – mainsocial
Tôi đã cập nhật câu trả lời của mình cho phù hợp. –
Didier - cảm ơn bạn đã điều tra. Tôi độc lập đến cùng một kết luận. Trong thực tế có một số lỗi trong mã kue mà tôi đã có thể sửa chữa. Tôi đã kiểm tra trong các bản sửa lỗi để ngã ba của tôi và thực hiện một yêu cầu kéo. – mainsocial