Sửa lỗi Redis 'ERR Background save already in progress' Khi Gọi BGSAVE

intermediate🔴 Redis2026-05-06| Redis 5.x / 6.x / 7.x trên Linux (Ubuntu, CentOS, Debian) và macOS

Error Message

(error) ERR Background save already in progress
#redis#bgsave#rdb#persistence#snapshot

Lỗi Gặp Phải

Bạn kích hoạt snapshot thủ công và Redis trả về:

127.0.0.1:6379> BGSAVE
(error) ERR Background save already in progress

Một tiến trình fork BGSAVE đang chạy — Redis không cho phép chạy hai tiến trình cùng lúc. Thường thì điều này vô hại. Nhưng lúc 2 giờ sáng với deployment đang chờ, bạn cần biết chuyện gì đang xảy ra và khi nào nó sẽ xong.

Nguyên Nhân

Redis xử lý RDB snapshot bằng cách fork một tiến trình con. Chỉ một tiến trình fork chạy tại một thời điểm. Lỗi xảy ra khi:

  • Một lệnh BGSAVE trước đó — thủ công hoặc được kích hoạt bởi cấu hình save — chưa hoàn thành
  • Một lệnh BGREWRITEAOF đang chạy — trên các phiên bản Redis cũ, việc ghi lại AOF cũng chặn BGSAVE
  • Một replica vừa kết nối và Redis đã fork để gửi RDB cho nó (lưu ngầm do replication)

Không có gì bị hỏng. Redis đang bảo vệ bạn khỏi việc fork hai lần. Việc của bạn là chờ lần lưu hiện tại hoàn thành, hoặc tìm hiểu tại sao việc lưu lại mất quá nhiều thời gian.

Bước 1 — Kiểm Tra Tiến Trình Đang Chạy

Bắt đầu từ đây — xem trạng thái persistence hiện tại:

redis-cli INFO persistence

Các trường quan trọng:

rdb_bgsave_in_progress:1          # 1 = đang có lần lưu chạy
rdb_current_bgsave_time_sec:42    # số giây đã trôi qua kể từ khi bắt đầu lưu
rdb_last_bgsave_status:ok         # trạng thái của lần lưu hoàn thành gần nhất
aof_rewrite_in_progress:0         # 1 = AOF rewrite đã được fork

rdb_bgsave_in_progress:1 nghĩa là đang có lần lưu đang hoạt động. Hãy chờ. Redis sẽ đặt lại về 0 khi xong.

Bước 2 — Chờ Đúng Cách

Theo dõi cho đến khi lần lưu hoàn thành:

watch -n 2 'redis-cli INFO persistence | grep -E "bgsave_in_progress|bgsave_time_sec|last_bgsave"'

Với dataset dưới vài GB và I/O đĩa bình thường, BGSAVE sẽ hoàn thành trong vài giây đến vài phút. Nếu quá 5–10 phút, có gì đó không ổn — hãy chuyển sang phần xử lý sự cố bên dưới.

Khi rdb_bgsave_in_progress về 0, chạy lại lệnh BGSAVE của bạn:

127.0.0.1:6379> BGSAVE
Background saving started

Bước 3 — Tìm Nguyên Nhân Kích Hoạt Lần Lưu Ban Đầu

Log của Redis cho bạn biết chính xác điều gì đã kích hoạt nó:

tail -n 100 /var/log/redis/redis-server.log | grep -i "bgsave\|save\|fork"

Các dòng log thường gặp:

# BGSAVE thủ công
* Background saving started by pid 12345

# Kích hoạt bởi cấu hình save (ví dụ: save 300 10)
* 10000 changes in 300 seconds. Saving...

# Kích hoạt bởi replication
* Starting BGSAVE for SYNC with target: disk

Lần lưu do replication kích hoạt? Kiểm tra các kết nối replica:

redis-cli INFO replication | grep -E "connected_slaves|slave"

Bước 4 — Nếu BGSAVE Mất Quá Nhiều Thời Gian

Lưu chậm thường do ba nguyên nhân. Hãy xử lý theo thứ tự sau.

Dataset lớn với đĩa chậm

Tiến trình con ghi toàn bộ dataset xuống đĩa — từng byte một. Với dataset 10 GB và đĩa cơ học chạy 100 MB/s, ít nhất mất 100 giây chưa kể overhead. Kiểm tra kích thước dataset và throughput đĩa:

redis-cli INFO memory | grep used_memory_human
iostat -x 1 5   # kiểm tra mức sử dụng đĩa

I/O đĩa đã đạt tối đa nghĩa là lần lưu sẽ rất chậm. Di chuyển file RDB sang ổ đĩa nhanh hơn:

# redis.conf
dir /mnt/fast-ssd/redis

Áp lực copy-on-write do tải ghi cao

Sau khi fork, mỗi lần ghi vào Redis khiến OS phải sao chép các trang bộ nhớ bị ảnh hưởng (copy-on-write). Throughput ghi cao trong khi lưu làm phồng working set của tiến trình con. Càng nhiều trang được sao chép, lần lưu càng kéo dài. Kiểm tra lượng thay đổi kể từ lần lưu cuối:

redis-cli INFO stats | grep rdb_changes_since_last_save

Con số lớn ở đây có nghĩa là khoảng thời gian lưu của bạn quá rộng. Hãy thu hẹp lại hoặc lên lịch lưu vào giờ thấp điểm.

Transparent Huge Pages gây độ trễ khi fork

THP là thủ phạm nổi tiếng làm giảm hiệu năng Redis — nó làm tăng đáng kể overhead của copy-on-write. Kiểm tra và tắt nó:

cat /sys/kernel/mm/transparent_hugepage/enabled
# Nếu hiển thị [always], hãy tắt đi:
echo never > /sys/kernel/mm/transparent_hugepage/enabled

Bước 5 — Điều Chỉnh Tần Suất Lưu Để Tránh Xung Đột

Tự động lưu quá thường xuyên là thủ phạm phổ biến trên các server bận. Các cấu hình mặc định kích hoạt rất tích cực — trên dataset lớn, các lần lưu có thể chồng chéo nhau. Hãy điều chỉnh lại trong redis.conf:

# Mặc định (thường quá tích cực với dataset lớn)
save 900 1
save 300 10
save 60 10000

# Thận trọng hơn — chỉ lưu khi có thay đổi đáng kể
save 900 1
save 300 1000

Áp dụng mà không cần khởi động lại:

redis-cli CONFIG SET save "900 1 300 1000"

Để xác nhận cấu hình đang chạy đã có hiệu lực:

redis-cli CONFIG GET save

Kiểm Tra Kết Quả

Xác nhận lần lưu đã hoàn thành thành công:

redis-cli INFO persistence | grep -E "rdb_bgsave_in_progress|rdb_last_bgsave_status|rdb_last_save_time"

Kết quả bình thường trông như thế này:

rdb_bgsave_in_progress:0
rdb_last_bgsave_status:ok
rdb_last_save_time:1714900000

Sau đó kiểm tra file RDB đã được cập nhật:

ls -lh $(redis-cli CONFIG GET dir | tail -1)/$(redis-cli CONFIG GET dbfilename | tail -1)

Thời gian của file phải khớp với lần lưu gần đây của bạn.

Tóm Tắt Nhanh

  • Có thể bỏ qua nếu đang có lần lưu chạy — chỉ cần chờ nó hoàn thành
  • Kiểm tra trạng thái: redis-cli INFO persistence | grep bgsave
  • Đừng bao giờ kill tiến trình con BGSAVE thủ công trừ khi nó chạy nhiều giờ — kill giữa chừng sẽ làm hỏng file RDB
  • LASTSAVE trả về Unix timestamp của lần lưu thành công gần nhất: redis-cli LASTSAVE
  • Để dừng toàn bộ việc lưu: redis-cli CONFIG SET save "" — chỉ làm điều này khi bạn hiểu mình đang từ bỏ tính năng persistence nào

Related Error Notes