上篇文章具体的介绍了MatrixCube的性能与架构,MatrixCube是MatrixOne数据库取得分布式能力的重要组件。明天咱们将通过一个简略的分布式存储demo试验来残缺的体验下MatrixCube的性能。

MatrixKV我的项目介绍

这个demo我的项目叫做MatrixKV,在Github的仓库地址是:https://github.com/matrixorig...。

MatrixKV是一个简略的分布式强统一KV存储系统,采纳Pebble作为底层的存储引擎,MatrixCube作为分布式组件,以及自定义了最简略的读写申请接口。用户能够非常简单的在像任意一个节点发动读写数据的申请,也能够从任意一个节点读到须要的数据。

如果对TiDB架构比拟相熟的同学能够把MatrixKV等同于一个TiKV+PD,而MatrixKV其中应用的RocksDB换成了Pebble。

本次试验以Docker模仿一个小型MatrixKV集群的模式,来进一步阐明MatrixCube的性能与运作机制。

第一步:环境筹备

工具筹备

咱们这个试验须要用到docker与docker-compose工具,因而须要装置好docker与docker-compose。一般来说能够间接装置Docker-desktop,外面自带了docker引擎,CLI工具及Compose插件。官网提供了各种操作系统的残缺安装包:https://www.docker.com/produc...

装置好之后能够通过以下命令查看是否装置实现,如果顺利完成装置的话会显示相应版本。

docker -vdocker-compose -v

Docker自身是跨平台的,因而本次试验对操作系统没有要求,不过举荐macOS12+或者CentOS8+(因为残缺验证过)。本次教程是在macOS12的环境中容许的。本次试验因为只有单机的一块硬盘,Prophet对各个节点进行负载再均衡Rebalance的性能无奈应用,因而在本次试验中会呈现节点负载和数据量并不平衡的状况,而在残缺的多机系统中能够更好体验这个性能。

Clone代码

将MatrixKV代码Clone到本地。

git clone https://github.com/matrixorigin/matrixkv  

第二步:MatrixKV集群配置

在上一篇文章中,咱们提到过MatrixCube基于Raft构建分布式共识协定,因而须要至多三个节点来作为最小部署规模,而最后的三个节点都属于调度用的Prophet节点。咱们这次试验筹备的这个小型集群有四个节点,其中三个为Prophet节点, 一个为数据节点。咱们以docker进行容器包装的模式来在单机上进行模仿。

Prophet节点设置

咱们能够看到在/cfg文件夹中有node0-node3的配置文件,其中Node0-Node2均为Prophet节点,Node3为数据节点。Prophet节点的配置以Node0举例如下如下:

#raft-group的RPC通信地址,节点之间通过这个地址来发送raft message和snapshot。addr-raft = "node0:8081" #对客户端凋谢的地址,客户通过这个端口和cube来交互自定义的业务申请。addr-client = "node0:8082"#Cube的数据寄存目录,每个节点会依据这个目录所在的磁盘统计存储的应用状况,上报给调度节点。dir-data = "/tmp/matrixkv"[raft]#Cube会对Raft的写申请做batch,会把多个写申请合并到一个Raft-Log,只做一次Raft的Proposal,这个配置指定一个Proposal的大小,这个 #配置取决于利用的具体情况max-entry-bytes = "200MB"[replication]# 1. 一个raft-group的正本最大的down time,当一个正本的down time超过这个值,调度节点就会认为这个正本用久的故障了,# 而后会在集群中抉择一个适合的节点来从新创立这个正本。如果前面这个节点又重新启动了,那么调度节点会告诉这个正本# 销毁本人。# 2. 这里的默认设置个别是30分钟,这个工夫咱们认为是设施个别呈现故障能够在30分钟内实现故障解决复原,如果超过这个工夫阐明曾经无奈  # 复原。在这里咱们为了做试验的不便,设置成15秒。max-peer-down-time = "15s"[prophet]#该Prophet调度节点的名称name = "node0"#该Prophet调度节点对外的RPC地址rpc-addr = "node0:8083"#指定该节点为Prophet节点prophet-node = true[prophet.schedule]# Cube集群中的所有节点都会定期发送心跳到调度的Leader节点,当一个节点超过肯定的工夫都没有发送心跳,# 那么调度节点会把这个节点的状态批改为Down,并且会把这个节点上,所有的Shard在集群其余节点来重建,# 当这个节点复原后,这个节点上的所有Shard都会收到销毁的调度音讯。# 这里也是为了试验不便设置成10秒,默认也是30分钟。max-container-down-time = "10s"#Prophet中内嵌一个ETCD作为存储元数据的组件[prophet.embed-etcd]#Cube的Prophet调度节点会先后启动, 假如咱们有node0, node1, node2三个调度节点, 第一个启动的是node0节点, 那么node0节点就会#组成一个只有一个正本的etcd, 对于node0而言, `join`参数不须要填写, 前面的node1, node1启动的时候, `join`设置为node1#的Etcd的Peer addressjoin = ""#内嵌Etcd的client addressclient-urls = "http://0.0.0.0:8084"#内嵌Etcd的advertise client address, 不填写, 默认和`client-urls`统一advertise-client-urls = "http://node0:8084"#内嵌Etcd的peer addresspeer-urls = "http://0.0.0.0:8085"#内嵌Etcd的advertise peer address, 不填写, 默认和`peer-urls`统一advertise-peer-urls = "http://node0:8085"[prophet.replication]#每个Shard最多多少个正本,当Cube的调度节点周期性巡检的时候,发现Shard的正本个数和这个值不匹配的时候,会执行创立正本或者删除正本的调#度操作。max-replicas = 3 

Node1与Node2的配置除了须要在ETCD配置局部中join后面的节点,其余的简直与Node0没有差异。

数据节点设置

而Node3作为数据节点,则配置绝对比较简单,除了prophet-node设置成false以外,其余没有须要额定配置的局部。

addr-raft = "node3:8081"addr-client = "node3:8082"dir-data = "/tmp/matrixkv"[raft]max-entry-bytes = "200MB"[prophet]name = "node3"rpc-addr = "node3:8083"prophet-node = falseexternal-etcd = [    "http://node0:8084",    "http://node1:8084",    "http://node2:8084",] 
Docker-Compose设置

Docker-compose将依据docker-compose.yml中的配置来进行容器启动,其中咱们须要将每个节点的数据目录改成本人指定的目录。咱们以Node0为例。

node0:    image: matrixkv    ports:      - "8080:8080"    volumes:      - ./cfg/node0.toml:/etc/cube.toml      # /data/node0须要批改成用户指定的某个本地目录      - /data/node0:/data/matrixkv    command:       - --addr=node0:8080      - --cfg=/etc/cube.toml      # shard will split after 1024 bytes      - --shard-capacity=1024

第三步:集群启动

配置好这些选项后,在MatrixKV代码库中,咱们曾经写好了构建镜像的dockerfile及启动构建流程的Makefile。

咱们间接在MatrixKV的门路下运行make docker命令,它会将MatrixKV整体打包成镜像。

#如果是MAC X86架构平台或者Linux,能够间接运行以下命令(make docker)#如果是MAC的ARM版本,则须要将Makefile中的docker build -t matrixkv -f Dockerfile .改成docker buildx build --platform linux/amd64 -t matrixkv -f Dockerfile .make docker

另外留神国内用户如果可能碰到go源站速度极慢无奈下载依赖库的状况,能够在Dockerfile中减少go的中国源站设置:

RUN go env -w GOPROXY=https://goproxy.cn,direct

而后通过docker-compose up命令将MatrixKV的镜像别离依据不同的节点配置启动四份,从而造成咱们的Node0到Node3的四节点集群。

docker-compose up

在docker desktop中咱们应该就能够看到咱们的4个MatrixKV的节点都以镜像的模式启动了。

在看到如下日志中呈现各个节点启动监听8080端口的时候,就代表集群曾经启动实现。

同时能够看到在咱们指定的数据目录中曾经开始生成了很多存储数据的文件夹以及一些初始文件。

敞开集群的话能够在启动的命令行中进行过程即可,或者也能够在Docker desktop中以图形化界面形式进行任意节点。

第四步:读写申请接口与路由

在启动好集群之后,咱们就能够对集群进行读写数据的申请。MatrixKV包装了几个非常简单的数据读写接口:

  • 数据写入SET:

    curl -X POST  -H 'Content-Type: application/json' -d '{"key":"k1","value":"v1"}' http://127.0.0.1:8080/set    
  • 数据读取GET:

    curl http://127.0.0.1:8080/get?key=k1
  • 数据删除DELETE

    curl -X POST -H 'Content-Type: application/json' -d '{"key":"k1"}' http://127.0.0.1:8080/delete

上一篇文章中介绍了MatrixCube中的Shard Proxy,这个组件能够使得咱们能够从集群的任意一个节点发动申请,不论是写入,读取还是删除的申请,Shard Proxy都会主动将申请路由到相应的解决节点上。

比方咱们能够在node0上写入数据,而在node0到node3上都能够进行读取,是齐全一样的。

//向node0发动写入申请curl -X POST  -H 'Content-Type: application/json' -d '{"key":"k1","value":"v1"}' http://127.0.0.1:8080/set//从node0-node3进行读取curl http://127.0.0.1:8080/get?key=k1curl http://127.0.0.1:8081/get?key=k1curl http://127.0.0.1:8082/get?key=k1curl http://127.0.0.1:8083/get?key=k1

这里如果试验的系统配置及写入读取数据规模更大一些的话,大家也能够验证一些更极其的场景,比方有多个客户端在疾速的读取各个节点的数据,而每次写入的数据在客户端读到的时候都能够保障是最新的以及统一的,通过这种形式能够验证MatrixCube的强一致性,保障任何时刻从任何节点读到的数据都是最新的以及统一的。

第五步:数据分片查问与决裂

MatrixCube会在写入的数据量达到肯定级别的时候产生Shard决裂,在MatrixKV中,咱们将Shard的大小设置成了1024Byte。因而写入数据超过这个尺寸的数据会产生决裂。MatrixKV提供了一个简略的查问以后集群或者以后节点中有多少个Shard的接口。

#以后集群中的Shard状况curl http://127.0.0.1:8080/shards#以后节点中的Shard状况curl http://127.0.0.1:8080/shards?local=true

咱们启动集群后能够看到初始状态下集群只有3个Shard,id别离为4, 6, 8, 而他们理论存储的节点在node0,node2与node3中。

而在咱们通过以下命令写入一个超过1024Byte的数据之后,咱们能够看到node0,node2与node3中的Shard全副进行了决裂,每个原来的Shard都造成了两个新的Shard,初始状态下的3个Shard变成了11,12,13,15,16,17六个Shard。

#test.json是测试数据,数据内容须要严格依照Key,Value格局标准,比方{"key":"item0","value":"XXXXXXXXXXX"}curl -X POST  -H 'Content-Type: application/json' -d@test.json http://127.0.0.1:8083/set

同时咱们依然能够在任意一个节点拜访到咱们写入的数据。

第六步:节点变动与正本生成

接下来咱们再来看下MatrixCube的高可用保障的性能。咱们能够通过Docker desktop来手动关停单个容器,以此来模仿实在环境中的机器故障状况。

在第五步中咱们输出一个较大数据之后零碎整体存在6个Shard,每个Shard有3个Replica。咱们当初将node3手动关掉。

尝试再拜访node3的命令均以失败告终。

然而从其余节点发动读申请,数据依然都能够读取,这也就是分布式系统对整体高可用性的体现。

依照后面咱们的设置,store3的心跳10秒内没有发到Prophet,Prophet会认为这个Store曾经下线,而通过查看目前正本状况发现,所有的Shard都只有两个Replica,为了满足3正本的要求,Prophet会开始主动去寻找闲暇节点,将Shard复制到下面,在咱们这里也就是node1,那么咱们再来看下每个节点Shard的状况。

能够看到node1中以前是没有Shard的,当初也与node0和node2一样都有6个shard。这也就是Prophet主动的正本生成性能,始终保证系统中有三份副原本保障高可用性。

除了正本生成以外,如果呈现问题的是某一个Shard的Raft Group Leader,那么这个Shard的Raft Group会从新发动选举,而后先选举新的Leader,再由Leader发动申请进行新的正本生成。这个大家能够自行试验,并且通过日志的信息进行验证。

MatrixKV代码扫描

通过整个试验咱们曾经残缺体验了在MatrixCube帮忙下将一个单机的KV存储引擎Pebble变成了一个分布式的KV存储。而其中须要MatrixKV自身实现的代码是非常简单的。总的来说就只有4个go文件,不到300行代码就能够实现MatrixKV的全副搭建。

  • /cmd/matrixkv.go: 整体程序启动的入口,进行最根本的初始化并启动服务。
  • /pkg/config/config.go: 定义了一个MatrixKV整体配置的数据结构。
  • /pkg/metadata/metadata.go:定义了用户与MatrixKV读写交互申请的数据结构。
  • /pkg/server/server.go:这是MatrixKV的最主体性能,其中次要做了三件事:

    • 定义MatrixKV server的数据结构。
    • 定义Set/Get/Delete等相干申请的Executor具体实现。
    • 调用Pebble库作为单机存储引擎,实现MatrixCube指定的DataStorage接口,将MatrixCube的Config项设置到相应办法上。

福利工夫

请加小助手微信,ID:MatrixOrigin001

  1. 发送您的MatrixKV初体验残缺录屏,即可取得限量MatrixOrigin T恤一件。
  2. 发送您的MatrixKV初体验残缺录屏并公布在CSDN,即可取得价值200元的京东卡+限量MatrixOrigin T恤一件。

总结

作为MatrixCube系列的第二篇,咱们通过基于MatrixCube和Pebble所实现的一个自定义分布式存储系统MatrixKV的试验,更进一步的展现了MatrixCube的运作机制,同时也展现了300行代码即能够迅速的搭建一个残缺强统一的分布式存储系统。下一期咱们将带来MatrixCube更加深刻的代码精讲,敬请期待。