曾经沧海难为水,除却巫山不是云。|

Joey-Wang

园龄:4年3个月粉丝:17关注:0

2023-08-20 10:35阅读: 375评论: 0推荐: 0

FoundationDB 架构

FoundationDB(简称 FDB),是 Apple 公司开源的一个支持分布式事务的 Key-Value 存储,可以认为类似 PingCAP 开源的 TiKV。它最近发表了一篇论文 FoundationDB: A Distributed Unbundled Transactional KeyValue Store,介绍了其内部实现原理。本文是这篇论文及其官方文档的学习笔记。

背景:

传统 SQL 数据库:对一致性要求较高,提供 ACID 事务语义,也导致扩展性较弱。

NoSQL 数据库:为了提高可扩展性,牺牲一定的一致性 (使用最终一致代替强一致),不提供 ACID 事务语义。

NewSQL 数据库:有 NoSQL 级别的可扩展性,支持 ACID 事务语义,支持关系模型,高可用。

FoundationDB 说自己是 NewSQL 数据库,但它是 KV 存储,不支持关系模型,其实是 NoSQL。说是 NewSQL 也行,因为 FoundationDB 向想做的是一个支持多种关系模型的底层 KV 存储,上层开发人员可做各种可插拔的 relational layer。它们自己也实现了一个 SQL Layer,只是没有集成到 FoundationDB里,而是作为一个上层的插件来使用。

架构

image-20230820090631030

FDB 的架构可分成三个模块:

  • 客户端接口 Client
  • 控制平台 Control Plane:负责管理集群的元数据,使用 Active Disk Paxos 来保证高可用。
  • 数据平台 Data Plane:负责处理事务并持久化数据。

论文重点介绍的是 Control Plane 和 Data Plane。

Control Plane

由 Coordinators 组成。几个 coordinator 进程组成一个 paxos group,其中的 leader,称为 Clustor Controller

Clustor Controller:负责故障检测,管理各种进程的角色,汇集、传递整个集群的各种信息。同时,Clustor Controller 是整个集群访问的入口点。Client 通过一个保存有 coordinator 的 IP:Port 的配置文件访问集群,并从 Clustor Controller 获取最新的 proxy 列表。

Clustor Controller 会创建三个进程:

  • Sequencer:给事务分配 read / commit version。
  • Data Distributor:负责监控 StorageServer 的故障情况和数据的平衡调度。
  • Rate Keeper:通过控制单调递增时间戳的分配速度来进行过载保护。

三个进程都是单点的,进程 crash 或 fail 时,FoundationDB 选择直接重新创建就行。因为进程都是无状态的,元数据都由 Coordinator 保存。

Data Plane

FDB 针对 OLTP 工作负载,所以读取和写入只涉及到小部分的 key,争用性低,需要可扩展性。所以 FDB 采用一个解耦的架构。

Data Plane 由三个组件组成 ,各组件都支持独立扩展:

  • Transaction System:负责实现 serializable snapshot isolation 级别的分布式事务。
  • Log System:为 Transaction System 存储 Write-Ahead-Log (WAL)。由多个 log server 组成。
  • Storage System:保存实际数据,或者说状态机,会从 Log System 异步拉取日志进行 apply。由多个 storage server 组成。目前单机存储引擎是使用一个修改过的 SQLite。采用 range sharding 的方式,即将 key 划分为多个 key range,然后分给不同的 storage server。每个 storage server 维护一个 SQLite B-Tree,内存维护一个多版本的 log data 来提供 serializable snapshot isolation。

Transaction System 由三种无状态的进程组成:

  • Sequencer:负责给事务分配递增的 read / commit version。
  • Proxy:作为事务系统面向 client 的代理接口,事务请求都需要通过 proxy 获取 read version,获取 key ranges 对应的 storage server 的信息;负责事务的提交。
  • Resolver:负责 SSI 级别的事务冲突检测。

Client 能直接从 Storage Server 中读数据,从而实现读性能的线性扩展;写性能的扩展可通过增加 Proxy, Resolver, Log Server 来完成。

因为 FDB 针对 OLTP 工作负载,只执行有限的元数据操作,Control Plane 相关组件不会成为性能瓶颈。

API

FDB 支持的 API:

Operation Description
get() Read a single key-value pair
set() Write a single key-value pair
getRange() Read a sorted list of key-value pairs within the range
clear() Delete all keys-value pairs within a range

事务的所有 Write 都会缓存在 client 中,直到事务 commit 才会 push 到 server 中进行处理。

事务处理过程中支持 Read-your-write 语义,会先读取 bufffer 在本地的数据,没有再去 storage server 中读取数据。

事务处理

Data Plane 的分布式事务是为典型的 OLTP 场景设计的,支持水平扩展、读多写少、小事务(5 秒)。

FDB 通过 OCC + MVCC 来实现 SSI 的事务隔离级别。

一个事务的基本流程大概如下:

  1. Client -> proxy -> sequencer 获取 read version(该 version 保证不小于之前所有提交事务的 commit version)。

  2. Client with read version -> storage servers 根据 read version 读取数据快照。

  3. 写请求在提交前会先缓存在本地。

  4. 事务提交:

    1. Client 发送读集合和写集合给 proxy。
    2. Proxy 从 sequencer 获取 commit version(该 version 保证不小于之前所有的 read version 和提交事务的 commit version)。
    3. Proxy 将读集合和写集合发送给 resolver ,利用 OCC 进行事务冲突检测。
      ❗️每个 resolver 负责一部分 key range 的冲突检测。所以 Proxy 要等待所有 resolvers 的响应才能得到最终的冲突检测结果。
    4. 如果事务冲突,则 abort 掉。否则 proxy 发送写集合给 log server 进行持久化,当 proxy 收到所有 log server 回复后再回复 Client 提交成功。

上述不涉及到 Storage server 的持久化。Storage server 会异步地从 Log System 拉取日志进行 apply。拉取的日志不会马上落盘,会加入内存中的一个日志窗口 (五秒的 MVCC 窗口),五秒后再按 commit version 顺序落盘。


待续

参考链接

FoundationDB:Apple 开源的分布式 KV 存储

Gauss 松鼠会论文分享

FoundationDB 将解耦做到了极致

本文作者:Joey-Wang

本文链接:https://www.cnblogs.com/joey-wang/p/17643702.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Joey-Wang  阅读(375)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开