Tôi đã triển khai tính năng rate/limit cho bình luận như thế nào?

Tôi đã triển khai tính năng rate/limit cho bình luận như thế nào?

Tin ngắn hàng ngày dành cho bạn
  • Sống trong thế giới Internet đủ lâu bạn có thể thấy con người ta trên này cũng chịu khó đu "trend" lắm đấy chứ, đã thế lại còn lan nhanh với tốc độ chóng mặt.

    Mới cách đây vài tháng, chúng ta còn chưa khỏi bàng hoàng về độ thông minh của các mô hình ngôn ngữ lớn (LLM) trả lời y như con người thì ngay sau đó bọn chúng đã được cập nhật thêm khả năng suy nghĩ, suy luận đáng kinh ngạc. Được ứng dụng rộng rãi không chỉ mỗi lĩnh vực lập trình. Rồi mới đây, thuật ngữ AI Agents lại đang làm mưa làm gió.

    Vậy AI Agents là gì? Trong bài viết ngắn này dĩ nhiên là không thể nêu ra một khái niệm vắn tắt mà đầy đủ được hết ý. Bạn đọc có thể tham khảo bài viết rất chi tiết này ở đây Agents | Chip Huyen. Còn cho dễ hình dung, Có thể coi AI Agents như một con người hay một cá thể gì đó. Bản thân Agents được trang bị đầy đủ các công cụ. Từ những thứ đó, Agents có thể kết hợp chúng lại với nhau để hoàn thành một tác vụ mà chúng ta sai bảo.

    Vẫn hơi mơ hồ nhỉ! Một ví dụ sát thực tế nhất là bạn ra lệnh cho Agents mỗi 8 giờ tối, truy cập vào Facebook, đọc xem có tin tức gì nổi bật từ bạn bè không rồi gửi một bản tóm tắt vào Telegram, thế là xong!

    » Xem thêm
  • Hôm qua đến nay, lượt truy cập tới từ Facebook tăng đột biến. Thường như thế là do ai đó chia sẻ bài viết của blog vào một nhóm nào đó.

    Cơ mà lần này là liên kết trực tiếp đến trang chủ luôn. Tò mò ghê, không biết ai chia sẻ, chia sẻ ở đâu nữa. Muốn biết để tìm hiểu "insight" ghê 🥹

    » Xem thêm
  • Mình mới phát hiện ra thư viện idb-keyval giúp triển khai cơ sở dữ liệu dạng key-value một cách đơn giản. Như đã chia sẻ trong chuỗi bài viết về quá trình làm OpenNotas, mình loay hoay đi tìm một loại cơ sở dữ liệu để lưu trữ mà xem chừng vất vả quá, cuối cùng chốt localForage.

    idb-keyval cũng tương tự như localForage nhưng có vẻ như nó đang làm tốt hơn một chút. Đơn cử là có hàm update để cập nhật dữ liệu, hình dung đơn giản là:

    update('counter', (val) => (val || 0) + 1);

    Chứ không như hàm set là thay thế dữ liệu mất tiêu luôn.

    » Xem thêm

Vấn đề

Captcha là một cách thức được sinh ra nhằm mục đích ngăn chặn hành vi spam trên các ứng dụng, đặc biệt là đối với ứng dụng web. Nếu không có captcha, kẻ tấn công có thể dễ dàng tạo ra những đoạn mã tự động gửi truy vấn với tần suất liên tục đến chức năng nào đó nhằm phá hoại hệ thống.

Tuy vậy, captcha không phải không có nhược điểm. Có lẽ hạn chế lớn nhất của nó là gây "lú" cho người dùng. Nhiều đoạn mã được sinh ra để xác minh bạn là con người, nhưng đôi khi bạn phải tự hỏi liệu mình có là người không khi không thể dịch được những kí tự méo mó hoặc mờ tịt kia.

Chức năng bình luận trên 2coffee không sử dụng captcha để tạo ra khó khăn cho người dùng giống như trên. Thay vào đó tôi đã áp dụng một kỹ thuật gọi là "rate/limit" để hạn chế hành vi spam. Nói nôm na, nó ngăn chặn một hành vi liên tục, giới hạn số lần thực hiện trong một khoảng thời gian nhất định. Ví dụ như chỉ cho phép người dùng bình luận tối đa 3 lần trong 1 phút, hay cần phải chờ ít nhất 10 giây để cho lượt gửi bình luận tiếp theo.

Bài viết ngày hôm nay tôi xin phép được tường thuật lại quá trình triển khai tính năng rate/limit của mình. Tôi nghĩ rằng điều đó sẽ giúp ích cho bạn đọc, hoặc hy vọng được nhận lại ý kiến của bạn đọc để có thêm cách triển khai tốt hơn.

Thuật toán

Ý tưởng ban đầu rất đơn giản, vì không quá khắt khe nên tôi quyết định cho phép người dùng được gửi bình luận sau mỗi 10 giây kể từ lần gửi thành công trước đó. Sau khi gửi bình luận thành công ở một bài viết thì cần chờ tối thiểu 10 giây để gửi bình luận ở bất kỳ bài nào.

Lúc này cần triển khai được thuật toán có đầu vào là id người dùng, đầu ra là true/false. True nếu chưa vượt quá limit và false nếu đã bình luận quá nhiều. Dựa vào đó để cho phép họ gửi được hay không.

Có nhiều cách để giải quyết vấn đề này, đơn giản nhất là cứ mỗi lần bình luận sẽ lấy ra bình luận cuối cùng của họ rồi kiểm tra thời gian xem có hợp lệ. Cách này thì triển khai nhanh, đơn giản nhưng nếu sau này bình luận nhiều lên thì truy vấn có phần chậm chạp. Hơn nữa việc mở rộng sau này có phần phức tạp hơn. Ví dụ như thay đổi thuật toán để cho phép họ gửi tối đa 3 bình luận trong thời gian một phút chẳng hạn. Lúc đó truy vấn sẽ phức tạp và nhiều khả năng sẽ chậm hơn.

Vì đang sử dụng Redis, tôi có thêm một cách là tận dụng chức năng khóa hết hạn (ttl) của một key trong Redis. Tôi sẽ tạo ra một key có dạng "comment_limit:" chứa một giá trị boolean có thời gian hết hạn là khoảng thời gian giữa các lần bình luận liên tiếp. Mỗi khi bình luận, chỉ cần kiểm tra key "comment_limit:" có tồn tại hay không, nếu có thì chắc chắn là họ không được phép bình luận và ngược lại.

Ưu điểm của cách này là thời gian kiểm tra điều kiện tương đối nhanh, chỉ mất một truy vấn lấy ra key "comment_limit:". Tuy vậy, cần phải viết nhiều mã hơn để xử lý logic.

Triển khai

Triển khai rất đơn giản, bạn cần có máy chủ Redis để tạo ra các key có ttl. Mỗi khi gọi hàm tạo bình luận thì kiểm tra xem đã có key "comment_limit:" chưa.

Ví dụ trong trường hợp user_id của tôi bằng 1:

GET comment_limit:1

Nếu comment_limit:1 trả về true hãy bắn ra một lỗi không được phép bình luận. Ngược lại nếu là null thì cho phép thêm bình luận rồi sau đó thêm một key comment_limit:1 với thời gian hết hạn là thời gian bạn thiết lập. Giả sử là 10 giây:

SET comment_limit:1 true EX 10

Khi đó, cứ sau 10 giây thì comment_limit:1 sẽ tự động bị xóa và trả lại logic được phép bình luận cho người dùng.

Tổng kết

Có nhiều cách để triển khai thuật toán rate/limit cho phần bình luận. Tôi đang áp dụng cách sử dụng tính năng key tự động xóa kết hợp với việc quy ước tên của key để tạo ra logic kiểm tra tính khả dụng của hoạt động bình luận. Còn bạn có cách nào khác hãy để lại bình luận cho mọi người biết nhé!

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...
Bấm hoặc cuộn mạnh để sang bài mới