了解如何在你的系统设计中使用Dynamo系列、AWS DynamoDB、Cassandra和SimpleDB
◆ 在我们开始之前的快速介绍
早在2004年,亚马逊正在运行一个大型的分布式Oracle数据库集群。想象一下,大量的服务器,运行大量笨重的闭源专有软件,并没有真正关注规模和可用性。他们在当时的规模下挑战了商业数据库的极限。
重要的是要了解这是个不同的时代。分布式系统并不常见,关系型数据库是唯一的主要OLTP数据库,最重要的是,当时没有足够的人或数据在线。
看到互联网在过去十年或二十年里的爆炸性增长,真是太疯狂了!
此时,亚马逊的服务正处于突破当时传统SQL数据库规模的边缘,他们决定需要一个长期可持续的解决方案来继续以他们的速度增长。
关系型数据库是复杂的系统。它们在你可以运行的查询类型方面给你很大的灵活性,给你很强的ACID兼容性,在表之间建立关系,并有能力连接表。这些功能不是免费的,是有代价的。其代价通常是有限的扩展性、可用性和较低的性能。
正如亚马逊的首席技术官Werner Vogels解释的那样, 他们评估了他们70%的操作是基于主键的,另外20%没有使用任何类型的JOIN。因此,他们正在使用关系型数据库,但他们意识到他们并不真正需要关系型数据库提供的大部分优势。此外,他们在横向扩展他们的数据库方面面临着困难。
因此,他们在内部建立了一个名为 "Dynamo"的内部数据库,并对其进行了数年的测试。2007年,他们公开发布了一份白皮书:"Dynamo, 亚马逊的高可用键值存储",以帮助其他在关系型数据库中面临类似可扩展性问题的人。
这篇论文大受欢迎,成为NoSQL数据库背后的驱动力,现在NoSQL数据库已经成为任何大型科技组织的技术栈的重要组成部分。正如Werner Vogels所描述的,"Dynamo论文广受好评,成为创建今天通常称为'NoSQL'的分布式数据库技术类别的催化剂。'"
Dynamo能够处理大量的规模,单个表能够每秒提供数千万个请求。最初的Dynamo在2017年就能每秒提供1290万个请求。我相信,现在的DynamoDB加强了很多,可能会进一步突破极限。
Dynamo最终激发了当今许多最流行的数据库,如AWS的SimpleDB和DynamoDB,以及Cassandra。这些数据库中的大多数,如Cassandra,和DynamoDB最后都与Dynamo论文非常相似,通常有相同的优点和缺点。了解Dynamo论文也会帮助你更好地理解这个Dynamo系列的数据库。
当我读到这个似乎是有史以来最神奇的数据库的成功、性能和几乎像童话一样的故事时,我想知道为什么其他数据库仍在使用?亚马逊的工程师们最终用什么来换取这些在性能、规模和可用性方面的巨大收益?无限规模的实际成本是多少?它是否负担得起?
◆ Dynamo系统的快速概述
Dynamo描述了一个由多个节点构建的分布式数据库系统。
这些数据库可以在彼此完全隔离的情况下运行,事实上,它们在物理上位于世界的不同地方。
它描述了该系统将是一个无主的系统。这意味着所有的节点都是同质的,行为都是一样的。
所有的数据都会分布在这些相同的节点中,然后在它们之间进行复制。例如,如果我不得不存储两行,比方说雇员数据,dynamo内部会将其存储为以下内容。
请注意,数据甚至可以在不同的洲上进行复制!
为了保证性能,集群往往不会等待所有节点真正写入数据。例如,要写一个ID为3的新员工,Dynamo可能会等待一个节点真正确认写入,而其他节点甚至没有完成写入数据到磁盘,Dynamo可能会返回一个响应给用户,说写入已经完成。
这意味着你的整个数据库集群可能处于不一致的状态,一些节点可能会存储某些行,而另一些节点可能不会。例如,在上图中,有两个节点没有完成写入新行,而其中一个节点已经完成。这意味着,在某种意义上,这些节点在行是否存在的问题上彼此不一致。不要担心,这很正常。
最终,所有的节点都将完成新行的写入,集群将处于一致状态。这是一个最终一致的数据模型,因为整个集群最终都会达到一致。
在我继续之前,有必要指出这个新实体的存在,即集群。在我职业生涯的早期,我曾在一台服务器上运行一个Postgres数据库,所以当我被介绍到分布式数据系统的想法时,我很难理解集群的概念。
为了更好地理解这一点,不要把节点想成你必须管理的单个节点。想想一个全新的实体,即集群。这个集群是由这些运行在服务器上的单个更小、更简单的数据库进程组成的。
集群实际上是在管理这些节点,照顾它们的健康,以及它们的通信,在需要时使更多的节点上升,在不需要时使节点下降。
有点像分行经理。
节点本身也意识到集群,并意识到它们是集群的一部分。节点之间可以相互交谈,讨论与集群有关的信息。
你作为一个客户会经常与集群进行互动,并经常关心整个集群所表现出来的特征,而不是个别节点。例如,集群可能处于不一致的状态,因为有些节点会存储更新的数据,而有些则可能没有。
◆ Dynamo的论文如何改变了世界
亚马逊的首席技术官维尔纳-沃格尔斯(Werner Vogels)说。
"Dynamo的论文广受好评,成为创建今天通常称为 "NoSQL "的分布式数据库技术类别的催化剂。"
Dynamo启发了许多其他的NoSQL数据库,并为大规模的高可用分布式数据存储创建了一个框架。它已经被引用了2000多次,并影响了各种数据库中分布式数据存储的工作方式。
简单地说,简单的关系型数据库根本无法维持现代应用程序的写入能力。大多数大型科技公司,如Netflix、苹果、Discord、AirBnB等,都使用Dynamo系列数据库(DynamoDB、Cassandra等)中的一种。
"改变世界 "可能是一种夸张的说法,但Dynamo论文绝对是最具影响力的白皮书之一,并影响了许多现有的大型科技公司。
◆ 主要收获和权衡
◆ 键值存储
Dynamo提出了一个键值数据存储,这意味着不支持表,也不支持关系,等等。
你只能存储键和它们相应的值。你使用的键将是你的分区键,这就是Dynamo用来计算将你的数据放在哪个分区的键。或者,从另一个角度看,分区键决定了你的数据将进入哪个节点。
分区键必须是唯一的,为了确保在各节点间的平等分配,它应该能够有一大组分布大致相同的值。
例如,假设我必须存储这些数据。
| ID | Name | Location --------------------------------------------------------- | 1 | Sanil Khurana | Delhi | 2 | Prerna Sharma | Delhi | 3 | Shivam Kalra | Bangalore | 4 | Nilesh Jain | Delhi | 5 | Hardik | Chennai
如果我选择Location作为分区键,这将意味着我的集群中的每个节点将负责存储与某一组地点相关的数据。
在上面的例子中,你可以看到,每个节点都被指定为存储一个位置。
这已经显示出问题。根据人口和你的组织可能针对的地点,有些地方必然比其他地方更受欢迎。例如,你的平台在德里比在钦奈被更多地使用。这导致了数据在你的节点上的不平衡分布。由于所有的节点都是同质的,你正在浪费那些没有存储大量数据的节点的资源。
然而,基于ID的数据存储可能要好得多。你的应用逻辑可以为每个数据项分配一个增量ID或一个随机ID,你可以根据这个ID来划分你的数据。
尽管这种数据模型相当简单,但Dynamo系列数据库已经发展到支持更复杂的数据模型。DynamoDB和Cassandra确实支持表,但没有分区键是不可能查询的。
它们还支持基本的排序水平,限制返回的结果等。总之,Dynamo论文的迭代能够支持更丰富的模型,尽管它缺乏关系型数据库一般所具有的功能。
选择你的分区键也有其他细微差别。Dynamo系列数据库支持较弱的ACID模型,其中一些基本的隔离或交易或一致性水平是可以实现的。当你与之交互的行在同一个分区上时,这些通常是可能的。
因此,Dynamo的数据模型是非常简单的。DynamoDB和Cassandra支持更丰富的数据模型,但仍然没有任何关系,关系,灵活的查询,等等。
选择你的分区键是决定你的数据模型的一个非常重要的部分,需要比关系型数据库考虑得更多。
◆ 不太灵活的查询模式
Dynamo暴露了一个更简单、更受限制的查询模型。
它只暴露了两个函数,get(partition key)和put(partition key, object)。这意味着不支持排序数据,限制返回的行数,等等,你通常会在关系型数据库中发现。
然而,正如我之前解释的那样,Cassandra和DynamoDB提供了一个更丰富的模型,能够过滤数据(类似于SQL中的WHERE),对数据进行排序,限制行数等。它们仍然有局限性,主要是由于数据必须存储在不同的节点上。
你一般会受到你的分区主键的限制,如果你还没有意识到,这非常重要。
◆ 分布式
Dynamo作为一个分布式系统工作。在一个单节点系统中运行它是没有意义的。如果你正在运行Dynamo,你有可能正在运行几十个甚至几百个节点,因为这正是Dynamo的优势所在。
◆ 缺少ACID支持
"亚马逊的经验表明,提供ACID保证的数据存储往往有很差的可用性。这一点已经被业界和学术界广泛认可[5]。Dynamo的目标是以较弱的一致性(ACID中的 "C")操作的应用程序,如果这能带来高可用性。Dynamo不提供任何隔离保证,只允许单键更新。"
正如论文中所说的那样,Dynamo不支持ACID属性。它没有支持更高的一致性,而是提出了一个AP系统,其目标是可用性而不是一致性。
这是有道理的。对于很多应用来说,严格的一致性可能是很重要的。这意味着你的集群中的节点应该总是同意数据的当前状态。例如,如果你正在处理与支付有关的数据,严格的一致性可能很重要。想象一下,如果集群中的节点在你的账户上有多少钱上有分歧。有些节点会允许借记交易,有些节点可能会拒绝。
然而,严格的一致性是有代价的。这个代价往往是可用性、性能和耐久性。
对于大多数应用来说,如果你的数据存储处于不一致的状态并不重要。例如,如果一些节点认为某条推文有2000个赞,而一些节点认为有2,001个,这并不重要。有些用户可能看到2000个,有些可能看到2,001个,但这几乎不影响用户体验。Dynamo是为这些应用而建立的。在这里,一致性并不重要,可用性和性能才是最重要的。
顺便提一下,Dynamo确实给了你一个可调整一致性的选项。简单地说,你可以定义你想要的一致性水平。这有更多的细微差别,但也可以有严格的一致性,尽管是以可用性为代价。这个概念需要更多的深度,所以,为了节省时间,我暂时跳过它。然而,如果你想让我写更多关于这个问题的文章,请在评论中告诉我。
◆ 可线性扩展的写入性能
当你横向扩展关系型数据库时,你并不能获得系统中所有节点的全部力量。这是因为在水平扩展的集群中运行的关系数据库,特别是当每个节点只存储关系的一部分,而不是整个关系的时候,会为了最简单的查询而不断地互相交谈。
例如,假设你有一个简单的客户表,在Postgres的三个节点之间分片,所以每个节点都存储了整个表的一些行。由于你为每一行存储了电子邮件地址和电话号码,你也想确保这些在整个表中是唯一的(同样,它跨越了多个节点)。
如果你要写一个新的客户,你首先要决定把它写在哪个节点上,然后检查其他节点上是否有相同的电话号码或电子邮件地址的客户存在,然后再写它。
在做这些工作的同时,你还需要确保其他节点上没有新的客户被写入,因为两个具有相同电子邮件或电话的客户可能同时被写入,从而破坏了UNIQUE约束。现在想象一下,如果这些节点在物理上也相距甚远。
即使在这样一个简单的场景中,已经可以看出关系型数据库中的分片是多么复杂。添加更多的节点也会增加每个现有节点的工作,因为现在它需要与另一个节点连接、交谈和闲谈。
Dynamo背后的道理很简单。单个节点无法维持所需的读写数量。解决这个问题的唯一方法是建立一个具有横向扩展能力的多节点系统。Dynamo是为了呈现一个可以轻松处理数百、数千甚至更多节点的系统。它之所以这样做,是因为它可以线性地扩展写入性能。
因此,目标应该是,增加一个节点不会增加其他节点的工作。每个节点只传递所需的信息,Dynamo不承诺验证或唯一的约束或其他功能,这将增加系统中节点的负担。
Netflix进行了大量的测试,以了解Cassandra(属于Dynamo数据库家族)在增加节点数时的表现。这张图完美地总结了这个线性比例。
你可以看到,增加更多的节点并不会降低其他节点的性能。
◆ 在哪里使用Dynamo家族的数据库?
我认为维尔纳-沃格尔斯真的很好地总结了这一点。
"我们的目标是建立一个具有无限制的可扩展性、一致的性能和高可用性的数据库,以支持我们快速增长的业务需求。" - Werner Vogels
Dynamo和Dynamo系列数据库提出了一个理念,即以一致的性能保证来存储绝对大量的难以想象的数据。它承诺了高可用性、低延迟和可线性扩展的写入性能。
但它牺牲了其数据模型和查询能力的灵活性,并且缺乏ACID支持。它还提出了一个分布式系统,作为一个单节点系统运行将是无用的。
我最近写了一篇关于Cassandra的深度文章,我在文章中打了个比方,也同样适用于Dynamo。
把Dynamo想象成兰博基尼Huracan,把传统的关系型数据库想象成劳斯莱斯幻影。幻影会给你更多的奢侈,在这种情况下,奢侈的是你的查询的灵活性,以及ACID属性,但是当你想踩油门,你想获得绝对的原始性能时,兰博基尼-胡拉康会直接击败幻影的。
因此,当你想在分布式环境中获得大规模的规模和可用性,并且性能稳定时,请使用Dynamo。
◆ 有趣的语录
◆ 一个始终可写的数据存储
"Dynamo主要针对那些需要一个 "永远可写 "的数据存储的应用,在那里没有更新会因为失败或并发写入而被拒绝。这是许多亚马逊应用程序的一个关键要求。"
有趣的是,上述段落在论文中的措辞。它强调了Dynamo是如何为写作而建立的,并始终确保更新或失败不会被拒绝。
这种永远可写的数据存储的理念贯穿本文,是该系统的主要目标之一。
◆ 强调不断的失败和如何处理它
"在一个由数百万个组件组成的基础设施中处理故障是我们的标准操作模式;在任何时候都有少量但重要的服务器和网络组件出现故障。因此,亚马逊的软件系统需要以一种将故障处理视为正常情况的方式来构建,而不影响可用性或性能。"
我非常喜欢上面这句话,这句话作为论文导言的一部分,真正设定了对Dynamo的期望。能够每天处理失败是Dynamo工作要求的一部分。
它还强调了Dynamo的关键焦点是可用性和性能。
◆ 流言蜚语
Dynamo是为了以分布式方式工作而建立的。在任何时候,系统中都应该有多个节点在存储数据。这些数据经常被复制到多个节点。这些节点需要知道彼此的情况,彼此的健康状况,以及系统的总体情况。有很多有趣的问题,如负载平衡、作业调度、请求路由、复制同步、处理故障、并发等,这些都需要在节点之间不断沟通。
节点之间使用基于gossip协议进行通信。这是一种点对点的通信方法,事实上数据库系统也经常使用这种方法。我之前在谈论Redis的时候谈到了这一点 here和Cassandra的时候,我在之前的文章中谈到过这个问题。The Wikipedia page关于gossip通信的文章也是一个有趣的阅读。
简而言之,把节点想象成普通的高中生,讨论我们某个节点的尴尬故障。
◆ 版本管理和冲突解决
"Dynamo不提供任何隔离保证,只允许单一主键更新。"
这很有意思,因为在分布式系统中没有隔离保证,你的数据存储有可能有一个数据项的多个版本。
事实上,Dynamo论文中描述的数据库系统也是如此。Dynamo没有像传统的关系型数据库系统那样回落到保证隔离,而是拥抱了多版本的可能性。
发生这种情况是因为更新需要异步传播系统。这种传播可能需要少量的时间。在这段时间里,数据存储将存储同一数据项的多个版本。Dynamo使用矢量时钟的概念来确定版本,并试图解决版本冲突,但它不能总是解决它们。在它不能解决的情况下,它将多个版本返回给用户,让用户来决定正确的版本。
这篇论文谈了很多关于版本的问题,关于他们是如何做出这些决定的,以及哪些因素促成了这些决定,这真是一篇引人入胜的文章。
重要的是要明白,某些故障模式有可能导致系统对相同的数据不只是有两个而是有几个版本。在网络分区和节点故障的情况下,更新有可能导致一个对象有不同的版本子历史,系统将需要在未来进行协调。
这就要求我们在设计应用程序时,明确承认同一数据存在多个版本的可能性(以便永远不会丢失任何更新)。
上面这段话特别强调,这些多版本是以 "永远不会错过更新 "的承诺为代价的。"这又与Dynamo所承诺的永远可写的数据存储有关。
论文的另一个节选谈到了版本问题和决定谁应该做冲突解决的决策过程,数据存储还是应用程序。Dynamo并不是懒得做冲突解决,而是Dynamo背后的工程师认为让应用程序做冲突解决可能更好一些
下一个设计选择是由谁来执行冲突解决的过程。这可以由数据存储或应用程序来完成。如果冲突解决是由数据存储完成的,那么它的选择就相当有限。在这种情况下,数据存储只能使用简单的策略,例如 "最后写的赢"[22],来解决冲突的更新。另一方面,由于应用程序知道数据模式,它可以决定最适合其客户端经验的冲突解决方法。
在读这一节的时候,我直觉地在想,为什么不直接用 "最后一次写入获胜 "的方法来确定所有数据项的当前状态,而这篇论文提供了一个非常好的例子,说明这种解决方案在什么时候是行不通的。
例如,维护客户购物车的应用程序可以选择 "合并 "相互冲突的版本,并返回一个统一的购物车。
◆ 对高可用性缺乏耐久性的看法很有趣
一般来说,数据库被迫在可用性和一致性之间做出选择。这是数据库做出的最大的选择之一,对他们的使用情况有很大的影响。
本文深入讨论了这一点,因为Dynamo试图带来的现状的一个重大变化是,在不需要的时候从一致性转向可用性和性能。
人们会认为可用性和耐用性是相辅相成的,该文件也指出了这一点。
传统的智慧认为,耐用性和可用性是相辅相成的。然而,这在这里不一定是真的
它进一步谈到,在Dynamo的情况下,情况恰恰相反。因为所有的节点并不总是承认写入,所以有可能数据项只被写入少数的节点,甚至是一个节点。
这意味着有一个小的时间窗口,数据还没有被复制和持久地存储在多个位置。这可能会影响耐久性,因为单个节点很少会因为硬件故障而丢失数据。
这也为持久性引入了一个漏洞窗口,当一个写请求被成功返回到客户端时,尽管它只在少数节点上被持久化。
这篇论文没有谈及耐用性,如果能读到他们是如何将数据同步到操作系统的,是类似于关系型数据库的每次交易的强制同步,还是像今天的NoSQL数据库中有时看到的更多的周期性同步,那将是很有趣的。另外,找不到任何与写头日志或类似东西有关的东西,所以很难评估单个节点的耐久性。
◆ 结论和资源
我觉得这份白皮书非常有趣,它是以普通软件工程师能够理解和理解的方式写的。我真的推荐你全文阅读,它比我所能涉及的要详细得多。
我非常推荐维尔纳-沃格尔斯在Dynamo十年后写的文章.
AWS关于DynamoDB的数据建模的两部分系列文章也非常有趣,尽管那更多地是关注DynamoDB而不是Dynamo。它真正展示了数据查询和数据模型是如何与关系模型完全不同的。
如果你喜欢这篇文章,请在评论中告诉我你是否使用过Cassandra或DynamoDB,以及你的使用经验如何。
来源:
https://www.toutiao.com/article/7117092391676346920/?log_from=bd8d977031e0f_1657521672759
“IT大咖说”欢迎广大技术人员投稿,投稿邮箱:aliang@itdks.com
来都来了,走啥走,留个言呗~
IT大咖说 | 关于版权
由“IT大咖说(ID:itdakashuo)”原创的文章,转载时请注明作者、出处及微信公众号。投稿、约稿、转载请加微信:ITDKS10(备注:投稿),茉莉小姐姐会及时与您联系!
感谢您对IT大咖说的热心支持!
- 相关推荐 推荐文章
- 快速高效搭建可视化拖拽平台,含事件机制、弹窗等解决方案
- md5算法不可逆,为啥网上很多网站声称可以解密md5
- CENTOS断更之后,该何去何从?
- Nginx 面试题 40 问
- 你都30多岁的程序员了,还不懂Docker的原理及构建部署过程吗?
- 一次性把Docker的概念、容器与虚拟机的区别、容器交付的优势讲清
- 从 CPU 讲起,深入理解 Java 内存模型!
- 前端工程化:保姆级教学 Jenkins 部署前端项目
- 中高级程序员可能都不会使用spring-boot-starter-jdbc访问MySQL
- 探索云原生技术之基石——Docker容器