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?

Những mẩu tin ngắn hàng ngày dành cho bạn
  • Mọi người đã nghe nói đến JSR chưa? Đó là một nền tảng tương tự như npm nhưng có rất nhiều cải tiến đáng kể.

    Cụ thể, JSR hỗ trợ TypeScript, tức là một số runtime hỗ trợ TS như Deno có thể dùng luôn mà không cần phải qua một bước chuyển đổi về JavaScript. Bên cạnh đó JSR tập trung hỗ trợ cho nhiều môi trường chạy mã khác như Bun, Deno, Cloudflare workerd... Còn nữa, các gói xuất bản trên đây phải tuân thủ theo ESM modules.

    JSR không nhằm mục đích thay thế npm, mà chỉ đơn giản là tham gia vào hệ sinh thái với những cải tiến hợp thời.

    » Xem thêm
  • Google Chrome vừa làm mới lại tính năng "Search your tabs" có ở trên thanh địa chỉ. Chỉ cần gõ vào kỹ tự @ bạn sẽ thấy nó gợi ý ra 4 tính năng rất rõ ràng. Ví dụ muốn chat nhanh với Gemini thì gõ @gemini rồi thêm dấu cách là đi vào đề luôn 😆

    » Xem thêm
  • Sáng sớm đọc được bài viết này mà chạnh lòng quá mọi người I am rich and have no idea what to do with my life.

    Bài viết là của một người giàu có đã bán công ty của mình và đang vật lộn với việc tìm kiếm mục đích sống. Không ai khác chính là Vinay Hiremath - đồng sáng lập của Loom. Tự nhiên nghe đến đây lại nhớ đến câu nói nổi tiếng "Tiền nhiều để làm gì?".

    Giàu thì giàu thật nhưng cuộc đời anh cũng lắm thăng trầm. Bạn có bao giờ nghĩ một ngày nào đó mình sẽ giàu lên chưa? Lúc đó thì mục đích sống của bạn là gì? 🤔

    » 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

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? 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