Cấu hình Persistence: RDB và AOF cho từng Node
Redis Cluster lưu trữ dữ liệu vào RAM, nhưng để đảm bảo an toàn khi mất điện hoặc crash, ta cần cấu hình cơ chế persistence. Với kiến trúc Cluster 3 Master + 3 Replica, ta sẽ áp dụng AOF (Append Only File) cho các node Master để đảm bảo tính toàn vẹn dữ liệu cao nhất, và RDB (Snapshot) cho các node Replica để phục hồi nhanh.
Trước tiên, hãy xác định file cấu hình của Redis. Nếu bạn cài đặt từ source code như Phần 2, file này thường nằm tại redis.conf trong thư mục cài đặt. Nếu dùng package manager, nó nằm tại /etc/redis/redis.conf. Hướng dẫn dưới đây giả định bạn đang cấu hình file redis.conf tại thư mục /etc/redis/6379.conf (ví dụ cho node Master đầu tiên).
Ta sẽ cấu hình AOF với chế độ everysec để cân bằng giữa hiệu năng và độ an toàn, đồng thời tắt RDB snapshot để tránh xung đột ghi.
Sửa file cấu hình /etc/redis/6379.conf với nội dung sau:
# --- Persistence Configuration for Master Node ---
# Tắt RDB Snapshot để tránh ghi trùng lặp khi đang dùng AOF
save ""
# Bật AOF
appendonly yes
# Đặt tên file AOF
appendfilename "appendonly.aof"
# Chế độ fsync: fsync mỗi giây (cân bằng giữa tốc độ và an toàn)
appendfsync everysec
# Cho phép AOF rewrite tự động để giảm kích thước file
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# Bật AOF load ở chế độ RDB nếu file AOF bị lỗi (phục hồi nhanh hơn)
aof-load-truncated yes
Sau khi lưu file, hãy thực hiện lệnh restart service Redis trên node Master để áp dụng thay đổi. Kết quả mong đợi là Redis khởi động lại và ghi log Background append only file rewriting started nếu có dữ liệu cũ.
Áp dụng cho các Node Replica
Các node Replica trong Redis Cluster không nên chạy AOF vì chúng chỉ đồng bộ dữ liệu từ Master. Nếu Master và Replica cùng ghi AOF, khi xảy ra failover, Replica mới sẽ mất dữ liệu trong khoảng thời gian đồng bộ. Ta sẽ cấu hình RDB snapshot cho Replica.
Sửa file cấu hình cho node Replica (ví dụ /etc/redis/6380.conf):
# --- Persistence Configuration for Replica Node ---
# Tắt AOF
appendonly no
# Bật RDB snapshot với chu kỳ:
# - Sau 900 giây (15 phút) nếu có ít nhất 1 key thay đổi
# - Sau 300 giây (5 phút) nếu có ít nhất 100 keys thay đổi
# - Sau 60 giây nếu có ít nhất 10000 keys thay đổi
save 900 1
save 300 100
save 60 10000
# Đặt tên file dump RDB
dbfilename "dump.rdb"
# Sử dụng dir riêng để tránh ghi đè vào thư mục AOF
dir /var/lib/redis/6380
Khởi động lại Redis trên các node Replica. Kết quả mong đợi là Redis chạy ổn định và file dump.rdb được tạo ra sau khi có thay đổi dữ liệu đủ điều kiện.
Verify Persistence
Để kiểm tra xem cấu hình đã áp dụng đúng, hãy chạy lệnh redis-cli kết nối vào node Master và dùng lệnh CONFIG GET:
redis-cli -p 6379 CONFIG GET appendonly
Kết quả phải trả về yes. Tương tự, kiểm tra RDB trên node Replica:
redis-cli -p 6380 CONFIG GET save
Kết quả phải trả về chuỗi các giá trị thời gian và số lượng key thay đổi như đã cấu hình.
Tối ưu hóa Memory: Maxmemory và Eviction Policy
Redis là database dựa trên RAM. Nếu bộ nhớ đầy, Redis sẽ từ chối ghi dữ liệu trừ khi ta cấu hình một chính sách "đẩy" (eviction) các key cũ ra ngoài. Trong môi trường production, ta luôn đặt giới hạn maxmemory thấp hơn tổng RAM vật lý của máy chủ để tránh OOM Killer của Linux can thiệp.
Giả sử server có 8GB RAM, ta nên đặt maxmemory khoảng 6GB để còn chỗ cho OS và các tiến trình khác. Policy được chọn là allkeys-lru (Least Recently Used) để xóa các key ít được truy cập nhất khi bộ nhớ đầy.
Sửa file cấu hình /etc/redis/6379.conf (áp dụng cho tất cả node Master và Replica):
# --- Memory Configuration ---
# Đặt giới hạn bộ nhớ (ví dụ: 6GB)
maxmemory 6gb
# Chính sách xóa key khi đầy bộ nhớ:
# - allkeys-lru: Xóa key ít dùng nhất trong tất cả các key (phù hợp cho cache)
# - volatile-lru: Chỉ xóa key có TTL trong nhóm ít dùng nhất
# - noeviction: Không xóa key, trả lỗi khi đầy (mặc định)
maxmemory-policy allkeys-lru
# Bật theo dõi bộ nhớ
maxmemory-samples 5
Lưu ý: Nếu bạn muốn áp dụng chính sách này cho toàn bộ Cluster, hãy cấu hình tương tự trên file config của 3 node Master và 3 node Replica. Sau đó, restart Redis trên tất cả các node.
Để kiểm tra nhanh mà không cần restart, bạn có thể dùng lệnh CONFIG SET (thay đổi tạm thời khi đang chạy):
redis-cli -p 6379 CONFIG SET maxmemory 6gb
redis-cli -p 6379 CONFIG SET maxmemory-policy allkeys-lru
Kết quả mong đợi là Redis trả về OK. Khi bạn ghi dữ liệu vượt quá 6GB, Redis sẽ tự động xóa các key ít dùng nhất và không bị lỗi OOM command not allowed when used memory > 'maxmemory'.
Verify Memory Usage
Chạy lệnh INFO memory để xem trạng thái bộ nhớ:
redis-cli -p 6379 INFO memory | grep used_memory_human
Để test chính sách eviction, hãy tạo một lượng dữ liệu lớn hơn giới hạn (ví dụ dùng script Python hoặc Lua) và quan sát số lượng key bị xóa trong phần evicted_keys của output INFO memory.
Tinh chỉnh Mạng: TCP Backlog và Timeout
Khi Redis Cluster phải xử lý hàng nghìn kết nối đồng thời, cấu hình mặc định của Linux và Redis có thể gây ra tình trạng từ chối kết nối (Connection refused) hoặc treo. Ta cần tinh chỉnh tcp-backlog để tăng độ dài hàng đợi kết nối và timeout để đóng các kết nối rảnh (idle) giúp giải phóng tài nguyên.
Tham số tcp-backlog xác định số lượng kết nối đang chờ chấp nhận tối đa. Mặc định thường là 128, ta nên tăng lên 512 hoặc 1024 cho môi trường cao tải.
Tham số timeout xác định thời gian Redis giữ một kết nối không hoạt động trước khi đóng. Mặc định là 0 (không bao giờ đóng), ta nên đặt là 300 giây (5 phút) để tránh tích tụ các socket "zombie".
Sửa file cấu hình /etc/redis/6379.conf:
# --- Network Tuning ---
# Tăng độ dài hàng đợi kết nối TCP
tcp-backlog 1024
# Đóng kết nối idle sau 300 giây
timeout 300
# Tăng giới hạn file descriptor (cần phối hợp với ulimit của OS)
# Redis mặc định thường là 10000, tăng lên 20000
maxclients 20000
# Bật TCP Keepalive để phát hiện kết nối chết
tcp-keepalive 60
Quan trọng: Để maxclients hoạt động, bạn cần đảm bảo kernel Linux cho phép mở đủ số file descriptor. Hãy kiểm tra và tăng giới hạn này trong file /etc/security/limits.conf:
# Thêm dòng sau vào /etc/security/limits.conf
redis soft nofile 20000
redis hard nofile 20000
# Nếu chạy dưới user root hoặc system, thêm dòng này:
* soft nofile 20000
* hard nofile 20000
Sau khi cấu hình, restart service Redis. Kết quả mong đợi là Redis có thể chấp nhận hàng nghìn kết nối đồng thời mà không báo lỗi max clients reached hoặc connection refused do backlog đầy.
Verify Network Settings
Chạy lệnh kiểm tra số lượng kết nối hiện tại và giới hạn:
redis-cli -p 6379 INFO clients | grep connected_clients
redis-cli -p 6379 CONFIG GET tcp-backlog
Bạn cũng có thể kiểm tra số lượng file descriptor đang mở của tiến trình Redis bằng lệnh cat /proc//limits để đảm bảo nó đã được nâng lên 20000.
Cấu hình Cluster-Announce-IP cho NAT và Docker
Với kiến trúc Cluster, các node cần biết địa chỉ IP của nhau để giao tiếp nội bộ. Tuy nhiên, trong môi trường Docker hoặc khi sử dụng NAT (Network Address Translation), địa chỉ IP bên trong container (ví dụ: 172.17.0.2) khác với địa chỉ IP mà client bên ngoài hoặc các node khác nhìn thấy (ví dụ: 192.168.1.10).
Redis mặc định sẽ tự động quảng bá IP bên trong container, gây ra lỗi kết nối khi các node khác cố gắng liên lạc qua IP đó. Tham số cluster-announce-ip cho phép ta chỉ định rõ địa chỉ IP mà node này sẽ thông báo cho các node khác.
Xác định địa chỉ IP công khai (Public IP) hoặc IP của Gateway mà các node khác có thể truy cập được. Giả sử IP này là 192.168.1.10.
Sửa file cấu hình /etc/redis/6379.conf:
# --- Cluster Announcement Configuration ---
# Chỉ định IP mà node này thông báo cho cluster (IP bên ngoài/NAT)
cluster-announce-ip 192.168.1.10
# Chỉ định port mà node này thông báo (thường là port cluster bus: port + 10000)
# Nếu port Redis là 6379, thì port cluster bus là 16379
cluster-announce-port 6379
cluster-announce-bus-port 16379
# (Tùy chọn) Chỉ định hostname nếu dùng DNS thay vì IP
# cluster-announce-hostname my-redis-node-1.example.com
Áp dụng cấu hình này cho tất cả các node (Master và Replica) với địa chỉ IP tương ứng của từng node. Lưu ý: Nếu bạn đang chạy trên Docker, hãy đảm bảo container được chạy với chế độ --network host hoặc cấu hình port mapping đúng, và cluster-announce-ip phải là IP của host machine, không phải IP của container.
Sau khi sửa config, bạn cần thực hiện CLUSTER MEET lại hoặc restart Redis để các node cập nhật lại bảng định tuyến (cluster table).
# Ví dụ: Restart node và force join lại nếu cần
systemctl restart redis@6379
redis-cli -p 6379 CLUSTER MEET 192.168.1.11 6380
Kết quả mong đợi là lệnh CLUSTER NODES trả về địa chỉ IP đúng (192.168.1.x) thay vì IP nội bộ Docker (172.17.x).
Verify Cluster Announce
Chạy lệnh CLUSTER NODES trên bất kỳ node nào trong cluster:
redis-cli -p 6379 CLUSTER NODES
Kiểm tra dòng output tương ứng với node bạn vừa cấu hình. Địa chỉ IP hiển thị phải trùng khớp với giá trị cluster-announce-ip bạn đã đặt. Nếu thấy IP nội bộ Docker, cấu hình chưa.
Điều hướng series:
Mục lục: Series: Triển khai Database Caching với Redis Cluster và Ubuntu 24.04
« Phần 4: Xây dựng và khởi tạo Redis Cluster với 3 Master và 3 Replica
Phần 6: Quản lý, mở rộng và xử lý sự cố (Troubleshooting) trong Redis Cluster »