用redis实现洪水控制

Ber*_*dir 6 php drupal redis

我正在尝试用基于redis的实现替换Drupal 8的防洪服务的sql实现.

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

要求是这样的:

  • 每次出现的动作/事件(例如,尝试登录)都会记录到期,标识符和时间戳
  • 我需要能够防止某个动作在给定的时间范围内完成N次以上
  • 我希望能够清理过期的事件
  • 在10分钟内阈值为3的情况下,如果用户尝试一次,然后在5分钟后尝试两次,则他被阻止并且可以在5分钟后再次尝试一次.不是10.虽然第二种方法是一种有效的方法,但不是sql实现的工作方式或测试期望它如何工作.
  • 正如您在API中看到的那样,我也不知道在注册事件时阈值是什么,我只知道单个事件的到期时间.

我对如何实现这个的想法:

  • 如果在N次出现之后应该锁定给定时间,那么使用单个KEY for event会很容易:增加的标识符,一旦达到最大值,它将被锁定直到它再次到期并且每个INCR也会更新到期(或不到期).
  • 我发现很多帖子询问列表条目的到期,这是不可能的.有使用排序集的变通方法和按范围删除.大多数似乎使用单个全局集,但我不能轻易计算我的事件+标识符 - 我想.

写完所有这些之后,我可能真的知道它是如何工作的,所以我想我正在寻找的是关于这是否有意义或者是否有更简单的方法的反馈.

每个事件:标识符组合是一个键,包含一个有序集.它使用到期作为分数,并将值用作唯一值,可能是以微秒为单位的创建时间.我计算未过期的记录以检测是否达到阈值.我正在更新每个事件的到期时间:标识符到提供的到期时间窗口,因此除非给定的标识符/客户端不放弃并继续尝试,否则它将被自动删除,而不会达到过期时间.是否值得清理集合中的记录,例如在进行新的注册时?它看起来相当快,我有时也只能这样做.

Pas*_*rer 1

我更愿意使用 Redis 的密钥过期功能,而不是重新实现这一功能。

一种更简单的替代方案如下:

  • 只需设置一个简单的值,即尝试次数;使用基于“identifier”:“event type”等模式构建的键: SETNX <identifier>:<event type> 1
  • 如果响应为 1,则这是第一次尝试,因此您为此键设置超时: EXPIRE <identifier>:<event type> <timeout in seconds>

  • 否则,您将增加尝试次数 INCR <identifier>:<event type> INCR 的响应将为您提供窗口期间的尝试次数,以便您知道是否可以允许该操作。

如果您需要存储更多数据(例如给定时间窗口内允许的最大尝试次数),您还可以使用哈希而不是简单值。在这种情况下,您可能会使用 HSETNX 和 HINCR。