Skip to content

Commit 36b15c9

Browse files
committed
feat: chapter 9
1 parent 26ead30 commit 36b15c9

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

docs/grokking/chapter-9.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,36 @@
8484
考虑到数据量每天可能会增长,同时也会删除一些不再被搜索的词条。如果假设每天有2%的新增查询,并且我们维护过去一年的索引,预计的总存储需求为:
8585

8686
**3 GB + (0.02 × 3 GB × 365 天) = 25 GB**
87+
88+
## 6. 数据分区
89+
尽管我们的索引可以轻松地适配到单个服务器上,但为了实现更高的效率和更低的延迟,仍可以对其进行分区。如何有效地对数据进行分区以将其分布到多个服务器上?
90+
91+
### a. 基于范围的分区
92+
假设我们根据短语的首字母将其存储在不同的分区中,例如,将所有以字母“A”开头的术语存储在一个分区中,以“B”开头的存储在另一个分区中,以此类推。对于出现频率较低的字母,还可以将它们合并到一个数据库分区中。
93+
这种分区方案需要在静态情况下设计,以确保数据的存储和查询始终具有可预测性。
94+
此方法的主要问题是可能导致服务器负载不平衡。例如,如果我们将所有以字母“E”开头的术语存储在一个分区中,但后来发现“E”开头的术语数量过多,以至于无法容纳在一个数据库分区中。
95+
上述问题几乎会出现在所有静态定义的分区方案中,因为无法在静态情况下预测每个分区是否能够适配到单个服务器。
96+
97+
### b. 基于服务器最大容量的分区
98+
假设我们根据服务器的最大内存容量对trie结构进行分区。只要服务器内存充足,我们可以将数据存储在该服务器中。当某个子树无法适配当前服务器时,就在此处断开分区,将范围分配给当前服务器,然后转到下一个服务器继续这个过程。例如:
99+
- 第一台服务器存储从“A”到“AABC”的所有术语;
100+
- 第二台服务器存储从“AABD”到“BXA”的术语;
101+
- 第三台服务器存储从“BXB”到“CDA”的术语。
102+
103+
我们可以通过哈希表快速访问这一分区方案:
104+
- 服务器1:A-AABC
105+
- 服务器2:AABD-BXA
106+
- 服务器3:BXB-CDA
107+
108+
**查询场景**
109+
- 如果用户输入“A”,需要同时查询服务器1和服务器2以找到推荐结果;
110+
- 如果用户输入“AA”,仍需查询服务器1和服务器2;
111+
- 当用户输入“AAA”时,只需查询服务器1即可。
112+
113+
可以在trie服务器前设置一个负载均衡器,存储分区映射并将流量重定向到相应的服务器。如果需要从多个服务器查询数据,可以选择在服务器端合并结果,或者让客户端处理合并。如果在服务器端处理合并,则需要在负载均衡器和trie服务器之间添加一个聚合层(称为“聚合服务器”),这些服务器负责从多个trie服务器中聚合结果并返回给客户端。
114+
**缺点**:即使基于最大容量分区,仍可能导致热点问题,例如,对于大量以“cap”开头的查询,请求集中到某一台服务器时会造成高负载。
115+
116+
### c. 基于术语哈希的分区
117+
将每个术语传递给一个哈希函数,由该函数生成服务器编号,然后将术语存储在对应的服务器上。这种方法会使术语分布随机化,从而最大限度地减少热点问题。
118+
**查询过程**:为获取某个术语的联想推荐,需要访问所有服务器并聚合结果。
119+

0 commit comments

Comments
 (0)