键值存储系统设计(第一部分)
收到许多读者邮件,表示希望阅读更多关于系统设计面试的内容,因此我们将在此主题上进行更深入的探讨。很高兴收到大家的反馈,如果您有任何建议或问题,欢迎通过评论告诉我们。
本周,我将讨论键值存储(Key-Value Store)。键值存储是一种非常强大的技术,几乎应用于世界上的每个系统中。它可以像哈希表一样简单,也可以演变为复杂的分布式存储系统。例如,Cassandra 的底层系统就是键值存储,而 Cassandra 被广泛用于许多公司,如 Apple、Facebook 等。
在本文中,我将介绍基本键值存储系统、分布式键值存储以及包括分片(Sharding)在内的扩展问题,所有这些都可能在系统设计面试中涉及。
基本键值存储 (Basic Key-Value Store)
您将如何在单台机器上设计一个简单的键值存储系统?
最简单的方法是使用哈希表(Hash Table)存储键值对,这是当今大多数此类系统的工作方式。哈希表使您可以在恒定时间(O(1))内读取/写入键值对,并且非常易于使用。大多数编程语言对此都有内置支持。
但是,缺点也很明显。使用哈希表通常意味着您需要将所有内容存储在内存中,这在数据集很大时可能无法实现。有两种常见的解决方案:
- 压缩数据。这应该是首先要考虑的事情,通常会有很多东西可以压缩。例如,您可以存储引用(Reference)而不是实际数据。您也可以使用
float32而不是float64。此外,使用不同的数据表示形式(例如位数组(Bit Array)或向量)也可能有效。 - 存储在磁盘中。如果不可能将所有内容都放入内存中,则可以将部分数据存储到磁盘中。为了进一步优化,您可以将系统视为缓存系统:经常访问的数据保存在内存中,其余数据保存在磁盘上。
分布式键值存储 (Distributed Key-Value Store)
最有趣的主题肯定是将键值存储扩展到多台计算机。如果要支持大数据,则一定要实现分布式系统。让我们看看如何设计分布式键值存储系统。
如果您已阅读 Design a Cache System,那么您会发现这里的许多概念是完全相同的。
由于单台计算机没有足够的存储空间来存储所有数据,因此这里的总体思路是按照某些规则将数据拆分为多台计算机,并且协调器(Coordinator)计算机可以将客户端定向到具有请求资源的计算机。问题是如何将数据分成多台计算机,更重要的是,什么是分割数据的好策略?
分片 (Sharding)
假设所有键都是 URL,例如 http://gainlo.co,我们有 26 台计算机。一种方法是根据 URL 的第一个字符("www"之后)将所有密钥(URL)划分给这 26 台计算机。例如,http://gainlo.co 将存储在机器 G 上,而 http://blog.gainlo.co 将存储在机器 B 上。那么,这种设计的缺点是什么?
让我们忽略 URL 包含非 ASCII 字符的情况。好的分片算法应该能够均衡所有计算机的流量。换句话说,理想情况下,每台计算机应收到相等的请求。显然,以上设计无法正常工作。首先,存储空间分布不均。以 "a" 开头的 URL 可能比 "z" 更多。其次,某些 URL 更受欢迎,例如 Facebook 和 Google,这会导致热点問題。
为了平衡流量,最好确保密钥是随机分配的。另一种解决方案是使用 URL 的哈希(Hash),通常具有更好的性能。要设计好的分片算法,您应该充分了解应用程序,并可以估计系统的瓶颈。
总结 (Summary)
关于键值存储的话题太多了,我几乎无法将它们全部写成一篇文章。如您所见,在扩展系统时,要考虑的问题更多,这就是为什么许多人发现分布式系统很困难的原因。
在 下一篇文章 中,我们将继续讨论,并将涵盖有关扩展系统的更多信息。将讨论诸如系统可用性(Availability)、一致性(Consistency)之类的问题。
说明:本文内容基于较早的技术讨论(部分参考链接指向 2016 年左右的文章),主要侧重于系统设计的基础原理与面试思路。文中提到的外部链接可能随时间失效,具体技术实现请参考相关项目的最新官方文档。
版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
本文地址:https://1diff.fun/archives/jian-zhi-cun-chu-xi-tong-she-ji--di-yi-bu-fen.html
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。