Skip to content

Commit

Permalink
feat: chapter 10
Browse files Browse the repository at this point in the history
  • Loading branch information
honkinglin committed Jan 3, 2025
1 parent a6e3ec8 commit b5e19a2
Showing 1 changed file with 25 additions and 0 deletions.
25 changes: 25 additions & 0 deletions docs/grokking/chapter-10.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,28 @@

因此,基于计数器的滑动窗口算法比单纯滑动窗口算法节省了 86% 的内存。

## 11. 数据分片与缓存

我们可以基于 `UserID` 进行分片以分配用户数据。为了实现容错和数据复制,我们应该使用一致性哈希(Consistent Hashing)。如果我们希望为不同的 API 设置不同的限流策略,可以选择基于用户和 API 进行分片。例如,在 URL 缩短器的场景中,我们可以为每个用户或 IP 分别设置 `createURL()``deleteURL()` API 的限流器。

如果我们的 API 被分区,一个实际的考虑是为每个 API 分区设置一个单独的(相对较小的)限流器。例如,在 URL 缩短器的场景中,我们希望限制每个用户每小时最多创建 100 个短链接。假设我们对 `createURL()` API 使用基于哈希的分区,可以对每个分区进行限流,限制用户每分钟最多创建 3 个短链接,同时每小时最多创建 100 个短链接。

我们的系统可以通过缓存最近活跃用户的记录获得巨大收益。应用服务器可以在访问后端服务器之前快速检查缓存中是否存在所需记录。我们的限流器可以显著受益于写回缓存(Write-back Cache),仅在缓存中更新所有计数器和时间戳。对永久存储的写操作可以以固定时间间隔完成。这种方式可以确保限流器对用户请求增加的延迟最小。读取操作可以始终优先访问缓存;当用户达到限额时,这种方式非常有用,因为限流器此时仅需要读取数据,而无需更新。

**最近最少使用(LRU)** 是我们系统中一种合理的缓存淘汰策略。

## 12. 应按 IP 还是用户进行限流?

以下是使用每种方案的优缺点:

**按 IP**

在此方案中,我们对每个 IP 的请求进行限流。尽管这种方式在区分“好”用户和“坏”用户方面并不理想,但仍然优于没有限流的情况。IP 基限流的最大问题在于多个用户可能共享一个公共 IP,例如网吧或使用同一网关的智能手机用户。一名恶意用户可能会导致其他用户被限流。此外,在缓存 IP 基限流规则时也可能出现问题,因为 IPv6 提供了巨大的地址空间,黑客甚至可以通过一台电脑生成大量 IPv6 地址,这可能导致服务器因追踪 IPv6 地址而耗尽内存。

**按用户**

限流可以在用户认证后的 API 上进行。一旦认证成功,用户将获得一个令牌,并在每次请求时传递该令牌。这可以确保我们对特定 API 进行限流,而该 API 仅针对具有有效认证令牌的用户。然而,如果我们需要对登录 API 本身进行限流,该方案可能存在弱点。例如,黑客可能通过输入错误的凭据达到限额,从而导致实际用户无法登录。

**混合方案**

一个合理的做法是同时实施按 IP 和按用户的限流,因为单独实施其中一种方案时存在缺点。不过,这种方法会导致更多的缓存条目,并且每条目需要包含更多的详细信息,从而增加内存和存储的需求。

0 comments on commit b5e19a2

Please sign in to comment.