使用RedisBloom防止重复签入

随着我们的应用越来越受欢迎,我们从不断扩大的用户基础中获得了越来越多的签到。我们决定限制这一点,只允许每个用户给每个地点一个特定的星级评级。例如,如果用户100在位置73签到并给它3星,我们希望拒绝他们在该位置的任何3星签到。

为了做到这一点,我们需要一种记住每个签入的方法,并快速确定我们以前是否见过它。我们不能通过查询签入流中的数据来做到这一点,因为流不允许这样的访问,并且会定期修剪,删除已经处理过的、不再需要的旧签入。

我们可以在表单中表示签到<标识>:< locationId >: <评级>.在这个模式中,字符串100733将表示用户100在位置73处的签入,并获得3星评级。

然后我们需要记住每个签入,这样我们就可以确保它是用户ID、位置ID和星级的唯一组合。我们可以使用Redis Set。当我们想要维护一个唯一成员的集合时,集合是很好的,因为它们不允许重复。在Redis Set中,添加新成员和检查成员是否在Set中都是O(1)操作,这意味着它们的性能不会随着Set的增长而下降。

然而,我们添加的每一个Set的新成员(在我们的情况下,这些是唯一的签入)都会导致Set在Redis服务器上占用更多的内存。随着我们收到越来越多的签到,这种增长将成为一个问题。

但是,如果有一种方法可以检查一个潜在的新成员是否已经在一个没有这个内存消耗问题的集合中呢?Bloom Filter是一种空间效率高的概率数据结构,在这里可以有所帮助。Bloom Filters存储Set成员的散列表示,而不是实际的成员数据本身。与Set不同,我们不能从Bloom Filter中取回成员,但我们可以测试是否有东西已经在那里了……带有一些由于散列冲突而导致的误报。当被问及某物是否是集合的成员时,Bloom Filter会告诉我们“no it isn’t”,或者“it’s likely that it is”。

这种哈希方法牺牲了我们使用Set所能获得的100%的准确性,从而极大地减少了内存开销。Bloom Filters可以配置一个期望的可接受的错误率,所以对于我们的应用程序来说,这似乎是一个很好的方法来执行我们的“无重复签入”规则,而不会出现内存消耗失控的问题。每当Bloom Filter告诉我们它可能在之前看到过签入时,它大部分都是正确的,我们也会接受有时我们不允许签入,实际上我们以前没有,作为保持我们的内存使用在控制下的一个明智的权衡。

RedisBloom是Redis的一个模块,为Redis提供了一个Bloom Filter实现,以及其他有用的概率数据结构。在视频中,您将看到在Node.js应用程序中使用它是多么简单,不需要数学技能!

实践锻炼

在本练习中,您将通过多次向系统提交相同的签入来看到Bloom过滤器的作用。

你需要运行Checkin Receiver Service…如果它仍然运行于前面的练习,则使用Ctrl-C停止它。然后,使用以下命令重新启动它。这个命令将禁用我们在本练习中不想要的登录要求:

npm 运行checkinreceiver
> js-crash-course@0.0.1 checkinreceiver
> 节点。/ src / checkinreceiver.js
info:禁用身份验证,签入 不需要有效的用户会话。
info: Checkin receiver listening on port 8082

现在,打开Postman并创建一个新请求,选择“POST”作为HTTP动词。

  • 将URL设置为localhost: 8082 / api /签入
  • 在Body选项卡中,将类型下拉列表设置为“raw”和“JSON”
  • 在主体文本区域,输入以下JSON:
“标识” One hundred. “locationId” 73 “starRating” 3.

你的请求应该是这样的:

签入请求

点击“发送”将您的签入提交到签入接收方,接收方应该以202接受状态和空响应体回应:

202签入响应

第二次点击“发送”,你应该收到来自Checkin Receiver的422不可处理实体响应,以及一条错误消息:

422签入响应

在Checkin Receiver服务仍然运行的情况下,启动生成随机签入的Checkin Generator实用程序:

node-js-crash-course美元 npm 运行checkingenerator
> js-crash-course@0.0.1 checkingenerator
> 节点。/ src / checkingenerator.js
启动签入生成器。

让签入生成器运行。它将每隔几秒产生一个新的随机签入。让它运行并生成几百个签入。在此过程中,使用rediscli或RedisInsight中的CLI选项卡定期监控Bloom Filter所需的内存使用情况:

127.0 .0.1:637 9 > bf.info ncc: checkinfilter
1 能力
2 整数 1000000
3. 大小
4 整数 2576760
5 数量的过滤器
6 整数 1
7 插入项目数
8 整数 269
9 膨胀率
10 整数 2

在生成更多签入时运行几次,注意存储Bloom Filter所需的大小不会随着插入项的增加而增加。虽然牺牲了一些准确性,但Bloom Filters是这种类型用例的高效存储解决方案。

外部资源

在这个视频中,Guy Royse解释了什么是Bloom Filters以及如何在Redis中使用它们:

Redis Sets是一个强大的数据类型,了解更多与安德鲁的两个视频在Redis大学YouTube频道。首先,Redis Sets解释:

其次是Redis集阐述:

Baidu