MatrixKv
MatrixKV是一个简单的分布式强一致KV存储系统,采用Pebble作为底层的存储引擎,MatrixCube作为分布式组件,以及自定义了最简单的读写请求接口。用户可以非常简单的在任意一个节点发起读写数据的请求,也可以从任意一个节点读到需要的数据。
如果对TiDB架构比较熟悉的同学可以把MatrixKV等同于一个TiKV+PD,而MatrixKV其中使用的RocksDB换成了Pebble。
Step1 环境准备
工具准备
需要用到docker与docker-compose工具,因此需要安装好docker与docker-compose。一般来说可以直接安装Docker-desktop,里面自带了docker引擎,CLI工具及Compose插件。
官方提供了各种操作系统的完整安装包:https://www.docker.com/products/docker-desktop/
docker -v
docker-compose -v
clone代码
将MatrixKV代码Clone到本地。
git clone https://github.com/matrixorigin/matrixkv
Step 2 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 address
join = ""
#内嵌Etcd的client address
client-urls = "http://0.0.0.0:8084"
#内嵌Etcd的advertise client address, 不填写, 默认和`client-urls`一致
advertise-client-urls = "http://node0:8084"
#内嵌Etcd的peer address
peer-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 = false
external-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
Step 3 集群启动
配置好这些选项后,在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
![在这里插入图片描述](https://img-blog.csdnimg.cn/f1384efd742b429da3cc234aea52f2fc.png)
另外注意国内用户如果可能碰到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的节点都以镜像的形式启动了。
Step4 体验请求接口
- 数据写入
curl -X POST -H 'Content-Type: application/json' -d '{"key":"k1","value":"v1"}' http://127.0.0.1:8080/set
// 结果
{“key”:“k1”,“error”:“”}
- 数据读取GET
curl http://127.0.0.1:8080/get?key=k1
// 结果
{“key”:“k1”,“value”:“v1”,“error”:“”}
- 数据删除DELETE
curl -X POST -H 'Content-Type: application/json' -d '{"key":"k1"}' http://127.0.0.1:8080/delete
// 结果
{“key”:“k1”,“error”:“”}
我们可以从集群的任意一个节点发起请求,不管是写入,读取还是删除的请求,Shard Proxy都会自动将请求路由到相应的处理节点上。比如我们可以在node0上写入数据,而在node0到node3上都可以进行读取,是完全一样的。
Step5 数据分片查询与分裂
MatrixCube会在写入的数据量达到一定级别的时候产生Shard分裂,在MatrixKV中,我们将Shard的大小设置成了1024Byte。因此写入数据超过这个尺寸的数据会产生分裂。MatrixKV提供了一个简单的查询当前集群或者当前节点中有多少个Shard的接口。
可以看到集群下有三个id为3,7,8的Shard
当我们写入一个超过1024Byte的数据之后,集群下的Shard会进行分裂
Step6 节点变化
将node3手动关掉
再次访问node3, 会被拒绝
而其他节点正常
体验
matrixkv整体比较简洁,使用比较方便,我也写个分布式的kv存储,这个产品给我了很多启发,也许我之后会将我的简单的kv支持docker,将操作变得更加简单。