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 2, 2025
1 parent bb908bf commit a6e3ec8
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions docs/grokking/chapter-10.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,27 @@

相比固定窗口算法,滑动窗口算法的内存需求更大,这可能会带来可扩展性问题。那么,如果我们结合以上两种算法,是否可以优化内存使用呢?

## 10. 基于计数器的滑动窗口

如果我们通过多个固定时间窗口追踪每个用户的请求计数,例如,将限流的时间窗口分为 1/60 的大小。例如,对于每小时限流,我们可以记录每分钟的计数,并在收到新请求时计算过去一小时内所有计数器的总和,以确定限流阈值。这将减少内存占用。假设我们每小时限流 500 次,并限制每分钟最多 10 次请求。这意味着,当时间戳在过去一小时内的计数器总和超过请求阈值(500)时,Kristie 超过了限流。此外,她每分钟不能发送超过 10 次请求。这是一个合理且实际的考量,因为真实用户不会频繁发送请求。即使他们这样做,限额每分钟重置,他们可以通过重试成功。

我们可以将计数器存储在 Redis 哈希中,因为它对少于 100 个键的存储效率极高。当每次请求递增哈希中的计数器时,同时设置哈希在一小时后过期。我们将每个“时间”归一化到分钟。

![图10-8](/grokking/f10-8.png)

**需要多少内存来存储基于计数器的滑动窗口用户数据?**

假设 `UserID` 占用 8 字节,每个时间戳占用 4 字节,计数器占用 2 字节。假设哈希表有 20 字节开销,Redis 哈希有 20 字节开销。由于我们将为每分钟保存一个计数,每个用户最多需要 60 个条目。我们总共需要 1.6KB 来存储一个用户的数据:

```
8 + (4 + 2 + 20 (Redis hash overhead)) * 60 + 20 (hash-table overhead) = 1.6KB
```

如果我们需要随时追踪 100 万个用户的请求,总内存需求为:

```
1.6KB * 1 million ~= 1.6GB
```

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

Binary file added docs/public/grokking/f10-8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a6e3ec8

Please sign in to comment.