Sử Dụng Script Lua trong Redis để Kiểm Soát Tần Suất Truy Cập

Từ phiên bản 2.6, Redis đã tích hợp khả năng thực thi các script được viết bằng ngôn ngữ Lua. Tính năng này mang lại nhiều lợi ích đáng kể cho các nhà phát triển:

  • Giảm thiểu chi phí mạng: Thay vì gửi nhiều lệnh riêng lẻ qua mạng, một script Lua duy nhất có thể gói gọn một chuỗi thao tác phức tạp. Điều này giúp giảm đáng kể số lượng lượt đi lại (round-trip time) giữa client và server, qua đó tối ưu hiệu suất mạng.
  • Đảm bảo tính nguyên tử: Redis xử lý toàn bộ script Lua như một khối lệnh đơn lẻ. Trong suốt quá trình thực thi script, không có lệnh nào khác có thể chen vào, đảm bảo tính nhất quán và nguyên tử của các thao tác dữ liệu.
  • Khả năng tái sử dụng: Khi một script được gửi tới Redis lần đầu, nó sẽ được lưu trữ vĩnh viễn trên server. Các client khác có thể gọi lại script này bằng một mã hash thay vì phải gửi lại toàn bộ mã nguồn, giúp tiết kiệm băng thông và đơn giản hóa logic phía client.

Triển khai cơ chế giới hạn tần suất truy cập bằng Script Lua

Để minh họa sức mạnh của script Lua trong Redis, chúng ta sẽ xây dựng một ví dụ về việc kiểm soát tần suất truy cập. Giả sử cần giới hạn số lượng yêu cầu mà một địa chỉ IP hoặc người dùng có thể thực hiện trong một khoảng thời gian nhất định.

Hãy tạo một tệp có tên access_limit.lua trên máy client của Redis với nội dung sau:

local current_requests = redis.call('incr', KEYS[1])

if current_requests == 1 then
    -- Nếu đây là lần truy cập đầu tiên trong cửa sổ thời gian này, đặt thời gian hết hạn cho khóa.
    redis.call('expire', KEYS[1], ARGV[1])
end

-- Kiểm tra xem số lượng yêu cầu hiện tại có vượt quá giới hạn cho phép không.
local max_allowed = tonumber(ARGV[2])
if current_requests > max_allowed then
    return 0 -- Vượt quá giới hạn
else
    return 1 -- Vẫn trong giới hạn
end

Để kiểm tra script này, bạn có thể sử dụng công cụ redis-cli. Giả sử chúng ta muốn giới hạn một IP cụ thể chỉ được truy cập tối đa 4 lần trong 30 giây. Sử dụng lệnh sau:

redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4

Trong lệnh trên:

  • --eval: Chỉ thị cho redis-cli rằng chúng ta muốn chạy một script Lua.
  • access_limit.lua: Đường dẫn đến tệp script Lua.
  • api:rate:192.168.1.100: Đây là khóa (key) mà script sẽ thao tác, được truy cập bên trong script bằng KEYS[1]. Nó đại diện cho định danh của đối tượng cần giới hạn (ví dụ: địa chỉ IP).
  • ,: Dấu phẩy này là bắt buộc và dùng để phân tách giữa các khóa (KEYS) và các đối số (ARGV). Không được bỏ qua khoảng trắng xung quanh dấu phẩy.
  • 30: Đây là đối số đầu tiên, được script truy cập qua ARGV[1]. Nó chỉ định thời gian tồn tại của khóa (key) tính bằng giây (ví dụ: 30 giây).
  • 4: Đây là đối số thứ hai, được script truy cập qua ARGV[2]. Nó chỉ định số lượng yêu cầu tối đa cho phép trong khoảng thời gian đã đặt (ví dụ: 4 lần).

Khi bạn liên tục chạy lệnh này trong terminal, bạn sẽ thấy kết quả thay đổi. Script sẽ trả về 1 nếu số lượng truy cập trong 30 giây không vượt quá 4 lần, và 0 nếu đã vượt quá giới hạn.

Ví dụ minh họa:

# Lần truy cập thứ 1
redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4
(integer) 1

# Lần truy cập thứ 2
redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4
(integer) 1

# Lần truy cập thứ 3
redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4
(integer) 1

# Lần truy cập thứ 4 (vẫn trong giới hạn)
redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4
(integer) 1

# Lần truy cập thứ 5 (vượt quá giới hạn)
redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4
(integer) 0

# Lần truy cập thứ 6 (tiếp tục vượt quá giới hạn)
redis-cli --eval access_limit.lua api:rate:192.168.1.100 , 30 4
(integer) 0

Thẻ: Redis lua scripting Rate Limiting Data Structures performance optimization

Đăng vào ngày 26 tháng 7 lúc 06:43