Trong hệ thống phân tán triển khai nhiều máy chủ, người dùng thường xuyên gặp lỗi đăng nhập thất bại kèm hiệu năng ứng dụng giảm mạnh. Phân tích chi tiết cho thấy nguyên nhân liên quan đến kết nối Redis.
Phân tích sự cố
Khi đăng nhập thành công, hệ thống chuyển hướng sang dự án khác và truy vấn cache quyền từ Redis. Log ứng dụng xuất hiện lỗi kết nối timeout lặp lại:
java.net.SocketTimeoutException: connect timed out
at redis.clients.jedis.Connection.connect(Connection.java:134)
at com.tools.cache.DataStore.checkExist(DataStore.java:267)
at com.enterprise.auth.service.PermissionService.getPermissions(PermissionService.java:23)
...
Quy trình chẩn đoán
Kiểm tra tài nguyên hệ thống:
- Lưu lượng mạng bình thường (873.74 rxpck/s, 257.58 txpck/s)
- CPU rảnh 98.7% (load average: 0.00)
- Bộ nhớ vật lý còn trống 4.5GB nhưng swap đang sử dụng 997MB
Phân tích Redis:
- Log Redis không ghi nhận lỗi
- Kết quả benchmark áp lực hoạt động ổn định
- Slow log ghi nhận truy vấn chậm 55ms (dưới ngưỡng cấu hình 10,000ms)
- Bộ nhớ Redis chỉ sử dụng 27.19MB
Phát hiện bất thường:
Thống kê I/O disk cho thấy mức sử dụng cao (sdb: %util 89.90). Sử dụng iotop phát hiện tiến trình kswapd0 chiếm dụng tài nguyên đáng kể - tiến trình này kích hoạt khi hệ thống thiếu bộ nhớ vật lý.
Xác định nguyên nhân gốc
Script kiểm tra swap space:
#!/bin/bash
echo "PID\t\tBoNhoSwap\tTenTienTrinh"
for pid in $(ls -l /proc | awk '/^d[0-9]+/ {print $9}')
do
if [ $pid -eq 1 ]; then continue; fi
swap_kb=$(grep Swap /proc/$pid/smaps 2>/dev/null | awk '{sum+=$2} END{print sum}')
if [ $swap_kb -gt 0 ]; then
ten_tien_trinh=$(ps -p $pid -o comm=)
echo -e "$pid\t${swap_kb}KB\t$ten_tien_trinh"
fi
done | sort -k2 -n
Kết quả cho thấy tiến trình Redis đang lưu trữ hoàn toàn trong swap space dù còn 1GB RAM trống. Nguyên nhân do tham số kernel vm.swappiness đang ở mức 60 (mặc định), khiến hệ thống ưu tiên sử dụng swap khi RAM còn trống.
Giải pháp
Bước 1: Giải phóng bộ nhớ tạm thời
echo 1 > /proc/sys/vm/drop_caches
Bước 2: Điều chỉnh tham số kernel
sysctl vm.swappiness=10
echo "vm.swappiness=10" >> /etc/sysctl.conf
Bước 3: Khởi tạo lại swap
swapoff -a && swapon -a
Sau khi áp dụng các thay đổi và khởi động lại máy chủ, tiến trình Redis sử dụng trực tiếp bộ nhớ vật lý. Thông số swap space giảm về 0, sự cố timeout kết nối được giải quyết hoàn toàn.