Redis: Zero to Hero

Sê-ri 40 phần về Redis, mỗi phần một phép đo chạy được trên Docker.

40/40 phần đã đăng Cơ sở dữ liệu
1 Redis nhanh hơn PostgreSQL 4,1 lần khi ghi — không phải 100 lần như lời đồn; và phần lớn khoảng cách đó là độ bền bị bỏ, không phải kiến trúc Mở đầu sê-ri bốn mươi phần về Redis, không bằng lời quảng cáo mà bằng cách đo nó cạnh PostgreSQL trên đúng cùng một bài toán. Redis nhanh hơn 4,1 lần khi ghi và 2,0 lần khi đọc — nhưng bật cờ UNLOGGED trên Postgres là khoảng cách co còn 1,4 lần, cho thấy Redis nhanh chủ yếu vì mặc định không hứa gì về độ bền. Bộ nhớ mỗi bản ghi gần bằng nhau (185 vs 178 byte), và có một câu hỏi Redis không trả lời được. 01/09/2026 · 8 phút đọc 2 Một kết nối Redis duy nhất nhảy từ 25.850 lên 1.136.364 lệnh/giây mà không đổi một dòng cấu hình — vì nút thắt chưa bao giờ là CPU, mà là lượt đi về Redis xử lý lệnh bằng một luồng duy nhất, nghe như lãng phí trên máy 16 nhân. Đo thật cho thấy nút thắt nằm ở chỗ khác: một luồng vẫn tăng gần tuyến tính tới 8 kết nối, và một kết nối đơn dùng đường ống 64 đạt 1,1 triệu lệnh/giây — gấp 44 lần cùng kết nối đó không đường ống. Không đường ống, Redis không dùng hết nổi một nhân vì phần lớn thời gian nằm trong lời gọi đọc/ghi socket, mỗi lời gọi mang đúng một lệnh. 01/09/2026 · 8 phút đọc 3 Cùng một chuỗi 1024 byte tốn 1.328 hay 2.608 byte tuỳ cách bạn ghi nó vào Redis — chênh 96% mà không đổi một ký tự dữ liệu Đào vào con số 185 byte cho mỗi khoá chứa 100 byte dữ liệu, và tìm ra ba cách ghi cùng một chuỗi cho ba lượng bộ nhớ khác nhau. Phụ trội cố định ~64 byte mỗi khoá; một khoá 8 byte dữ liệu tốn 72 byte, gấp 9 lần. Ranh giới 44 byte đổi embstr sang raw. Và dựng chuỗi bằng APPEND chiếm gần gấp đôi vì Redis cấp phát tăng gấp bội. FLUSHALL cũng không trả RAM về hệ điều hành. 01/09/2026 · 8 phút đọc 4 Một tập 512 số nguyên trong Redis tốn 2,6 byte mỗi số — thêm đúng một phần tử nữa là nhảy lên 48,2 byte, gấp 18,6 lần Đo bốn kiểu tập hợp của Redis và tìm ra ba vách đá bộ nhớ rơi ở đúng một phần tử. Gom nhiều giá trị vào một Hash/Set rẻ hơn nhiều khoá riêng 2,3–2,8 lần vì phụ trội 64 byte mỗi khoá biến mất. Nhưng vượt ngưỡng listpack/intset là bộ nhớ mỗi phần tử nhảy 2,3–18,6 lần chỉ vì một phần tử. Và LINDEX có hình chữ V: chậm nhất ở giữa list, không phải ở cuối. 01/09/2026 · 7 phút đọc 5 Cùng 199 trường, cùng dữ liệu, nhưng một Hash tốn 16.256 byte còn cái kia 1.840 byte — chênh 8,8 lần chỉ vì một khoá từng phình to rồi co lại Redis đổi cách mã hoá tập hợp khi nó vượt ngưỡng, nhưng KHÔNG BAO GIỜ đổi ngược. Đo thật: một Hash từng có 513 trường rồi xoá còn 199 vẫn tốn 16.256 byte, gấp 8,8 lần một Hash tạo mới đúng 199 trường (1.840 byte). Đây là rò rỉ bộ nhớ âm thầm nhất trong Redis — phình trong đợt cao điểm rồi giữ chi phí lúc lớn nhất vĩnh viễn. Và một giá trị vượt 64 byte đẩy cả Hash sang mã hoá đắt. 01/09/2026 · 7 phút đọc 6 Đếm một triệu phần tử khác nhau bằng 14.384 byte với sai số 0,12% — và HyperLogLog còn ghi nhanh hơn Set 1,6 lần vì nó không lưu phần tử nào Hai kiểu dữ liệu ít dùng nhất của Redis cũng là hai kiểu tiết kiệm nhất. Đo cả bộ nhớ lẫn sai số: HyperLogLog đếm một triệu phần tử khác nhau trong 14.384 byte cố định (nhỏ hơn Set 3.364 lần) với sai số dưới 0,5%, và PFADD nhanh hơn SADD vì nó băm rồi vứt, không cấp phát. Bitmap nhỏ hơn Set 35 lần nhưng có bẫy: bộ nhớ phụ thuộc chỉ số bit lớn nhất, không phụ thuộc số bit đã đặt. 01/09/2026 · 8 phút đọc 7 Một tiêu thụ Redis Stream quên gọi XACK thổi 1,4 MB thành 28 MB — gấp 19,7 lần — và XTRIM cắt stream không cứu được một byte List làm hàng đợi được và nhiều hệ thống dùng nó. Đo xem Stream cho thêm gì: nó gọn hơn List 24% dù mang thêm id, và khác biệt thật là khi tiến trình chết — bản tin ở lại danh sách chờ tới khi có ai XACK, còn List thì mất dấu. Nhưng danh sách chờ là cái bẫy: quên XACK làm bộ nhớ phình 19,7 lần, và XTRIM không cứu được vì chỗ tốn nằm ở pending, không ở stream. Giám sát XPENDING, không chỉ XLEN. 01/09/2026 · 8 phút đọc 8 Một lệnh SET vô tình xoá sạch TTL và biến phiên đăng nhập 30 phút thành khoá sống mãi mãi — còn APPEND lại giữ nguyên hạn, dù cả hai đều sửa giá trị Đặt TTL là thao tác phổ biến nhất trong Redis sau GET và SET. Đo ba thứ ít ai kiểm: Redis dọn 100.000 khoá hết hạn trong dưới một giây (nhanh hơn lời đồn), SET xoá TTL nhưng APPEND/INCRBY thì không — vì lệnh thay thế cả khoá thì mất hạn còn lệnh sửa tại chỗ thì giữ — và mỗi TTL tốn thêm 34,4 byte (+19%). Quên KEEPTTL là nguồn của một lớp lỗi khoá bất tử không lỗi, không cảnh báo. 01/09/2026 · 7 phút đọc 9 Đặt volatile-lru khi không khoá nào có TTL chính là tắt hẳn việc dọn dẹp — Redis từ chối ghi trong khi 166.000 khoá bỏ được vẫn nằm nguyên trong RAM Khi Redis chạm trần bộ nhớ, chính sách maxmemory quyết định nó dọn gì. Đo tám chính sách trên cùng một phép thử: volatile-lru với dữ liệu không TTL cho kết quả y hệt noeviction (0 khoá bị đuổi, 27.610 lỗi ghi) — cái bẫy dễ vấp nhất. Và LRU của Redis là gần đúng (lấy mẫu 5 khoá) nên chỉ giữ được 545/1000 khoá nóng, trong khi LFU giữ đủ 1.000/1.000 mà không cần chỉnh gì. 01/09/2026 · 8 phút đọc 10 Xoá 270.000 khoá khỏi Redis mà RSS không giảm một byte — bộ nhớ trả về theo cả trang, không theo từng khoá, nên xoá rải rác để lại lỗ không thu hồi được mem_fragmentation_ratio là chỉ số hay bị hiểu sai nhất trong INFO memory. Đo ở ba trạng thái: một instance gần rỗng có tỷ lệ 16,59 mà hoàn toàn khoẻ; xoá 90% khoá thì used_memory tụt còn RSS đứng im ở 107,6 MB vì jemalloc chỉ trả một trang về khi MỌI đối tượng trong đó đã chết. Và activedefrag y, tự nó, thường là lệnh không có tác dụng vì ngưỡng mặc định 100 MB. Cảnh báo trên allocator_frag_bytes, đừng trên tỷ lệ. 01/09/2026 · 8 phút đọc 11 Một lệnh KEYS đẩy độ trễ PING của Redis từ 1 ms vọt lên 263 ms — trong khoảnh khắc đó khoảng 13.000 yêu cầu xếp hàng chờ, và DEL còn tệ hơn KEYS Redis xử lý lệnh bằng một luồng duy nhất, nên một lệnh chậm không chỉ chậm — nó chặn đầu hàng của mọi khách khác. Đo thật trên 2 triệu khoá: KEYS '*' đẩy PING max lên 263,8 ms, SCAN chậm hơn 58% nhưng độ trễ tệ nhất ít hơn 63 lần vì nó nhường luồng; DEL một Hash 194 MB chặn 467,7 ms còn UNLINK chỉ 3,6 ms. Và độ trễ trung bình gần như không đổi — nên nếu chỉ đo trung bình, cả vấn đề này vô hình. 01/09/2026 · 8 phút đọc 12 Đường ống Redis 10.000 lệnh cho 47,9 lần thông lượng — nhưng đẩy lên 100.000 thì tụt còn một nửa; gộp lô có điểm ngọt, không phải càng lớn càng tốt Phần 2 thấy đường ống cho hơn bốn mươi lần thông lượng trên một kết nối. Bài này tìm điểm dừng: đường ống 10.000 đạt 969.426 ops/s (47,9×), nhưng 100.000 chỉ còn 473.477 — một nửa, vì chi phí đệm ở hai phía vượt phần tiết kiệm round-trip. Bất ngờ hơn: MGET 100 khoá nhanh hơn đường ống 100 lệnh 45% dù cùng một lượt đi về, vì một lệnh phân tích một lần thay vì trăm lần. Và bộ đệm khách thường không có giới hạn (0 0 0). 01/09/2026 · 8 phút đọc 13 Một lệnh lỗi giữa giao dịch Redis không huỷ gì cả — các lệnh khác vẫn chạy và vẫn giữ kết quả; 'transaction' của Redis không có chữ Rollback Redis có MULTI/EXEC và gọi nó là giao dịch, nhưng nó bảo đảm ít hơn bạn tưởng. Đo thật: lỗi cú pháp lúc xếp hàng huỷ cả khối (EXECABORT), nhưng lỗi lúc chạy — INCR trên một chuỗi — chỉ báo lỗi đúng lệnh đó còn SET x và SET y vẫn chạy và vẫn giữ kết quả. Không có quay lui. Cái mạnh thật sự là WATCH — khoá lạc quan kiểu kiểm-rồi-đặt — và MULTI bọc quanh một đường ống gần như miễn phí (chênh 0,2%). 01/09/2026 · 8 phút đọc 14 Một Lua script chạy 3 giây trên Redis bắt mọi khách hàng khác chờ đúng 2.951,6 ms — vì tính nguyên tử bạn nhận được CHÍNH LÀ thời gian chặn mọi người phải chịu Lua cho bạn tính nguyên tử mà MULTI không cho: đọc một giá trị rồi quyết định dựa trên nó. Đo cái giá: script chạy 3,02 giây thì PING của khách khác chạm 2.951,6 ms — độ chặn gần đúng bằng thời gian chạy, không nhường luồng. Vòng lặp vô hạn không làm máy chủ chết (BUSY sau 5 giây, cứu bằng SCRIPT KILL) nhưng script đã ghi thì không giết được. EVALSHA nhanh hơn EVAL 27%, và cache script sinh động rò 340 MB không ai dọn. 01/09/2026 · 8 phút đọc 15 Khởi động lại Redis: script Lua biến mất sạch, còn Function vẫn nguyên vẹn và chạy được ngay — nhưng tốc độ hai bên giống hệt nhau, vì cùng một máy Lua Redis 7 thêm Functions, và câu hỏi đầu tiên ai cũng hỏi là 'khác gì Lua script'. Đo cả hai trên cùng logic: sau khi khởi động lại, EVALSHA trả NOSCRIPT còn FCALL chạy bình thường — vì function nằm trong chính dữ liệu, đi theo RDB/AOF/bản sao, còn script chỉ nằm trong bộ nhớ tạm. Nhưng FCALL 20.520 ops/s so EVALSHA 20.256, chênh trong nhiễu: đừng chuyển vì hiệu năng, chuyển vì vận hành — cờ no-writes được thi hành thật, tên có nghĩa thay mã băm, và mã đi theo quy trình triển khai. 01/09/2026 · 8 phút đọc 16 50 bản tin Redis Pub/Sub gửi trong lúc thuê bao mất kết nối: nhận lại được đúng 0 — nó là đài phát thanh, không phải hộp thư, và người ta cứ nhầm hai thứ đó Pub/Sub là tính năng hay bị dùng sai nhất của Redis vì nó trông giống một hàng đợi. Đo ba tình huống chứng minh nó không phải: bản tin gửi khi chưa ai nghe mất sạch, gửi trong lúc thuê bao ngắt kết nối cũng mất sạch (0/50), và thuê bao đọc chậm bị Redis đóng kết nối sau khi bộ đệm chạm 32 MB. PUBLISH cũng chậm 6 lần khi lên 10 thuê bao vì phải ghi vào bộ đệm từng người trên luồng duy nhất. 01/09/2026 · 8 phút đọc 17 BLPOP nhận việc sau 0,3 mili giây, còn vòng lặp hỏi mỗi 100 ms mất 50,6 ms và tốn gấp 10 lần số lệnh — nhanh hơn 170 lần cho một dòng lệnh đổi tên Dùng List làm hàng đợi là cách phổ biến nhất, và cách lấy việc ra quyết định gần như mọi thứ. Đo ba cách chờ: BLPOP nhận việc sau 0,3 ms với 0 lần thăm dò, còn vòng lặp hỏi mỗi 100 ms mất 50,6 ms (trung vị luôn xấp xỉ nửa chu kỳ) và gửi gấp 10 lần số lệnh cho không việc gì. Nhưng BLPOP vẫn mất việc khi tiến trình chết — BLMOVE sang danh sách 'đang xử lý' chỉ tốn thêm 9,5%, và đó là ranh giới nên chuyển sang Stream. 01/09/2026 · 8 phút đọc 18 Ghi đè 7 triệu khoá trong lúc Redis đang chụp ảnh bộ nhớ làm chi phí copy-on-write nhảy từ 1,4 MB lên 87 MB — và INFO memory không hề thấy một byte nào trong đó RDB chụp toàn bộ bộ nhớ Redis ra một tệp. Đo thật: BGSAVE 2 triệu khoá xong trong 1,21 giây, tệp nén 7,2 lần nhỏ hơn bộ nhớ, khách gần như không thấy độ trễ nhờ fork. Nhưng chi phí thật nằm ở copy-on-write: không ghi gì thì tốn 1,4 MB, ghi đè 7 triệu khoá lúc đang chụp thì tốn 87 MB — gấp 64 lần — và used_memory_rss của Redis đứng im vì các trang bị sao chép thuộc về tiến trình con. Đây là nguồn gốc lời khuyên 'chỉ dùng 50% RAM cho Redis'. 01/09/2026 · 8 phút đọc 19 Giết Redis bằng SIGKILL với appendfsync=no — mất đúng 0 bản ghi, lặp ba lần vẫn vậy; vì tiến trình chết không phải mất điện, và người ta hay nhầm hai thứ đó AOF ghi từng lệnh vào tệp thay vì chụp ảnh định kỳ, với ba chế độ appendfsync ai cũng gọi là nhanh/cân bằng/an toàn. Đo cả tốc độ lẫn lượng mất thật: no và everysec nhanh ngang nhau, always chậm 12,5 lần khi gọi từng lệnh nhưng chỉ 4,8 lần khi có đường ống. Bất ngờ lớn nhất: SIGKILL Redis với appendfsync=no vẫn mất 0 — vì write() đã vào bộ đệm kernel, và giết tiến trình không xoá được nó. appendfsync chỉ quyết định chuyện gì xảy ra khi mất điện. 01/09/2026 · 8 phút đọc 20 Tệp AOF của Redis lớn gấp 5,8 lần RDB nhưng nạp lại nhanh y hệt — lặp bốn lần vẫn vậy, và nó lật đổ lời khuyên 'AOF khôi phục chậm hơn nhiều' Đặt RDB và AOF cạnh nhau trên cùng 2 triệu khoá rồi đo thứ quan trọng nhất — thời gian sống lại sau sự cố. AOF văn bản 270 MB so với RDB 47 MB, lớn gấp 5,8 lần, nhưng nạp lại trong 1,3–1,4 giây y như RDB, vì thời gian nạp bị chi phối bởi việc dựng 2 triệu mục bảng băm chứ không phải đọc byte. Nên lựa chọn không nằm ở tốc độ mà ở lượng dữ liệu mất: RDB mất tới một giờ, AOF everysec mất một giây. 01/09/2026 · 8 phút đọc 21 Giết máy chính Redis giữa 2,7 triệu lệnh ghi: mất 0 — nhưng để bản sao chậm lại một chút rồi mới giết: mất 79%; 'bất đồng bộ' không có nghĩa 'mất một ít' Sao chép của Redis là bất đồng bộ, và mọi tài liệu đều cảnh báo điều đó nghĩa là mất dữ liệu. Đo thật: liên kết khoẻ thì giết máy chính giữa 2,78 triệu lệnh vẫn mất đúng 0; nhưng cho bản sao chậm lại trước khi giết thì mất 79.592 trên 100.719 lệnh — gần bốn phần năm. Lượng mất không phải 'vài lệnh cuối', nó bằng ĐÚNG khoảng cách bản sao đang chậm ngay lúc đó. WAIT thu hẹp khoảng đó nhưng chậm 25 lần. 01/09/2026 · 8 phút đọc 22 Sentinel công bố máy chính Redis mới sau 4,50 giây — nhưng khách hàng của bạn thấy hệ thống chết 6,27 giây, và khoảng chênh đó là con số duy nhất đáng đưa vào SLA Sao chép giữ dữ liệu tốt cho tới khi máy chính chết và không ai thay nó — Sentinel làm việc thay đó. Đo thật một lần chuyển đổi: Sentinel công bố máy chính mới sau 4,50 giây (≈ down-after + 1,5 giây), nhưng khách hàng ghi liên tục thấy gián đoạn 6,27 giây vì còn phải nhận ra kết nối chết, hỏi lại địa chỉ, nối lại. Vì sao cần ba Sentinel ở ba vùng hỏng, và cái Sentinel không cứu được. 01/09/2026 · 9 phút đọc 23 Một khách Redis Cluster không giữ bản đồ slot chạy chậm 1,63 lần vì 67% lệnh bị đá sang nút khác — và cái giá thật của Cluster không phải tốc độ, mà là MGET ngừng hoạt động Sentinel cho chịu lỗi nhưng dữ liệu vẫn nằm một máy; Cluster chia ra nhiều máy và lấy đi vài thứ. Dựng cụm sáu nút rồi đo: khách tự tính CRC16 gọi thẳng đúng nút đạt 16.907 ops/s với 0 lần MOVED, còn khách 'ngây thơ' chỉ 10.390 ops/s vì 67% lệnh bị chuyển hướng. Nhưng mất mát lớn nhất không đo bằng ops/s: MGET, MSET, Lua, MULTI đều chết với CROSSSLOT khi khoá nằm khác slot. Cái Cluster lấy đi là khả năng diễn đạt. 01/09/2026 · 8 phút đọc 24 Công thức khoá phân tán 'SET NX PX' được chép nhiều nhất Internet — và 50 trên 50 lần nó âm thầm mất khoá giữa chừng, để ba tiến trình cùng ghi vào một chỗ mà không ai biết SET key value NX PX 30000 là công thức khoá phân tán ai cũng chép. Đo thật xem nó bảo đảm gì và ngừng bảo đảm ở đâu: khi công việc ngắn hơn TTL, nó chặn sạch 599 lần đua về 0; nhưng khi công việc dài hơn TTL, 50/50 lần lấy khoá đều mất khoá trước khi xong, ba tiến trình cùng vào vùng cấm mà không lỗi nào hiện ra. Redlock không cứu được — vấn đề nằm ở đồng hồ, không ở số lượng Redis. 01/09/2026 · 9 phút đọc 25 Cửa sổ cố định cho 200 yêu cầu lọt qua trong 0,3 giây dù giới hạn là 100/giây — và cách đếm chính xác tuyệt đối ngốn gấp 1.646 lần bộ nhớ để sửa đúng 2% sai số Giới hạn tần suất là ứng dụng phổ biến thứ hai của Redis sau cache. Cài bốn thuật toán bằng Lua rồi đo cả tốc độ, bộ nhớ lẫn độ chính xác: cửa sổ cố định đơn giản nhất nhưng để lọt gấp đôi ở ranh giới; nhật ký trượt chính xác tuyệt đối nhưng tốn 88 GB nơi cửa sổ trượt chỉ tốn 53 MB với sai số 2%. Bài học là chọn xấp xỉ đủ tốt, không đuổi theo chính xác tuyệt đối. 01/09/2026 · 8 phút đọc 26 Thêm một dòng CREATE INDEX làm truy vấn nhanh hơn 181 lần — tốt hơn cả tỉ lệ trúng cache 99%, và không thêm một hệ thống nào để hỏng Cache-aside là mẫu dùng Redis phổ biến nhất, nhưng đo thật cho thấy nó thắng ít hơn ta tưởng. Tra khoá chính: Redis GET 0,062 ms ngang PostgreSQL 0,065 ms — đặt cache ở đây chỉ thêm một chỗ để hỏng. Truy vấn đắt 19,9 ms: cache nhanh hơn 321 lần, nhưng một CREATE INDEX kéo nó xuống 0,110 ms — nhanh hơn 181 lần, tốt hơn cả cache trúng 99%. Bộ đệm che một truy vấn chậm; chỉ mục xoá nó. 01/09/2026 · 8 phút đọc 27 200 khách cùng gặp một khoá Redis vừa hết hạn tạo ra đúng 200 truy vấn xuống cơ sở dữ liệu — và một dòng khoá kéo nó về 1, còn làm chính người dùng nhanh hơn 6,4 lần Cache-aside chạy tốt khi mọi thứ bình thường. Bài này đo đúng khoảnh khắc nó không bình thường: một khoá nóng hết hạn và 200 khách cùng lao vào. Không bảo vệ: 200 truy vấn, p50 vọt lên 360 ms. Một khoá độc quyền: 1 truy vấn, p50 xuống 56 ms — nhanh hơn 6,4 lần, vì CSDL không bị 200 mũi cùng đâm. Trả giá trị cũ: không ai phải chờ, p50 chỉ 29 ms. 01/09/2026 · 7 phút đọc 28 Ghi giá trị mới thẳng vào cache lệch với cơ sở dữ liệu 103 trên 120 lần — còn 'xoá cache trước khi cập nhật', cái nghe an toàn nhất, để lại dữ liệu cũ nằm đó vĩnh viễn Bộ đệm chỉ có ích khi nó đúng. Đo bốn cách giữ nó khớp với cơ sở dữ liệu khi có 8 luồng vừa đọc vừa ghi: ghi đè giá trị mới lệch 103/120 lần (tệ nhất, lại trực giác nhất); xoá-trước-cập-nhật nhìn hoàn hảo cho tới khi thêm người đọc song song thì để lại dữ liệu cũ VĨNH VIỄN; chỉ 'xoá sau khi cập nhật' cho lệch tạm thời tự khỏi. Bài toán thật không phải 'làm sao luôn khớp' mà 'lệch bao lâu thì chấp nhận được'. 01/09/2026 · 9 phút đọc 29 Một cặp ngoặc nhọn trong tên khoá đẩy trọn 20.000 khoá về đúng một nút Redis Cluster — nhưng thông lượng không hề đổi; cái nó lấy đi là hai phần ba dung lượng Phần 23 thấy CRC16 rải khoá rất đều. Bài này đo khi nó KHÔNG đều: một thẻ băm {khach} gom cả 20.000 khoá vào một slot, hai nút còn lại giữ đúng số không. Bất ngờ là tốc độ chẳng suy suyển — một nút chịu trên 1,2 triệu lệnh/giây — nhưng cụm ba máy giờ chỉ còn dung lượng của một máy. Bạn trả tiền cho ba, dùng được một. Vấn đề của khoá nóng không phải chậm, mà là mất chỗ. 01/09/2026 · 8 phút đọc 30 Đọc giá trị 10 MB từ Redis chỉ chậm hơn 1 KB đúng 3,5 mili giây — nhưng 20 khách đọc chậm cùng lúc thổi 10 MB dữ liệu thành 200 MB bộ nhớ mà maxmemory không hề hay biết 'Đừng lưu giá trị lớn trong Redis' là lời khuyên phổ biến, nhưng vấn đề thật không phải chỗ người ta nghĩ. Đo thật: đọc 10 MB gần như không chặn khách khác (Redis gửi theo đoạn), độ trễ dưới 10 KB phẳng hoàn toàn. Cái nguy hiểm là bộ đệm đầu ra — 20 khách đọc chậm biến 10 MB dữ liệu thành 215 MB used_memory, gấp 5.183 lần, và đó là cách một Redis 'chỉ chứa 5 GB' bị giết khi có 20 GB RAM. 01/09/2026 · 8 phút đọc 31 Mở kết nối Redis mới cho mỗi lệnh chậm gấp 5,5 lần — và khi chạm trần 10.000 kết nối, chính redis-cli của bạn cũng không vào nổi để xem chuyện gì đang xảy ra Bể kết nối là thứ mọi thư viện đều có và ít ai chỉnh. Đo thật: tái dùng kết nối nhanh gấp 5,5 lần mở mới mỗi lệnh (6,4 lần khi có mật khẩu), mật khẩu không làm Redis chậm mà chỉ làm việc MỞ kết nối chậm; mỗi kết nối chỉ tốn 1.928 byte và gần như 0 CPU khi ngồi không — nhưng có một trần cứng 10.000, và lúc chạm nó bạn mất luôn đường nhìn vào bên trong. 01/09/2026 · 8 phút đọc 32 Bật TLS cho Redis chậm hơn 11,5% khi gọi từng lệnh — nhưng gộp thành đường ống thì nhanh bằng bản không mã hoá; cái giá thật nằm ở chỗ khác: 40% CPU Redis mặc định không mật khẩu, không mã hoá, ai cũng làm được mọi thứ. Đo hai lớp bảo vệ và cái giá thật của từng lớp: ACL gần như miễn phí và chặn được lớp lỗi lớn nhất; còn TLS thì bất ngờ — chi phí mã hoá tính trên bản ghi chứ không trên lệnh, nên đường ống 100 lệnh làm nó gần như biến mất (477.027 so với 461.274/giây), nhưng CPU máy chủ vẫn nhảy từ 38,71% lên 54,26% cho cùng một lượng việc. 01/09/2026 · 8 phút đọc 33 Cảnh báo trên phần trăm bộ nhớ Redis cho bạn đúng 2 giây báo trước — rồi nó ghim ở 100% và câm lặng trong khi 15.870 khoá bị vứt đi mỗi giây INFO trả về hơn hai trăm dòng; đo thật trên một Redis 64 MB cho thấy dòng bạn hay cảnh báo nhất — phần trăm bộ nhớ — là dòng vô dụng nhất khi sự cố xảy ra. Nó là chỉ số bão hoà, chạm trần rồi đứng im; cái thật sự nói mức nghiêm trọng là tốc độ đuổi khoá, một con số không có trần. Cùng bốn nguồn để truy một lệnh chậm, và mười chỉ số nên đưa lên bảng. 01/09/2026 · 9 phút đọc 34 Một lệnh GET khiến khách chờ 3.335,8 ms không hề xuất hiện trong slowlog của Redis — nó chỉ ghi thời gian chạy, không ghi thời gian nằm chờ trong hàng SLOWLOG là công cụ chẩn đoán tốt nhất của Redis, nhưng nó đo thời gian một lệnh CHẠY, không đo thời gian nó xếp hàng. Đo thật: một EVAL chạy 3 giây làm một GET mất 3,3 giây từ phía khách — và slowlog chỉ ghi EVAL, GET biến mất. SLOWLOG cho biết ai gây nghẽn, không cho biết ai bị nghẽn; muốn thấy phía nạn nhân phải đo ở khách hàng. 01/09/2026 · 8 phút đọc 35 Nâng Redis 6.2 lên 7.4 không cần cửa sổ bảo trì: đúng một lệnh ghi thất bại trên 3.843 lần — nhưng vừa đổi vai trò xong là không còn đường lùi Một quy trình nâng cấp không downtime, đo thật: dựng bản mới làm bản sao (đồng bộ 0,6 giây), đổi vai trò (0,12 giây), khách mất đúng một lệnh ghi và 0,03 giây gián đoạn. Nhưng khi thử đảo ngược — cho bản cũ làm bản sao của bản mới — bản 6.2 không đọc nổi định dạng RDB của 7.4, dbsize về 0. Đây là quyết định một chiều, và mọi kiểm tra phải xong trước bước không quay lại được. 01/09/2026 · 8 phút đọc 36 Ảnh Redis chính thức tự tắt protected-mode — tôi chạy FLUSHALL từ một container khác, không mật khẩu, và nó trả về OK docker run -d redis chạy được ngay, nhưng cấu hình mặc định là cho phòng thí nghiệm, không phải production: không mật khẩu, nghe mọi giao diện, không giới hạn bộ nhớ. Và --memory của Docker không bảo vệ được Redis — đặt nó mà quên maxmemory chỉ đổi cách Redis chết từ 'hết RAM máy chủ' thành 'container bị OOMKilled'. Kèm cấu hình tối thiểu cho môi trường thật, mỗi dòng một lý do đo được. 01/09/2026 · 7 phút đọc 37 Gom nhóm bốn trạng thái đơn hàng mất 203,8 ms trong Redis và 8,9 ms trong PostgreSQL — và 203,8 ms đó đóng băng toàn bộ máy chủ Redis Dựng thử một ứng dụng thật trên Redis rồi đo. Tra một khoá đã biết: Redis thắng, 0,145 ms so với 0,334. Nhưng gom nhóm, lọc, sắp xếp thì nó thua 5–23 lần hoặc không làm được — và mỗi báo cáo chạy trong Lua khiến mọi khách khác chờ một phần năm giây. Redis giỏi tra theo nhãn, dở tra theo thuộc tính; ép nó làm việc thứ hai là tự dựng chỉ mục mà không ai giữ đồng bộ. 01/09/2026 · 9 phút đọc 38 Memcached đọc nhanh hơn Redis 55% và tốn ít bộ nhớ hơn 61% cho cùng một bộ đệm — nhưng khởi động lại là mất sạch, và đó mới là chỗ quyết định Đo cả hai trên đúng cùng bài toán khoá–giá trị 100 byte. Không đường ống thì bằng nhau (nút thắt là lượt đi về). Đẩy mạnh thì Memcached thắng vì đa luồng thật, và tốn ít RAM hơn 2,6 lần vì không có lớp đối tượng đa kiểu. Nhưng nó không có lưu trữ, trần 1 MB mỗi giá trị, và không có kiểu dữ liệu nào. Câu hỏi không phải cái nào nhanh, mà là bạn sẽ cần gì trong sáu tháng tới. 01/09/2026 · 7 phút đọc 39 Một lệnh SET thiếu đúng chữ KEEPTTL biến mọi phiên đăng nhập thành bất tử — và ba lỗi Redis khác chạy hoàn hảo ở dev rồi sập ở production Bốn lỗi có ở gần như mọi hệ thống, mỗi cái kèm số đo: khoá không TTL rò rỉ 15 MB âm thầm; KEYS chặn 38 ms ở 500 nghìn khoá và 263 ms ở 2 triệu trong khi SCAN gần như không đổi; một SET ghi đè xoá TTL làm phiên không bao giờ hết hạn; bốn khoá riêng tốn hơn một Hash 43%. Điểm chung: không cái nào báo lỗi, tất cả chỉ lộ ra ở quy mô thật. 01/09/2026 · 7 phút đọc 40 Bốn mươi phép đo Redis gói thành một danh sách kiểm, và ba niềm tin của chính tôi bị con số bác bỏ — cùng ba lần tôi đo sai rồi phải sửa Chốt sê-ri 40 phần: mười con số đáng nhớ, ba quy luật lặp lại (nút thắt là lượt đi về; vượt ngưỡng là nhảy bậc không tăng dần; Redis chậm dần chứ hiếm khi báo lỗi), một danh sách kiểm chạy được trước khi lên production, và ba lần phép đo của tôi cho kết quả bất khả thi — mỗi lần đều lộ ra vì một con số vượt giới hạn vật lý hoặc không khớp phép đo trước. 01/09/2026 · 9 phút đọc