Distributed Database System —— CockroachDB文档阅读


为了简单表示,在今后这个系列的文章,都以CRDB或者crdb来表示CockroachDB。要了解这个NewSQL数据库,我们先从Architecture Overview开始,从Cockroach labs提供的文档开始了解。

Architecture Overview

Architecture Overview

CockroachDB was designed to create the source-available database our developers would want to use: one that is both scalable and consistent.

crdb作为强一致的可扩展的数据库,在文档Reference中被分成了下面几层:
在这里插入图片描述
下面一一介绍这5层架构的作用。

SQL Layer

The SQL layer of CockroachDB’s architecture exposes its SQL API to developers and converts SQL statements into key-value operations used by the rest of the database.

SQL层就做了两个工作:

  1. 对外提供API服务
  2. 对内翻译SQL语句至对应的KV操作

在crdb中,节点具备对称性(Symmetrically),所以一个SQL请求可以发送到任意节点上(这个节点会作为gateway节点,不一定是真正处理这个SQL的事务节点)。对于客户端的请求虽然以SQL语句的形式发出的,但是它们最终会在存储层以KV对的形式做读写,所以SQL层在此时会将这个SQL语句转换为后续其他层能够读懂的KV对操作(KV operations)的形式。

Developers experience data stored in CockroachDB in a relational structure, i.e., rows and columns. Sets of rows and columns are organized into tables. Collections of tables are organized into databases. Your cluster can contain many databases.


  • SQL parser, planner, executor

了解MYSQL的Innodb处理引擎后,很好理解。

以查询语句举例,当crdb收到查询语句后,在Parsing阶段会根据类yacc的Parser解析为AST(抽象语法树)

Planning阶段,分成了逻辑计划和物理计划两个部分。

  • 在Logic Planning时,会将AST转换为一个high-level logic query plan。在这个过程中,包括检查查询是否有效,解析名称,消除不需要的中间计算,并最终确定用于中间结果的数据类型。然后会使用一个搜索算法来计算最小成本的执行方案。
  • 在Physical Planning时,会决定哪些节点参与到了这次的查询中。

Query Execution阶段,在每个参与到这个查询的节点上,crdb会在每个节点内部或者跨节点上有专门的Logical processors通过Logical Flow来做数据的交互,完毕后的结果数据被被返回到头一个接收到该Query的节点上,并最终返回客户端。


  • Dist SQL

crdb 没有像其他一些数据库那样做计算和存储进程分离,每个 binary 都是一个既能运算又能存储的 node, 客户端可以将 sql 发送到任意一个 node, sql 最初抵达的 node 会作为这个 sql 的 gateway node 负责这条 sql 的处理,处理可能需要向其他 node 读取或写入数据, 因为 cdb 数据是通过 k/v range 的方式分布在不同节点 node 中, 所以最简单的实现是 gateway node 收到 sql 后向其他节点把相关数据都要过来,然后在 gateway 完成计算,如果是 update 还需要把计算结果写到存的 node 中

上面这种做法就叫做non-distributes queries,虽然nodes是分布式的,但是实际上数据是收集起来后在一个节点上处理的。DistSQL 的目的是优化这种每次都读取数据集中计算再回写的模式。

通过DistSQL-compatible queries,每个涉及到的节点先各自使用拥有的行来先做计算,然后再将数据发送到gateway node(coordinating node),通过coordinating node聚合结果返回给client。通过这种方式,很显然coordinating node不需要再接受太多的数据,节省了内存和网络带宽,也减少了在一个节点上的CPU计算的占用,另外,也不需要再做回写了。

Transaction Layer

The transaction layer of CockroachDB’s architecture implements support for ACID transactions by coordinating concurrent operations.

事务层做了两个工作:

  • 接收来自SQL层的KV值
  • 控制KV操作流发送到分发层

crdb是强一致性的,所以其事务层需要提供ACID的特性。所以,由于分布式的关系,Cockroach DB就需要实现跨越整个集群的ACID事务(包括cross-range和cross-table的事务),所以它使用“Parallel Commit”的方式,即一种分布式原子提交协议来实现正确性。


  • Writes and Reads (Phase 1)

Writing:
crdb在做写操作时不会直接把值直接写入磁盘,而是会使用下面的策略去协调分布式的事务:

Write Intent也被称为 Replicated Locks,通过Raft协议来保证可用和一致的。

Reading:
在上述引用的文章里,可以知道Write Intent会被指向存储在集群上的Transaction Record中,这个Transaction Record保存了当前事务的状态,包含PENDING / STAGING / COMMITTED / ABORTED 的状态。

所以,在读操作发生的时候,可能会遇到WR冲突,如果一个事务没有异常终止(aborted),事务层开始执行读操作。满足标准的MVCC,只读事务,没有任何问题。但如果有任何写意向,必须通过事务冲突来解决。具体解决方案见上文引用。


  • Commits (Phase 2)

CockroachDB检查正在执行的事务记录,查看它是否被标记为ABORTED,如果有,则重启事务。

在通常情况下,事务状态会被标记为STAGING。这时会检查事务的Write Intent是否成功执行,如果事务通过这些检查,事务会被标记为COMMITED,并进入下一个阶段,同时向客户端返回事务成功。


  • Cleanup (Phase 3)

清理Write Intent。当然这个步骤不是必须的,也可以延迟删除,当下一次操作遇到完成的write intents时再删除。

Distribution Layer

To make all data in your cluster accessible from any node, CockroachDB stores data in a monolithic sorted map of key-value pairs. This key-space describes all of the data in your cluster, as well as its location, and is divided into what we call "ranges"

分布式层主要做两个工作:

  1. 简单查找。定位数据到对应的节点上。
  2. 高效扫描。定义数据的顺序,通过扫描可以发现数据具体的range。

要了解分布式层,首先需要了解”Monolithic sorted map“整体排序图这个结构,这个结构由两个元素组成:

  • 系统数据(Sytem data),包括meta ranges ,用以描述了集群中数据的位置。
    集群里所有的Ranges的位置信息被存储到Meta range中,Meta Range由两层索引组成,第一层索引(Meta1)是用于指向第二层索引位置的,而第二层索引(Meta2)才真正的指向集合中的数据。
  • 用户数据(User data),存储真正的业务表数据。

使用Monolithic sorted Map,当某一个节点拿到一个请求时,它会到meta ranges中去定位请求将路由到哪个节点。meta ranges指向的数据被大量的缓存,很多时候不需要想实际的节点发送RPC请求。

所以对于分布式层与其他层的交互:

  • 从相同节点获取来自事务层的请求。
  • 识别哪个节点应该接受请求,并将请求发送到节点对应的冗余层上。

Replication Layer

冗余层保障高可用的特性,是为了在部分节点离线的情况下确保系统的一致性。Crdb使用Raft协议来解决上述问题的。

Raft协议了解的很多了,简单来说当节点宕机时,采用Raft协议的其他Crdb节点会因为心跳而检测到Leader节点的断连,从而重新选举Leader。

另外关于冗余层的租约(Lease),以后再做介绍。

对于冗余层与其他层的交互:

  • 冗余层接收来自自己或其他节点的DistSender发送的请求,如果节点是这个range的租约获得者,接受这个请求,如果不是,返回错误,并返回指针,指向租约获得者,这些KV请求转化为raft命令。冗余层发送BatchResponses 返回给分布式层的DistSender。
  • 提交raft命令被写入raft日志中,最终通过存储层存储在磁盘上。租约获得者通过RocksDB实例处理读,在存储层。

Storage Layer

每个cockroachDB包含至少一个存储,当节点启动,cockroach进程在磁盘中读写数据。这个数据以KV对形式存储在磁盘上使用RocksDB,被视为一个黑箱的API,每个节点包含三个rocksDB的实例。在Crdb v20.2版本中,替换RocksDB为Pebble,相比于RocksDB,Pebble是以Go语言实现的RocksDB功能的子集,包含了更多的优化。

每一个存储层节点包含了三个RocksDB实例:

  • 为raftlog服务
  • 存储当前的分布式SQL数据
  • 为其他节点提供冗余的数据服务

另外,在一个节点的所有存储共享一个block缓存。这些存储按顺序获取有range副本,一个range的多个副本不会放在相同的存储中,甚至不会放在相同的节点。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值