ITPub博客

首页 > 数据库 > > Google Cloud Spanner的架构与模型

Google Cloud Spanner的架构与模型

作者:u_9ff4c058a0e0 时间:2022-04-02 16:23:33 0 删除 编辑

第一次接触到Google Cloud Spanner是因为客户对于新技术的追求与尝试,将我们基本完成的APIs从原先的Google Cloud Sql迁移到Spanner数据库上。并且因为客户在老服务商已有百万个客户数据,也需要进行迁移,数据id是Spanner不默认支持的序列id。客户想要保留序列id格式,这也为我们迁移到Cloud Spanner数据库造成了一定麻烦。

但在我们不断接触Cloud Spanner并深入(对于我来说的深入:-p)了解后发现,Cloud Spanner的使用并没有想象中那样会特别复杂。尤其是Google为Cloud Spanner提供了大量对已有依赖的封装库,如hibernate、JDBC等。

Google Cloud Spanner

Cloud Spanner数据库原先作为Google内部使用的数据库,在2017年对外发布测试版。如今已经在Google云平台上架并拥有大量各个行业的用户。Cloud Spanner数据库是全球范围分布式的关系型/事务数据库,并且Google承诺Cloud Spanner拥有高吞吐量、低延迟和99.999%的高可用性。

分布式数据库

每一个Spanner的实例都是在不同数量的节点上运行的,每一个节点都是由Google云平台服务去自动管理的。因此,Cloud Spanner拥有很高的可扩展性,并且可根据请求负载和数据的大小进行自动分片(splits),为系统提供了更多的弹性空间。

关系型数据库

Cloud Spanner支持关系型数据库所有的功能,但Cloud Spanner不完全是关系型数据库,尽管Spanner的数据模型与任何其他关系数据库的数据模型基本相似,有预定义的数据元组,可以存储在关系(表)中并进行查询,但它缺乏约束。

Cloud Spanner拥有主键概念,并且必须为每个表定义主键,而且该主键是强制唯一性的。然而它没有foreign key的概念,取而代之的是interleave。在关系型数据库中,我们期望数据的强完整性,以确保能满足预定义的约束。Cloud Spanner在该方面的能力有所限制。

事务数据库(ACID)

Cloud Spanner在事务上提供了最严格的并发控制,实现全球事务对外强一致性。在外部一致性[1]的保证下,即使Cloud Spanner的实例位于多个数据中心上运行,事务也能在高性能和高可用性的前提下按顺序执行。Cloud Spanner能够实现外部一致性得益于TrueTime的功能特性。Cloud Spanner 使用 TrueTime 的这一特性为事务分配时间戳。具体而言,每个事务都分配有一个时间戳,它反映 Cloud Spanner 认为事务发生的时间。

其他特性

Cloud Spanner还有很多其他的特性,包括单区域和多区域配置、多语言支持等[2]。

数据架构与模型

Cloud Spanner和传统RDBMS的数据模型基本一致,都是由行、列和值组成,并且含有主键。Cloud Spanner中的数据是强类型,每个表需要定义一个架构,并且每一列的数据都需要制定数据类型[3]。

CREATE TABLE customers(
    customer_id   INT64  NOT NULL,
    first_name    STRING(16),
    last_name     STRING(16)
)PRIMARY KEY (customer_id)

其中,主键(PRIMARY KEY)被定义在表架构外。

数据的分布是通过主键实现的,因此在选择主键的时候需要尽量防止Cloud Spanner服务的热点(Hotspots),时间戳或者自增的序列数字都会造成热点问题出现,Cloud Spanner推荐使用随机(用户名等)的信息或者UUIDs作为主键。

交错表(Interleaved tables)

在Cloud Spanner中,是没有办法去定义两表之间外键(FOREIGN KEY)关系的。但是Cloud Spanner引入了一个类似的概念--交错表。

CREATE TABLE accounts(
    customer_id     INT64  NOT NULL,
    account_id      INT64  NOT NULL,
    created_at      TIMESTAMP NOT NULL
)PRIMARY KEY (customer_id, account_id),
INTERLEAVE IN PARENT customers ON DELETE CASCADE;

以上架构中表示为customers表创建accounts子表或“交错”表。其中需要注意的事项:

  • customer_id是子表accounts的主键之一,也是父表的customers的主键。在accounts声明为customers子表时,该主键是必须添加的,并且要保证命名、类型、限制等都必须一致。
  • 当插入子表时需要确保父表有对应的行(即以相同父表主键开头的行)。
  • 删除父表行需要满足其中两点之一:
    • 在子表中没有对应的行。
    • 声明ON DELETE CASCADE。
  • ON DELETE CASCADE 声明表示,当父表中的某一行被删除时,子表中对应的行也会被自动删除。如果没有该声明,或声明为ON DELETE NO ACTION,则必须先删除子行,才能删除父行。
  • 交错行首先按父表的行进行排序,然后在父表共享主键的基础上,对子表进行再排序。
  • 在对数据库进行分片操作的时候,只要父表行以及子表行的大小在8GB以内,并且在子表行中没有热点,则每个父表以及子表的数据的存放区域关系会一同保留下来。

交错表的主要目的是为了加快某些查询操作,尤其是包含JOIN的操作。因为交错表直接改变了数据在云上的布局方式,确保在执行JOIN操作的时候不会访问集群的每个节点(Nodes)。

二级索引(Secondary indexes)

在Cloud Spanner中,主键会被自动设置为表的索引,Cloud Spanner也同时支持将其他非主键字段设置为二级索引。

CREATE UNIQUE INDEX customer_index_name ON customers(first_name);

其中UNIQUE INDEX关键字表示,该索引会强制该字段在插入时需要不重复。并且在极少情况下,Cloud Spanner可能会自动选择让查询延迟增加的索引,此时可以使用FORCE_INDEX关键字提供指定索引进行查询操作。

SELECT * FROM customers@{FORCE_INDEX=customer_index_name}

数据库分片(split)

在表之间,Cloud Spanner支持最多7层的父子关系,也就是可以将7个逻辑独立的表的行物理地存储在一起。当相关表数据不断增长,达到单个Cloud Spanner服务器的资源限制时,作为分布式数据库的Cloud Spanner会将数据划分为各个“split”区块,每个分片都可以被独立移动并分配给不同物理位置的多个服务器。

分片包含一系列连续的行,这些行的开始和结束键称为“分片边界”(split boundaries)。Cloud Spanner 会根据大小和/或负载自动添加和移除分片边界,这样做会改变数据库中的分片数量。

基于负载进行分片

当数据库中的一个表上的10行数据的读取频率高于表中所有其他的行,Cloud Spanner就会为这10行中的每一行添加分片边界,以便于每一行是由不同的服务器处理,以此来避免这10行数据的读写操作只消耗单台服务器的资源(避免热点)。

架构的更新

Cloud spanner支持对现有的数据库架构执行以下更新操作:

  • 新建表。新表格中的列可以为 NOT NULL。
  • 删除一个表,前提是该表内没有交错其他表,并且没有二级索引。
  • 将一个非主键列添加到任何表,新的非主键列不能为 NOT NULL。
  • 将 NOT NULL 添加到非主键列,不包括 ARRAY 列。
  • 从非主键列中移除 NOT NULL。
  • 从任何表中删除非主键列,前提是二级索引未在使用该列。
  • 将 STRING 列更改为 BYTES 列,或将 BYTES 列更改为 STRING 列。
  • 增加或减少 STRING 或 BYTES 类型的长度限制,前提是它不是由一个或多个子表继承的主键列。
  • 在值和主键列中启用或停用提交时间戳[4]。
  • 添加或移除任何二级索引。
  • 来源 
  • https://zhuanlan.zhihu.com/p/383777164

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69999831/viewspace-3170293/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2022-02-11

  • 博文量
    1828
  • 访问量
    20598