Câu hỏi này đã cũ và câu trả lời thường là "Redis, vì nó làm được nhiều hơn". Bài này đo cả hai trên đúng cùng một bài toán bộ đệm.

Bảng so sánh thông lượng, bộ nhớ, CPU, và những gì Memcached không có

Cùng bài toán khoá–giá trị 100 byte

Redis Memcached
SET, không đường ống 20.136/s 20.854/s
GET, không đường ống 20.894/s 20.970/s
SET, đường ống 100 376.063/s 388.538/s
GET, đường ống 100 608.120/s 944.119/s
Bộ nhớ 100.000 khoá 40,37 MB 15,82 MB
CPU khi 4 khách song song 73,94% 100,16%

Không đường ống, hai hệ thống bằng nhau — 20.000 ops/s cho cả hai. Đúng như đo ở phần 2: nút thắt là lượt đi về, không phải máy chủ.

Có đường ống, Memcached GET nhanh hơn 55%.

Vì sao Memcached nhanh hơn khi đẩy mạnh

Dòng CPU nói rõ: Redis dùng 73,94% — tức chưa hết một nhân, và nó không thể vượt 100% vì xử lý lệnh chỉ có một luồng. Memcached dùng 100,16%, tức nó đang dùng nhiều hơn một nhân.

Memcached đa luồng thật sự: -t 4 cho bốn luồng worker, mỗi luồng xử lý lệnh độc lập. Với máy nhiều nhân và tải cao, đó là lợi thế kiến trúc mà Redis không có.

Redis chọn một luồng để đổi lấy tính nguyên tử miễn phí và mã đơn giản. Với phần lớn hệ thống — dưới 100.000 ops/s — lựa chọn đó không tốn gì. Trên ngưỡng đó, nó là trần cứng, và cách vượt duy nhất là Cluster (phần 23).

Và tốn ít bộ nhớ hơn 61%

Redis      40,37 MB
Memcached  15,82 MB

Cho cùng 100.000 khoá × 100 byte.

Lý do đã đo ở phần 3: Redis tốn khoảng 64 byte phụ trội mỗi khoá cho robj, dictEntry, tiêu đề chuỗi và bộ cấp phát. Memcached dùng bộ cấp phát slab đơn giản hơn và không có lớp đối tượng đa kiểu — nó chỉ biết chuỗi.

Với bộ đệm hàng chục triệu khoá nhỏ, chênh lệch 2,6 lần là tiền thật.

Nhưng Memcached đổi lấy điều đó bằng gì

khởi động lại      ->  curr_items 0
SET giá trị 2 MB   ->  SERVER_ERROR object too large for cache
SET giá trị 900 KB ->  STORED

Không có lưu trữ. Khởi động lại là mất sạch, không có RDB, không có AOF. Với bộ đệm thuần thì không sao — nhưng nó nghĩa là mỗi lần triển khai là một lần bão cache (phần 27).

Trần 1 MB mỗi giá trị (chỉnh được bằng -I, nhưng mặc định là vậy). Redis cho tới 512 MB.

Và danh sách những gì hoàn toàn không có:

  • Kiểu dữ liệu: List, Set, Sorted Set, Hash, Stream, Bitmap, HyperLogLog
  • Pub/Sub, Lua, giao dịch
  • Sao chép, chuyển đổi tự động
  • Lệnh chặn như BLPOP
  • TTL đọc lại được (TTL trả về thời gian còn lại)

Mỗi mục trong danh sách này là một phần của sê-ri này. Nếu bạn dùng bất kỳ cái nào, câu hỏi đã có câu trả lời.

Chọn thế nào

Memcached khi: bộ đệm thuần khoá–giá trị, dữ liệu dựng lại được, tải rất cao trên máy nhiều nhân, và bạn muốn ít thứ để hỏng nhất có thể.

Redis khi: cần bất kỳ thứ gì trong danh sách ở trên — và với phần lớn ứng dụng, bạn sẽ cần ít nhất một.

Điều đáng nói: hai hệ thống này không cạnh tranh nhau như người ta tưởng. Memcached làm đúng một việc và làm rất tốt. Redis làm nhiều việc, mỗi việc tốt vừa đủ, và giá trị của nó nằm ở chỗ bạn không phải chạy năm hệ thống.

Một góc nhìn thực dụng

Nếu đang chọn mới: bắt đầu bằng Redis. Không phải vì nó nhanh hơn — đo được là không — mà vì xác suất bạn cần thêm một kiểu dữ liệu, một hàng đợi, hoặc một khoá phân tán trong sáu tháng tới là rất cao, và lúc đó việc thêm Memcached-thứ-hai tốn hơn nhiều.

Nếu đang chạy Memcached và nó ổn: đừng đổi. Chênh lệch hiệu năng nghiêng về phía nó, và việc di chuyển một bộ đệm đang chạy tốt không mang lại gì.

Nếu đang chạy Redis chỉ để làm bộ đệm khoá–giá trị và bộ nhớ là vấn đề: 61% là con số đáng cân nhắc. Nhưng hãy đo trên dữ liệu thật trước — con số đó phụ thuộc kích thước giá trị, và với giá trị lớn phụ trội của Redis trở nên không đáng kể.

Thử ba mươi giây

Xem bạn có đang dùng gì ngoài khoá–giá trị không:

redis-cli info commandstats | sed 's/cmdstat_//' | cut -d: -f1 | \
  grep -vE '^(get|set|del|exists|expire|ttl|mget|mset|ping|info|config|client|command)$' | sort

Danh sách in ra là những lệnh Memcached không có. Trống nghĩa là bạn đang dùng Redis như một Memcached đắt hơn 2,6 lần về bộ nhớ.

Và kiểm kiểu dữ liệu đang lưu:

redis-cli --scan --count 500 | head -2000 | while read k; do redis-cli type "$k"; done | sort | uniq -c

Chỉ toàn string thì cùng kết luận. Có hash, zset, stream thì câu hỏi đã được trả lời.

Phần sau: danh sách kiểm trước khi đưa Redis lên chạy thật.