Published at 2024-09-12 | Last Update 2024-09-12
Fig. JuiceFS cluster initialization, and how POSIX file operations are handled by JuiceFS.
水平及维护精力所限,文中不免存在错误或过时之处,请酌情参考。 传播知识,尊重劳动,年满十八周岁,转载请注明出处。
Fig. JuiceFS components and architecutre.
如图,本质上可以分为三个组件。
juicefs format ...
可以创建一个 juicefs volume;juicefs config ...
可以修改一个 juicefs volume 的配置;juicefs mount ...
可以把一个 juicefs volume 挂载到机器上,然后用户就可以在里面读写文件了;实际的对象存储,例如 S3、Ceph、阿里云 OSS 等等,存放 JuiceFS volume 内的数据。
TiKV as metadata engine | etcd as metadata engine | |
---|---|---|
管理节点(e.g. leader election) | PD (TiKV cluster manager) | etcd server |
数据节点(存储 juicefs metadata) | TiKV server | etcd server |
数据节点对等 | 无要求 | 完全对等 |
数据一致性粒度 | region-level (TiKV 的概念,region < node ) |
node-level |
Raft 粒度 | region-level (multi-raft,TiKV 的概念) | node-level |
缓存多少磁盘数据在内存中 | 一部分 | 所有 |
集群支持的最大数据量 | PB 级别 |
几十 GB 级别 |
性能(JuiceFS 场景) | 高(猜测是因为 raft 粒度更细,并发读写高) | 低 |
维护和二次开发门槛 | 高(相比 etcd) | 低 |
流行度 & 社区活跃度 | 低(相比 etcd) | 高 |
适用场景 | 大和超大 JuiceFS 集群 | 中小 JuiceFS 集群 |
etcd 集群,
TiKV 方案可以可以理解成把管理和数据存储分开了,
TiKV cluster manager
,负责 leader 选举、multi-raft、元数据到 region 的映射等等;M >= N
;TiKV 方案总结成一句话就是:根据硬件配置干活,能者多劳:内存大、磁盘大就多干活,内存小、磁盘小就少干活。
下面是 7 台 TiKV node 组成的一个集群,其中 3 台机器有 256GB 内存,2 台有 128GB 内存,2 台有 64GB 内存, 可以看到每个 TiKV server 确实只用了各自所在 node 一半左右的内存:
Fig. TiKV engine size and memory usage of a 7-node (with different RAMs) cluster.
用 TiKV 作为元数据引擎,架构如下(先忽略其中的细节信息,稍后会介绍):
Fig. JuiceFS cluster initialization, and how POSIX file operations are handled by JuiceFS.
两个组件的几个核心配置项,
$ cat /etc/tikv/pd-config.toml
name = "pd-node3"
data-dir = "/var/data/pd"
client-urls = "https://192.168.1.1:2379" # 客户端(例如 JuiceFS)访问 PD 时,连接这个地址
peer-urls = "https://192.168.1.1:2380" # 其他 PD 节点访问这个 PD 时,连接这个地址,也就是集群内互相通信的地址
# 创建集群时的首批 PD
initial-cluster-token = "<anything you like>"
initial-cluster = "pd-node1=https://192.168.1.3:2380,pd-node2=https://192.168.1.2:2380,pd-node3=https://192.168.1.1:2380"
可以看到,PD 的配置和 etcd 就比较类似,需要指定其他 PD 节点地址,它们之间互相通信。
TiKV 节点(tikv-server)的配置就不一样了,
$ cat /etc/tikv/tikv-config.toml
[pd]
endpoints = ["https://192.168.1.1:2379", "https://192.168.1.2:2379", "https://192.168.1.3:2379"]
[server]
addr = "192.168.1.1:20160" # 服务地址,JuiceFS client 会直接访问这个地址读写数据
status-addr = "192.168.1.1:20180" # prometheus
可以看到,
Fig. JuiceFS cluster initialization, and how POSIX file operations are handled by JuiceFS.
对应图中 step 1 & 2:
对应图中 step 3~5:
step 3. JuiceFS 客户端连接到 PD;发出读写文件请求;
TiKV 内部存储的都是 JuiceFS 的元数据。具体来说又分为两种:
foo.txt
,在 TiKV 里面就会对应一条或多条元数据来描述这个文件的信息;TiKV 是扁平的 KV 存储,所以以上两类文件都放在同一个扁平空间,通过 key 访问。 本文先简单通过命令看看里面的元数据长什么样,下一篇再结合具体 JuiceFS 操作来深入解读这些元数据。
本文所用的
tikv-ctl.sh
等脚本就是tikv-ctl
加上几个证书参数。看起来更简洁。
tikv-ctl scan
扫描 key/valuetikv-ctl 不支持只列出所有 keys,所以只能 key 和 value 一起打印(扫描)。
扫描前缀是 foo
开头的所有 key:
$ ./tikv-ctl.sh scan --from 'zfoo' --to 'zfop' --limit 100
...
key: zfoo-dev\375\377A\001\000\000\000\000\000\000\377\000Dfile3.\377txt\000\000\000\000\000\372
key: zfoo-dev\375\377A\001\000\000\000\000\000\000\377\000Dfile4.\377txt\000\000\000\000\000\372
...
key: zfoo-dev\375\377setting\000\376
default cf value: start_ts: 452330324173520898 value: 7B0A224E616D65...
扫描的时候一定要在 key 前面加一个 z
前缀,这是 TiKV 的一个设计,
The raw-scan command scans directly from the RocksDB. Note that to scan data keys you need to add a ‘z’ prefix to keys.
代码出处 components/keys/src/lib.rs。
但对用户来说不是太友好,暴露了太多内部细节,没有 etcdctl
方便直接。
tikv-ctl mvcc
查看给定 key 对应的 value$ ./tikv-ctl.sh mvcc -k 'zfoo-dev\375\377A\001\000\000\000\000\000\000\377\000Dfile1.\377txt\000\000\000\000\000\372' --show-cf default,lock,write
key: zfoo-dev\375\377A\001\000\000\000\000\000\000\377\000Dfile1.\377txt\000\000\000\000\000\372
write cf value: start_ts: 452330816414416901 commit_ts: 452330816414416903 short_value: 010000000000000002
tikv-ctl --decode <key>
解除字符转义# tikv escaped format -> raw format
./tikv-ctl.sh --decode 'foo-dev\375\377A\001\000\000\000\000\000\000\377\000Dfile4.\377txt\000\000\000\000\000\372'
foo-dev\375A\001\000\000\000\000\000\000\000Dfile4.txt
tikv-ctl --to-hex
:转义表示 -> 十六进制表示$ ./tikv-ctl.sh --to-hex '\375'
FD
tikv-ctl --to-escaped <value>
:十六进制 value -> 带转义的字符串./tikv-ctl.sh scan --from 'zfoo' --to 'zfop' --limit 100
key: zfoo-dev\375\377setting\000\376
default cf value: start_ts: 452330324173520898 value: 7B0A224E616D65...
其中的 value 是可以解码出来的,
# hex -> escaped string
$ ./tikv-ctl.sh --to-escaped '7B0A224...'
{\n\"Name\": \"...\",\n\"UUID\": \"8cd1ac73\",\n\"Storage\": \"S3\",\n\"Bucket\": \"http://xxx\",\n\"AccessKey\": \"...\",\n\"BlockSize\": 4096,\n\"Compression\": \"none\",\n\"KeyEncrypted\": true,\n\"MetaVersion\": 1,\n\"UploadLimit\": 0,\n\"DownloadLimit\": 0,\n\"\": \"\"\n}
本文介绍了一些 JuiceFS 元数据引擎相关的内容。