Twitter和Facebook的Cassandra架构以及NoSQL数据库等都应用Dynamo。
如图是面向服务的Amazon平台基础架构,其是完全的分布式,去中心化的。Dynamo采用简单的键值方式存储数据,而非传统的关系型数据库方式。Dynamo存储数据值的原始形式,以bit形式存储,不解析数据的具体内容,不识别任何数据结构。
Dynamo定位为高可靠,高可用,具有良好容错性的分布式存储架构,其主要面临的问题及解决方案如下表:
问题 |
采取的相关技术 |
数据均衡分布 |
改进的一致性哈希算法;数据备份 |
数据冲突处理 |
向量时钟(vector clock) |
临时故障处理 |
弱Quorum机制;数据回传机制(Hinted handoff) |
永久故障后的恢复 |
Merkle哈希树;反熵协议 |
成员资格以及错误检测 |
基于gossip的成员资格协议和错误检测 |
一致性哈希算法满足:
1.平衡性:存储数据哈希完尽量均匀分布在所有节点上;
2.单调性:新增加节点时,一部分旧节点内容会映射到新节点上,其他的旧节点之间的内容不会重新分配;
3.分散性:由于分布式环境下,不同节点可能只看到一部分节点,导致同一内容映射到不同节点,需尽量避免或降低分散性;
4.负载:另一角度看分散性,由于同一内容映射到不同节点,其负载变高。
一致性算法步骤:
1.计算节点的哈希值,将节点分配到环上;
2.计算数据的哈希值,按顺时针方向将其映射到最近的节点。
左图为一致性哈希算法,右图为增加节点时的示意图。
由于一致性哈希函数是随机函数,在节点较少时可能造成环上节点数据不均匀,其也没有考虑不同节点的性能差异。因此,Dynamo引进虚拟节点,每个物理节点根据其性能分配不同数量的虚拟节点,每个虚拟节点能力相当,随机分布在哈希环空间中。
Dynamo对数据进行冗余备份,一般副本数N为3,节点的数据副本保存在环上它的顺时针方向的后继节点中。如图,键k数据保存在虚拟节点A中,其副本保存在虚拟节点B,C中。Dynamo对数据写进行了优化:保证一个副本写入硬盘,其他副本写入内存即返回成功。Dynamo还保证相邻的节点位于不同的地区区域,如此某个数据中心瘫痪,保证数据在其他数据中心有副本。
根据CAP理论,分布式系统的一致性(Consistency),可用性(Availability),分区容忍性(Partition Tolerance)最多只能实现其中的二者,Dynamo选择牺牲一致性,采用最终一致性模型。Dynamo用向量时钟(vector clock)来保证最终一致性。
Dynamo中的向量时钟用(node,counter)对表示,node代表节点,counter为计数器,初始为0,每发生一次事件加1。当系统有了多个版本的对象发生冲突时,系统不会自行选择,而是保持多个版本,用户根据版本信息进行选择。向量时钟数量有限,当超过时间戳(Timestamp)删除最开始的向量时钟。
N:存储的副本数;W:一次成功写操作需要写入的最少副本数;R:一个成功读操作需要服务器返回的最少副本数。保证R+W>N,即用户读取数据时总可以获得一个最新版本。N固定,用户可自行配置R和W调节可用性和容错性。弱Quorum机制对传统Quorum机制的改进是:N不是N的节点,而是N个正常节点。
由于N代表N个正常节点,当节点出现故障时,自动由后面的节点接替其工作,新的节点开辟临时空间存储故障节点的数据,并监控故障节点,一旦故障节点可用,将数据回传给故障节点,删除临时空间数据。
节点出现永久性故障时,Dynamo必须检查并保持数据同步。Dynamo采用Merkle哈希树提高数据同步检查速度,采用反熵协议保证数据同步。
Merkle哈希树的叶子节点存储单个数据对应的哈希值,父节点是其所有子节点的哈希值。检查数据是否同步时,从根节点开始,如果根节点相同,说明这个数据分区数据一致,不需继续检查,否则一层一层往下直到叶子节点,找出哈希值不同的数据。
反熵协议假定同步会按照一个固定进度表执行,每个节点定期随机或是按照某种规则选择另外一个节点交换数据,消除差异。有三种反风格的反熵协议:推,拉和混合。协议的原理是简单选取一个随机节点然后把数据状态发送过去。在真实应用中将全部数据都推送出去显然是愚蠢的。推协议中:节点A作为同步发起者准备好一份数据摘要,里面包含了A上数据的指纹。节点B接收到摘要之后将摘要中的数据与本地数据进行比较,并将数据差异做成一份摘要返回给A。最后,A发送一个更新给B,B再更新数据。拉方式和混合方式的协议与此类似。
每个节点即是一个成员,每个成员保存其他成员的路由信息来减少数据发送延迟。由于随时有成员的增加和撤离,所有成员每隔固定时间(1秒)利用闲聊(Gossip)协议任意选择一个节点通信,交换双方保存信息。为了避免新成员加入不能及时发现其他成员,设立种子节点,其与所有节点连接,充当中介角色,使新节点跟其他所有节点感知。
当成员失效时,为了避免传送无效信息,引入错误检测机制,即一旦发现对方没有回应,认为其失效,选择别的节点通信,并定期向节点发送消息,试图重新建立通信。
当一个新成员加入,通过最优的方式进行传播(即每次交换都是第一次交换新节点信息)。如图,新节点消息传遍整个系统需要log N。
灵活性:用户可对实例类型,数量,运行的地理位置进行配置;
安全性:采用基于密钥对机制的SSH方式访问,可配置的防火墙,允许用户对自己的应用程序进行监控;
容错性:利用弹性IP地址等机制,使EC2发生故障时仍能保证用户服务较为稳定。
EC2基本架构:
(1)Amazon机器映像(Amazon Machine Image,AMI)
AMI将用户应用程序,配置进行打包的加密机器映像。使用EC2的第一步是创建AMI。
(2)实例(Instance)
用户实际运行的系统称为实例,每个实例携带一个存储模块,临时存放用户数据。实例重启数据还在,出现故障或实例被终止,数据消失,一般重要数据保存在弹性块存储EBS中。
EBS用于长期保存或保存重要数据,允许用户创建卷,每个卷作为一个设备挂载在一个实例上。快照可以捕捉当前卷状态,存储在S3中。
地理区域:美国东,美国西,欧盟,亚太;
可用区域:有独立的供电冷却系统,即一个数据中心。
系统各模块之间及系统和外界之间的信息交互是通过IP地址进行的,IP地址包括公有IP地址,私有IP地址,弹性IP地址。
实例可自动分发应用流量。ELB可识别应用实例的状态,当其运行不佳时,可自动将其流量路由到状态较好的实例资源上。
CloudWatch是个Web服务,可监控包括EC2实例状态,资源利用率,需求状况,CPU利用率,磁盘读写,写入和网络流量等指标。
按照用户自定义的条件,自动调整EC2的计算能力。需求高峰时,保证EC2实例处理的无缝增大,需求下降时,缩小EC2实例规模降低成本。
基于Web的控制环境,用于启动,管理EC2实例和提供各种管理工具和API接口。
引入安全组概念可有效配置防火墙。安全组是一组规则,符合规则的网络流量会被实例接受,其他流量被拒绝。若没有指定特定安全组,则分配到默认组里,默认组只接受组内成员的消息,忽略其他任何消息。
用户在访问EC2时用SSH密钥对登录。
弹性IP地址。用户通过公共IP地址访问实例,每当实例重启公共IP地址会产生变化。弹性IP地址和用户账号绑定,而非实例。每个账号默认绑定5个弹性IP地址。
用户可以通过Amazon提供的服务接口将任意类型的文件临时或永久的存储在S3服务器上。S3的设计目标是可靠,易用,低成本。
S3系统架构在Dynamo之上,采取的不是传统的关系数据库存储方式。
对象是S3的基本存储单元,包括数据和元数据。元数据可以是默认的系统元数据,也可以是自定义的用户元数据。其中默认的系统元数据包括:last-modified(对象最后修改时间),ETag(对象MD5值),Content-Type(对象MIME类型),Content-Length(对象长度,单位字节)。对象不支持重命名操作,不能直接修改对象,只能重新创建对象间接修改。每个对象还有个键,以及访问控制列表。
键是对象的唯一标识符。
桶是存储对象的容器。桶不能嵌套,即桶内不能有桶。因为S3允许文件共享,桶的名称必须全局唯一。
S3支持5中基本操作:Get,Put,List,Delete,Head。
操作 |
Get |
Put |
List |
Delete |
Head |
桶 |
获取桶中对象 |
创建或更新桶 |
列出桶中所有键 |
删除桶 |
无 |
对象 |
获取对象数据和元数据 |
创建或更新对象 |
无 |
删除对象 |
获取对象元数据 |
S3采用冗余存储,利用跟Dynamo一样的最终一致性模型。对于写操作,一个副本写入硬盘,其他副本写入内存即返回成功,而在数据被充分传播到所有的存放节点之前返回给用户的仍是原数据。
S3的安全机制包括:身份认证(Authentication)以及访问控制列表(ACL)。
S3采用基于HMAC-SHA1的数字签名来确定用户身份。HMAC-SHA1基于加密Hash函数和共享密钥的消息认证协议,包括一个加密的Hash函数,一个加密的随机密钥,一个安全的密钥交换机制。HMAC-SHA1可以有效防止数据在传输过程中被截获,篡改,维护数据的完整性,可靠性,安全性。每个新用户会被分配一个Access Key ID和一个Secret Access Key,其中Access Key ID用来确定服务请求的发送者,Secret Access Key参与数字签名过程,用来证明用户是发送服务请求的合法拥有者。
S3的授权用户分为:所有者(Owner),个人授权用户(User),组授权用户(Group)。其中所有者具有最高权限,可以通过绑定电子邮件或者AWS ID的方式授权个人用户,通过绑定AWS用户组或者所有用户组的方式授权给用户组。
S3的访问控制策略如下表:
权限 |
操作目标 |
具体权限内容 |
READ |
桶 |
列出已有桶 |
对象 |
读取数据及元数据 |
|
WRITE |
桶 |
创建、覆写、删除桶中对象 |
READ_ACP |
桶 |
读取桶的ACL |
对象 |
读取对象中的ACL |
|
WRITE_ACP |
桶 |
覆写桶的ACP |
对象 |
覆写对象的ACP |
|
FULL_CONTROL |
桶 |
允许进行以上所有操作,是S3提供的最高权限 |
对象 |
桶和对象的ACL各自独立,对桶的某种访问权限不代表对桶内对象具有相同权限,即S3的ACL不具有继承性。
SQS是为了解决云计算平台之间不同组件的通信而专门设计开发的。SQS的身份认证采取跟S3一样的数字签名方式。
SQS包括系统组件(Component),队列(Queue)和消息(Message)。系统会给每个新创建的队列一个URL,后续需要定位某个队列时采用URL的方式进行访问。
消息由四个部分组成:消息ID,接受句柄,消息体,消息体MD5摘要。
队列的消息被冗余存储,同一个消息被保存在多个服务器上,以此保证消息的高可用性。查询消息时采用基于加权随机分布的消息取样:用户发出查询队列中的消息命令后,系统在所有的服务器上使用基于加权的随机分布算法随机选出部分服务器,返回这些服务器上保存所查询的消息副本。当用户所查询消息副本太少,某次查询系统可能不会返回任何结果,但一直查询下去总会查到所要查询的消息。如图,所查询的服务器4没有返回用户需要查询的消息B,只返回了另两个消息A和C,所以需要继续查询别的服务器以返回消息B。
用户接收到消息之后,系统就会将消息从队列中删除。为了保证其他组件不会查看消息,SQS会将消息阻塞,即给消息加把锁,直到需要给用户进行重传消息时,进行解锁,让重传消息的组件给对应用户重传消息。可见性表明消息可以被所有组件查看,当需要重传消息时,就把消息变成可见,以便重传消息的组件看到消息,其他时间,为了保证消息不会被其他组件查看,消息应为不可见。可见性超时值是一个计时器,在设定好的时间内,消息不可见。除了在计时器开始之前可以改变设置外,还可以在计时器计时过程中,通过“扩展”(重新对计时器进行设置,计时器重新计时)和“终止”(对计时器终止,消息由不可见变成可见)改变设置。消息从产生到被删除的过程称为消息的生命周期,消息存放超过4天,SQS会自动将其删除。
Simple DB属于键值数据库,其跟S3不同在于,其主要存储结构化数据,并为这些数据提供查找,删除等基本数据库功能。Amazon希望用户将相对大的数据存储在S3中,只在Simple DB存储指向某个特定文件位置的指针。
如图,Simple DB范围从宽到窄,依次包含用户账户,域,条目,属性,值。
域是数据容器,Simple DB的数据库操作都是以域为基本单位的,所有的查询都只在一个域内进行,域间操作是不允许的。由于Simple DB是树状组织方式,其对属性的操作相当自由,每当有个条目有新的属性时,只需要简单的把这个新属性添加进去即可,而不用考虑这个属性和其他条目是否相关。对于值,Simple DB允许多值属性。
传统的关系型数据库采用表结构存储,而Simple DB采用的是树状组织方式。
Simple DB为了系统的高可用性,采用最终一致性模型。
问题1:支持的操作类型不够,像连接,对结果的排序这样的操作都不支持
解决方案:用户自己通过程序来完成
问题2:所有数据用字符串存储,做查询操作时采取词典排序,排序结果不准确
解决方案:1.整数补零:数字20和100,补零变成00020和00100进行排序
2.对负数整数集添加正向偏移量:相当于当负数变成正数
3.采用ISO 8601格式对日期进行转换
用户将需要处理和存储的数据上传至S3,需要时随时下载。当上传成功后可以通过SQS对Simple DB执行一系列操作,将S3中需要处理的文件位置(指针)存储在Simple DB中。利用这些指针,配合SQS,向EC2发出命令,让EC2的某个实例从S3中提取相关文件直接处理,成功处理后将文件再回存至S3并把结果返回用户。
Amazon RDS是一种云中MySQL数据库系统,它采用集群方式将MySQL数据库移植到云中,一定范围内解决了关系数据库的可扩展性问题。
MySQL集群采用Share-Nothing架构,每台数据库服务器都是完全独立的计算机系统,通过网络相连,不共享任何资源。RDS通过表单划分(Sharding)的方式将一张大表划分成若干个小表,分别存储在不同的数据库服务器上,从逻辑上保证了数据库的可扩展性。但是表单划分没有固定的方式,只要根据业务的需要进行针对性的划分。
集群SQL通过主从备份和读副本技术提高可靠性和数据处理能力。数据库升级时,先对从数据库进行升级,然后从数据库变成主数据库,再对主数据库进行升级,保证业务的连续性。集群SQL设置了若干个读副本,这些副本的数据只能读,不能写,写操作只能由主数据库完成。