2015-12-30 17 views
5

Tôi đang cố gắng thay thế việc triển khai sql dịch vụ kiểm soát lũ của Drupal 8 bằng cách triển khai dựa trên redis.Thực hiện kiểm soát lũ với redis

Xem https://github.com/drupal/drupal/blob/8.0.x/core/lib/Drupal/Core/Flood/DatabaseBackend.php

Các yêu cầu là như thế này:

  • Mỗi lần xuất hiện của một hành động/sự kiện (ví dụ như cố gắng để đăng nhập) được đăng nhập với thời hạn, định danh và timestamp
  • tôi cần để có thể ngăn chặn một hành động nhất định có thể được thực hiện nhiều hơn N lần trong một khung thời gian nhất định
  • Tôi muốn có thể xóa các sự kiện đã hết hạn
  • Trong trường hợp ngưỡng 3 trong 10 phút, nếu người dùng cố gắng một lần, sau đó hai lần sau 5 phút, anh ta bị chặn và có thể thử lại sau 5 phút nữa. Không 10. Trong khi thứ hai sẽ là một cách hợp lệ để làm điều này, nó không phải là cách thực hiện sql hoạt động hoặc làm thế nào các bài kiểm tra mong đợi nó hoạt động.
  • Như bạn có thể thấy dựa trên API, tôi cũng không biết khi đăng ký sự kiện ngưỡng là gì, tôi chỉ biết hết hạn của một sự kiện.

những suy nghĩ của tôi về cách thực hiện điều này:

  • Nếu sau N lần xuất hiện nên được khóa cho thời gian nhất định, thì đây sẽ là dễ dàng với một chìa khóa duy nhất cho sự kiện: nhận dạng được tăng lên, khi đạt đến mức tối đa, nó sẽ bị khóa cho đến khi nó hết hạn một lần nữa và mỗi INCR cũng sẽ cập nhật hết hạn (hoặc không).
  • Tôi đã tìm thấy nhiều bài đăng hỏi về việc hết hạn các mục nhập danh sách, điều này là không thể. Có cách giải quyết bằng cách sử dụng các bộ sắp xếp và xóa theo phạm vi. Hầu hết dường như sử dụng một tập hợp toàn cầu duy nhất, nhưng sau đó tôi không thể dễ dàng đếm sự kiện + số nhận dạng của mình - tôi nghĩ vậy.

Sau khi viết xong, tôi thực sự có ý tưởng về cách thức hoạt động, vì vậy tôi đoán những gì tôi đang tìm kiếm là phản hồi về việc điều đó có hợp lý hay không.

Mỗi sự kiện: kết hợp số nhận dạng là khóa và chứa tập hợp được sắp xếp. Điều đó sử dụng hết hạn dưới dạng điểm và giá trị là một giá trị duy nhất, có thể là thời gian tạo trong micro giây. Tôi đếm các bản ghi không hết hạn để phát hiện xem đã đạt đến ngưỡng chưa. Tôi đang cập nhật hết hạn của mỗi sự kiện: số nhận dạng đến cửa sổ hết hạn được cung cấp, vì vậy nó sẽ tự động bị xóa giả định trừ khi một số nhận dạng/khách hàng không từ bỏ và tiếp tục thử, mà không bao giờ hết hạn. Có đáng để làm sạch các hồ sơ bên trong một tập hợp hay không. Ví dụ: khi đăng ký mới? Nó có vẻ khá nhanh, và đôi khi tôi cũng có thể làm điều đó.

+0

Nhân tiện, tôi đã triển khai phiên bản đầu tiên tại đây: https://github.com/md-systems/redis/blob/8.x-1.x/src/Flood/PhpRedis.php. Vẫn hy vọng cho một số thông tin phản hồi về việc đó là một cách tiếp cận tốt. – Berdir

+0

Dường như đây là một câu hỏi đánh giá về mã. Tôi đoán bạn nên di chuyển nó ở đây: http://codereview.stackexchange.com/ – t1gor

+0

Điểm tốt, chưa có mã nào khi tạo. Tôi đang tìm kiếm phản hồi về khái niệm mà tôi đã triển khai và ít hơn về mã cụ thể. Nhưng vui lòng di chuyển nó nếu điều đó sẽ có nhiều khả năng dẫn đến một câu trả lời. – Berdir

Trả lời

1

Tôi muốn sử dụng tính năng hết hạn chính của Redis, thay vì thực hiện lại.

Một lựa chọn đơn giản sẽ là một trong sau:

  • chỉ đặt một giá trị đơn giản, đó là số lần; sử dụng một chìa khóa xây dựng trên một mô hình như "định danh": "loại sự kiện": SETNX <identifier>:<event type> 1
  • nếu câu trả lời là 1, đây là nỗ lực đầu tiên, vì vậy bạn thiết lập một thời gian chờ trên phím này: EXPIRE <identifier>:<event type> <timeout in seconds>

  • nếu không bạn tăng số lần thử INCR <identifier>:<event type> Phản hồi của INCR sẽ cho bạn số lần thử trong cửa sổ, vì vậy bạn biết liệu bạn có thể cho phép hành động đó hay không.

Bạn cũng có thể sử dụng một băm thay vì một giá trị đơn giản, nếu bạn cần lưu trữ nhiều dữ liệu hơn, như số lượng tối đa của những nỗ lực cho phép trong cửa sổ thời gian nhất định. Trong trường hợp này, bạn có thể sử dụng HSETNX và HINCR.

+0

Cảm ơn câu trả lời. Đó là cơ bản điểm đầu tiên sau "Suy nghĩ của tôi về cách thực hiện điều này". Như được viết trong yêu cầu thứ 4, điều này dẫn đến một hành vi hơi khác. Sau khi đạt đến giới hạn, nó sẽ khóa cho khung thời gian đã cho. Tuy nhiên, sự mong đợi của giao diện mà tôi đang triển khai là nó sẽ chỉ khóa cho đến khi tôi ở dưới ngưỡng trong khung thời gian đã cho, từ bây giờ trở đi. – Berdir

+0

Có lẽ tôi không hiểu điểm của bạn, nhưng tôi không nghĩ vậy. –

+0

Ah, bạn không đặt hết thời gian, chỉ là ban đầu. Thật. Nhưng nó sẽ có tác dụng ngược lại rồi. Sau khi hết hạn, tôi có thể sử dụng lại ngưỡng đầy đủ. Vì vậy, nếu ngưỡng 5 và hết hạn 5 phút và tôi đang thực hiện X cứ sau 1 phút, thì khi triển khai, tôi có thể thực hiện lại 5 lần ngay sau 5 phút từ sự kiện đầu tiên trong trường hợp của tôi, tôi chỉ có thể làm điều đó một lần , sau đó tôi lại đạt ngưỡng. – Berdir

Các vấn đề liên quan