作为新一代的数据库系统,MatrixOne也是以当今风行的分布式架构为根底来设计的。除了存储引擎与计算引擎之外,分布式组件也曾经成为古代数据库设计的必选项。数据库系统在分布式组件的撑持下展现出越来越弱小的可扩展性和高可用性,然而同时也必须面对分布式环境中的一致性,可靠性等挑战。
MatrixOne中的MatrixCube正是一个这样的分布式组件,它能够将任意单机存储引擎扩大成分布式的存储引擎,存储引擎只须要关怀单机的存储设计,而不须要去思考分布式环境中的各种问题。MatrixCube是一个相当宏大的组件,MatrixOne社区将输入一系列文章与教程来进行全面揭秘。
本文作为第一篇文章,将首先从性能与概念上解释MatrixCube能做什么,以及它的架构是什么样的。
MatrixCube是什么
MatrixCube是一个Golang实现的基于Multi-Raft的自带调度能力的分布式强一致性存储框架。
MatrixCube的设计指标是让开发人员可能轻松地实现各种强统一的分布式存储服务。咱们能够应用MatrixCube来构建一些常见的分布式存储服务,比方:分布式Redis、分布式KV等等。而MatrixOne也是一个通过MatrixCube构建的分布式数据库,在没有MatrixCube的状况下,MatrixOne就是个单机的数据库,MatrixCube使得咱们能够搭建一个小型的集群。然而MatrixCube并不与MatrixOne紧耦合,MatrixCube能够对接任意的其余存储引擎,使得其取得同样的分布式存储能力,比方咱们能够让MatrixCube对接一个RocksDB,Pebble,或者Redis。
图-MatrixCube的作用
MatrixCube有以下几个性能个性:分布式,高可用,强统一,主动平衡,用户自定义。
分布式
这个很好了解,单机零碎就是一台机器的零碎,分布式系统就是很多机器组成的零碎,所有分布式问题都是在解决协调多台机器共同完成一件事件的问题。与单机只须要操作一套硬件相比,分布式环境中的多台机器须要有大量的协调与沟通机制,同时须要对其中可能出问题的中央进行解决。比方让计算机解决两个数字的运算,在一台机器上间接一套代码就能运行了,然而在分布式环境中咱们须要设计一套机制如何将这个运算拆成不同的子工作交给不同的机器,在每台机器实现本人的局部之后再将各自的后果通过某种机制合并到一起造成最终的后果。而这其中如果某台机器故障,或者因为网络通信的问题导致机器无奈连贯,这些异常情况都须要分布式组件进行解决,保障整个集群依然能实现工作。MatrixCube就是为了实现多台机器的分布式数据存储而实现的一套分布式框架。
图-分布式系统
高可用
作为一个数据库系统,存数据是其最起码的职责。在一个分布式环境中,每台机器都会有肯定的出问题概率,不论是硬件环境还是软件环境都有fail的可能性,为了能继续提供服务保证系统的可用性,咱们往往会采纳将同一份数据在复制多个正本的形式,将每个正本放在不同的机器上,以此来晋升可用性,同时因为多正本的存在,在用户来拜访数据的时候咱们也能够通过多台机器同时提供服务来晋升零碎的吞吐能力。应用MatrixCube实现的存储服务反对高可用,因为Raft协定的选举机制,如果一个集群领有2*N+1
的正本数量,那么集群在N
个正本故障的时候,还可能失常的提供读写服务。
强统一
因为多正本的存在,用户能够读取任意节点上的正本。而强统一就是为了保障这些正本之间的数据始终都是统一的,如果在某个正本数据有更新的时候也会先将其余正本同步更新之后才会响应用户来读取,这样用户能始终读到最新的数据。另外一个绝对的概念就是最终一致性,区别在于写入之后马上就通知用户能够读了,然而用户如果马上去读其余正本的时候可能还没有复制实现,所以依然会读到老数据。Matrixcube提供强统一的读写接口,并且承诺一旦数据写入胜利了,后续的读操作就不会读到一个古老的值,肯定会读到之前写入的数据或者更新的数据。MatrixCube采纳了Multi-Raft的形式。Raft是目前应用最宽泛的分布式一致性协定,解释Raft协定和运作机制的文章行业内十分丰盛,这里就不具体开展。简略的来说Raft协定通过Leader选举以及日志复制的办法,保障集群在呈现如机器宕机或者故障的状况下能够始终保持对外提供数据的一致性,且始终维持最新的数据。
图-强统一(Follower1)与最终统一(Follower2)
主动平衡
作为分布式存储系统,除了通过强统一的正本复制机制保障高可用性以外,咱们还应该尽可能多地将多台机器的资源利用起来,以达到更高的应用效率。一个合格的分布式存储应该让每个节点之间的存储压力大致相同,同时对每个节点的拜访压力大致相同,不至于在某些节点上面临过大的存储或者拜访压力,这样整个零碎的性能就会因而受到影响。而MatrixCube就具备这样的调度与主动平衡能力,能够在多节点间放弃存储与负载的平衡,并且在节点发生变化时进行存储与拜访负载的调度,以达到从新均衡。在MatrixCube中,咱们提供了三种级别的主动平衡:
- 实现各节点存储空间的平衡,以高效利用各节点存储资源;
- 各节点的 Raft-Group Leader 的平衡,因为读写申请都须要从Leader通过,以此来达到读写申请的负载平衡;
- 各节点 Table 数据分布的平衡,因为某些表可能是热门数据会被频繁拜访,以此来实现表级别的读写申请平衡。
用户自定义
MatrixCube提供相当灵便的用户自定义能力。MatrixCube不限度单机的数据存储引擎,并且定义了DataStorage接口,任何实现DataStorage的存储引擎都能够接入MatrixCube。而且MatrixCube反对自定义的读写申请,使用者只须要实现这些申请在单机上的逻辑,分布式相干的细节全副交给MatrixCube。因而用户能够十分不便地接入各种不同的单机存储引擎,以及自定义各种不同的读写申请命令。
MatrixCube的架构与运作机制
MatrixCube基本概念
咱们须要先理解一些概念来帮忙咱们更好地了解MatrixCube。
- Store:MatrixCube是一个分布式存储的框架,所以咱们的数据会寄存在很多的节点上,咱们把集群中的一个节点称为一个Store。
- Shard:数据在MatrixCube集群中是分片存储的,每个数据分片咱们称之为一个Shard。一个Store中能够治理多个Shard。
- Replica:为了保障存储服务的高可用,每个Shard的数据是存储多份的,并且散布在不同的Store上,Shard的一个数据正本咱们称之为一个Replica。所以一个Shard会蕴含多个Replica,每个Replica中的数据都是一样的。
- Raft-Group:通过多正本咱们保障了数据的高可用,为了保证数据的
一致性
,咱们采纳Raft
协定来做数据共识,一个Shard的多个Replica会组成一个Raft-Group。
MatrixCube性能组件
- DataStorage: 应用MatrixCube就必须要定义一个DataStorage,用来存储单机数据。咱们须要针对存储服务的特点来设计对应的DataStorage。MatrixCube默认提供了一个残缺的基于KV的DataStorage,因为基于KV的存储能够满足大部分的场景。
- Prophet: Prophet是一个调度模块,主要职责是负责Auto-Rebalance以及维持每个Shard的Replica个数。每个Store以及Shard的Leader Replica都会定期上报心跳信息给Prophet,Prophet会依据这些信息来做出调度决定。MatrixCube须要在集群中指定哪些节点承当调度的职责。
- Raftstore: Raftstore是MatrixCube最外围的组件, 其中实现了Store,Shard,Raft-Log相干的元数据存储,对Multi-Raft协定的反对,全局路由表的构建以及每个节点上的读写Shard Proxy代理性能。
MatrixCube的整体架构
图-MatrixCube整体架构
MatrixCube的工作机制
系统启动与配置
在零碎初始化的时候,MatrixCube会依据集群中每个节点的配置文件来进行初始化。在MatrixCube中,一共有两种类型的节点,一种是调度节点,也就是Prophet节点,另一种是数据节点,只存数据,没有调度性能。两种节点之间目前无奈相互转换,都是在零碎初始化的时候指定好的。MatrixCube的最后三个节点必须都是Prophet节点,这也是MatrixCube所能组成的最小规模集群。Prophet的三个节点形成一个Raft-Group,其中会选举出一个leader,所有的调度申请与信息上报都会到这个Prophet Leader上。Prophet的节点数能够进行配置,然而以Raft协定为基准,必须是2*N+1个节点(N为不小于0的整数)。
数据存储与决裂
在零碎开始启动运行之后,用户开始往零碎中导入数据。MatrixCube在初始化时已读入一个数据分片Shard的大小配置,比方1GB一个Shard。用户写入数据还没有达到1GB的时候,会继续写入同一个Shard,而同时每次写入的数据会同步在三个节点中更新Shard,这三个Shard会形成一个Raft-Group,其中也会选举出一个Leader,对这个Shard的读写申请与信息上报全副会由这个Leader来解决。直到一个Shard达到1GB时,此时MatrixCube会启动Shard决裂机制,也就是把一个Shard平均拆分成两个Shard,也就是1个GB的分片变成了2个500MB的分片,而这个过程是同步在三个节点中产生的,也就是说同时将生成6个Shard,而他们将组成新的2个Raft-Group。
图-Shard决裂
用户读写响应与路由
用户以接口的模式与MatrixCube交互,从而来发动对数据的读写申请。因为Raft-Group的存在,只有每个Raft-Group的Leader能力响应读写申请。而用户的申请可能并不一定间接指向Raft Group Leader,因而咱们就须要一个路由机制,来让用户的申请能被正确的转到它该去的中央。因而每个节点上都会有一个Shard Proxy,这些Proxy会定期接管Prophet给它的全局路由表。咱们后面提到Prophet会承受各个Store与各个Shard的Leader给的心跳信息,因而Prophet是有一张全局的路由信息表的。这个时候Shard Proxy就会晓得用户申请读写那份数据应该在哪个Store的哪个Shard中。这样的话用户无论向集群中哪个节点发动读写申请,最终失去的后果都是一样的,用户不须要关怀Shard在外部存在什么中央。
假如咱们有一个3个Store节点的集群,初始状态如下:
Range | Store1 | Store2 | Store3 | |
---|---|---|---|---|
Shard1 | [key1-key10) | Leader | Follower | Follower |
Shard2 | [key10-key20) | Follower | Leader | Follower |
Shard3 | [key20-key30) | Follower | Follower | Leader |
用户别离向key1,key10和key20数据发送申请,下图阐明了申请如何通过Shard Proxy路由组件并被转发。
图-Shard Proxy对用户申请的转发
节点变动与数据搬迁
在整个集群产生节点变动时,比方集群须要扩缩容,或者呈现机器或者网络故障的时候,咱们就要进行集群的调度。通常来讲,咱们的Prophet会有一个超时机制,在某个节点超过咱们规定的工夫没有心跳上报的时候,咱们这时就认为这个节点曾经下线,咱们将开始数据搬迁流程。在节点缩小的状况下,Prophet会检测到一部分Shard没有足够的Replica组成一个残缺的Raft-Group,这时就须要在现有的节点中找到存储空间比拟充裕的节点,在其中创立这一部分Shard的Replica。而在节点减少的状况下,Prophet会发现多出的节点存储空间比拟充裕,这时会将集群中的一部分Shard进行重新分配,以达到一个各节点绝对平衡的状态。在节点变动的时候,除了Prophet会进行调度意外,每个被毁坏的Shard组成的Raft-Group也会视状况进行调度,如果少了Raft-Group的follower,那在实现Shard的新Replica生成后会从新组成残缺的Raft-Group;如果少了Raft-Group的Leader,那剩下的两份Replica就会先选举出新的Leader,再去新的节点上实现Replica与Raft-Group的生成。
在下图的例子中咱们看到,初始状态的三节点在减少第四节点的状况下,每个节点的4个Shard被均摊到了4个节点上,而原本不平衡的Leader数量也均摊到了每个节点上
图-节点减少时的数据搬迁
在这些机制的组合工作下,MatrixCube就能够将一个单机的存储引擎扩大到一个分布式场景中来应用。
MatrixCube与TiKV的区别
很多社区的小伙伴在之前都接触过TiDB分布式数据库的架构,以及其中负责提供分布式能力的组件TiKV以及负责调度的模块Placement Driver。实际上MatrixCube的性能根本相当于TiKV与PD的联合,MatrixCube除了还在开发中的分布式事务能力以外,其余的高可用,强统一以及调度的能力与TiKV+PD根本保持一致。
MatrixCube与TiKV+PD次要有三点区别:
- TiKV+PD是一个残缺的服务,所有的读写细节都曾经在外部封装实现,用户通过与其定义好的接口与其进行交互。而MatrixCube是一个Library,无奈独自运行,必须与存储引擎一起工作。而且MatrixCube将读写的申请命令交给了用户定义,使用者能够自行去实现各自不同存储引擎的读写申请命令,只须要实现MatrixCube提供的存储引擎接口即可与MatrixCube对接,由MatrixCube负责各自分布式的相干细节。
- PD的调度性能次要体现在存储空间的调度与Raft Group的Leader的调度,能够在正本级别达到负载平衡。而MatrixCube除了在实现这两点外,还实现了表级别的数据分布平衡,从而使得对表的读写申请也能达到绝对平衡的状态。
- TiKV由Rust实现,而PD是由Go实现。因而这套构造在对接过程中须要肯定的中间层接口。而MatrixCube整体都是由Go所实现,因而不存在这样的问题。
总的来说MatrixCube更加看重开发灵活性,开发者能够非常灵活的利用MatrixCube去实现不同地分布式存储引擎。
下期预报
为了向开发者展现MatrixCube的应用,MatrixOne社区筹备了一个非常简单的KV存储的例子,用MatrixCube对接Pebble存储引擎实现了一个分布式存储系统。