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 c1cf6ba commit bb908bf
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions docs/grokking/chapter-10.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,37 @@

在实际中,我们可以采用 Redis 或 Memcached 等分布式方案。所有数据都会存储在远程的 Redis 服务器中,所有限流器节点在允许或拒绝请求之前,都会先去读写这些远程服务器的数据。

## 9. 滑动窗口算法

如果我们能够追踪每个用户的每个请求,就可以维护一个滑动窗口。我们可以将每次请求的时间戳存储在 Redis 的有序集合(Sorted Set)的哈希表的“值”字段中。

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

假设我们的限流器允许每个用户每分钟最多发出 3 次请求,当有新请求到达时,限流器将执行以下步骤:

1. 从有序集合中移除所有早于“当前时间 - 1分钟”的时间戳。
2. 统计有序集合中的元素总数。如果此计数超过我们的限流阈值“3”,则拒绝请求。
3. 将当前时间插入有序集合中并接受请求。

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

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

假设 `UserID` 占用 8 字节,每个时间戳(epoch time)占用 4 字节。有序集合有 20 字节的开销,哈希表有 20 字节的开销。如果我们需要限制每小时 500 次请求,单个用户的数据总占用为 12KB:

```
8 + (4 + 20 (sorted set overhead)) * 500 + 20 (hash-table overhead) = 12KB
```

其中每个元素保留了 20 字节的开销。在有序集合中,为了维护元素之间的顺序,我们需要至少两个指针:一个指向前一个元素,一个指向下一个元素。在 64 位机器上,每个指针占用 8 字节,因此需要 16 字节来存储指针。我们还添加了一个额外的字(4 字节)来存储其他开销。

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

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

**滑动窗口算法的问题**

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

0 comments on commit bb908bf

Please sign in to comment.