JuiceFS:元数据详解

种地  金牌会员 | 2024-6-10 13:34:34 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 557|帖子 557|积分 1671

引言

  juicefs是一款面向云原生设计的高性能分布式文件系统,其有如下特点:
  

  • 数据存储和元数据存储分离,可以适配多种数据和元数据存储引擎。
  

  • 后端存储可以直接对接各种对象存储,使用起来更方便,更加适配云服务趋势。
  相干技术架构可直接参考:https://juicefs.com/docs/zh/community/architecture
  JuiceFS部署

  部署规划

  

  • 本文使用mysql作为元数据存储引擎。
  

  • 由于主要关注元数据构造,使用s3协议的对象存储作为数据存储引擎。
  部署方法

  

  • 安装mysql,并创建database juicefs
  

  • 安装juicefs
  1. [root@k8s-master /data/juicefs]# tar -zxf juicefs-1.0.3-linux-amd64.tar.gz
  2. [root@k8s-master /data/juicefs]# sudo install juicefs /usr/local/bin/
复制代码


  • format,使用mysql作为元数据存储引擎,本地目次/var/jfs/myjfs作为后端存储
  1. [root@k8s-master /data/juicefs]# juicefs format --storage s3 --bucket http://100.99.50.95/jfs --access-key xxxxxxxx --secret-key xxxxxxxx "mysql://root:@(127.0.0.1:3306)/juicefs" myjfs
  2. 2023/01/11 14:07:06.680579 juicefs[3629024] <INFO>: Meta address: mysql://root:****@(127.0.0.1:3306)/juicefs [interface.go:402]
  3. 2023/01/11 14:07:06.681384 juicefs[3629024] <WARNING>: the database does not support read-only transaction [sql.go:686]
  4. 2023/01/11 14:07:06.681977 juicefs[3629024] <INFO>: Data use s3://jfs/myjfs/ [format.go:429]
  5. 2023/01/11 14:07:06.938532 juicefs[3629024] <INFO>: Volume is formatted as {
  6.   "Name": "myjfs",
  7.   "UUID": "3f584ef7-0fa1-4f75-813e-3763b73977ee",
  8.   "Storage": "s3",
  9.   "Bucket": "http://100.99.50.95/jfs",
  10.   "AccessKey": "xxxxxxxx",
  11.   "SecretKey": "xxxxxxxx",
  12.   "BlockSize": 4096,
  13.   "Compression": "none",
  14.   "KeyEncrypted": true,
  15.   "TrashDays": 1,
  16.   "MetaVersion": 1
  17. } [format.go:466]
复制代码


  • mount,将文件系统myjfs,mount到目次/data/juicefs/myjfs目次
  1. [root@k8s-master /data/juicefs]# juicefs mount "mysql://root:@(127.0.0.1:3306)/juicefs" /data/juicefs/myjfs/2023/01/11 14:08:15.368521 juicefs[3630386] <INFO>: Meta address: mysql://root:****@(127.0.0.1:3306)/juicefs [interface.go:402]
  2. 2023/01/11 14:08:15.369229 juicefs[3630386] <WARNING>: the database does not support read-only transaction [sql.go:686]
  3. 2023/01/11 14:08:15.370647 juicefs[3630386] <INFO>: Data use s3://jfs/myjfs/ [mount.go:428]
  4. 2023/01/11 14:08:15.370959 juicefs[3630386] <INFO>: Disk cache (/var/jfsCache/3f584ef7-0fa1-4f75-813e-3763b73977ee/): capacity (102400 MB), free ratio (10%), max pending pages (15) [disk_cache.go:94]
  5. 2023/01/11 14:08:15.381783 juicefs[3630386] <INFO>: Create session 1 OK with version: 1.0.3+2022-12-27.e4bf15a [base.go:275]
  6. 2023/01/11 14:08:15.382575 juicefs[3630386] <INFO>: Prometheus metrics listening on 127.0.0.1:9567 [mount.go:161]
  7. 2023/01/11 14:08:15.382653 juicefs[3630386] <INFO>: Mounting volume myjfs at /data/juicefs/myjfs/ ... [mount_unix.go:181]
  8. 2023/01/11 14:08:15.872197 juicefs[3630386] <INFO>: OK, myjfs is ready at /data/juicefs/myjfs/ [mount_unix.go:45]
复制代码
JuiceFS元数据分析

  在mount目次中写入如下数据。
  1. [root@k8s-master /data/juicefs/myjfs]# tree -h
  2. .
  3. ├── [4.0K]  dir0
  4. │   └── [1.0M]  file1
  5. └── [256M]  file1
复制代码
edge:通过目次名称找到inode

  如果需要找到文件myjfs/dir0/file1,通过下表可以先找到dir0,其inode为3,然后找到以3为parent的file1,其inode为4。
  1. MariaDB [juicefs]> select * from jfs_edge;
  2. +----+--------+-------+-------+------+
  3. | id | parent | name  | inode | type |
  4. +----+--------+-------+-------+------+
  5. |  1 |      1 | file1 |     2 |    1 |
  6. |  2 |      1 | dir0  |     3 |    2 |
  7. |  3 |      3 | file1 |     4 |    1 |
  8. +----+--------+-------+-------+------+
复制代码
inode:文件/目次属性

  1. MariaDB [juicefs]> select * from jfs_node;
  2. +---------------------+------+-------+------+-----+-----+------------------+------------------+------------------+-------+-----------+------+--------+
  3. | inode               | type | flags | mode | uid | gid | atime            | mtime            | ctime            | nlink | length    | rdev | parent |
  4. +---------------------+------+-------+------+-----+-----+------------------+------------------+------------------+-------+-----------+------+--------+
  5. |                   1 |    2 |     0 |  511 |   0 |   0 | 1673417226937074 | 1673417630041311 | 1673417630041311 |     3 |      4096 |    0 |      1 |
  6. |                   2 |    1 |     0 |  420 |   0 |   0 | 1673417333270140 | 1673417336289864 | 1673417336289864 |     1 | 268435456 |    0 |      1 |
  7. |                   3 |    2 |     0 |  493 |   0 |   0 | 1673417630041311 | 1673417700029898 | 1673417700029898 |     2 |      4096 |    0 |      1 |
  8. |                   4 |    1 |     0 |  420 |   0 |   0 | 1673417700029898 | 1673417700121148 | 1673417700121148 |     1 |   1048576 |    0 |      3 |
  9. | 9223372032828243968 |    2 |     0 |  365 |   0 |   0 | 1673417226937074 | 1673417226937074 | 1673417226937074 |     2 |      4096 |    0 |      1 |
  10. +---------------------+------+-------+------+-----+-----+------------------+------------------+------------------+-------+-----------+------+--------+
复制代码
chunk:某个chunk与inode和slice的对应关系

  

  • inode2对应文件myjfs/file1,其为256MB,包含了4个64M的chunk。
  

  • inode4对应文件myjfs/dir0/file1,其为1MB,因此只包含一个chunk。
  由于其在表中的slices为blob范例,因此无法在此处打印出来。
  1. MariaDB [juicefs]> select * from jfs_chunk;
  2. +----+-------+------+--------------------------+
  3. | id | inode | indx | slices                   |
  4. +----+-------+------+--------------------------+
  5. |  1 |     2 |    0 |                       |
  6. |  2 |     2 |    1 |                       |
  7. |  3 |     2 |    2 |                       |
  8. |  4 |     2 |    3 |                       |
  9. |  5 |     4 |    0 |                       |
  10. +----+-------+------+--------------------------+
复制代码
block:文件在对象存储中的对象文件

  使用下面下令可以表现出这个文件在对象存储中的存储情况。
  如myjfs/dir0/file1在对象存储中存储在bucket jfs中,其对象名称为myjfs/chunks/0/0/6_0_1048576。
  1. [root@k8s-master /data/juicefs/myjfs]# juicefs info dir0/file1
  2. dir0/file1 :
  3.   inode: 4
  4.   files: 1
  5.    dirs: 0
  6. length: 1.00 MiB (1048576 Bytes)
  7.    size: 1.00 MiB (1048576 Bytes)
  8.    path: /dir0/file1
  9. objects:
  10. +------------+------------------------------+---------+--------+---------+
  11. | chunkIndex |          objectName          |   size  | offset |  length |
  12. +------------+------------------------------+---------+--------+---------+
  13. |          0 | myjfs/chunks/0/0/6_0_1048576 | 1048576 |      0 | 1048576 |
  14. +------------+------------------------------+---------+--------+---------+
复制代码
元数据编码分析

  inode

  inode的ID为mysql中的自增id。
  数据对象文件名

  可见源码,其由slice id,block indx,blocksize构成
  1. func (s *rSlice) key(indx int) string {
  2.     if s.store.conf.HashPrefix {
  3.         return fmt.Sprintf("chunks/%02X/%v/%v_%v_%v", s.id%256, s.id/1000/1000, s.id, indx, s.blockSize(indx))
  4.     }
  5.     return fmt.Sprintf("chunks/%v/%v/%v_%v_%v", s.id/1000/1000, s.id/1000, s.id, indx, s.blockSize(indx))
  6. }
复制代码
slice id

  slice id通过在全局的id池中获取,源码如下
  1. func (m *baseMeta) NewSlice(ctx Context, id *uint64) syscall.Errno {
  2.     m.freeMu.Lock()
  3.     defer m.freeMu.Unlock()
  4.     if m.freeSlices.next >= m.freeSlices.maxid {
  5.         v, err := m.en.incrCounter("nextChunk", sliceIdBatch)
  6.         if err != nil {
  7.             return errno(err)
  8.         }
  9.         m.freeSlices.next = uint64(v) - sliceIdBatch
  10.         m.freeSlices.maxid = uint64(v)
  11.     }
  12.     *id = m.freeSlices.next
  13.     m.freeSlices.next++
  14.     return 0
  15. }
复制代码
block idx

  某个chunk为64M,每个block为4M,因此id依次递增
  综上,myjfs/file1的数据对象列表为。
  1. [root@k8s-master /data/juicefs/myjfs]# juicefs info file1
  2. file1 :
  3.   inode: 2
  4.   files: 1
  5.    dirs: 0
  6. length: 256.00 MiB (268435456 Bytes)
  7.    size: 256.00 MiB (268435456 Bytes)
  8.    path: /file1
  9. objects:
  10. +------------+-------------------------------+---------+--------+---------+
  11. | chunkIndex |           objectName          |   size  | offset |  length |
  12. +------------+-------------------------------+---------+--------+---------+
  13. |          0 | myjfs/chunks/0/0/1_0_4194304  | 4194304 |      0 | 4194304 |
  14. |          0 | myjfs/chunks/0/0/1_1_4194304  | 4194304 |      0 | 4194304 |
  15. |          0 | myjfs/chunks/0/0/1_2_4194304  | 4194304 |      0 | 4194304 |
  16. |          0 | myjfs/chunks/0/0/1_3_4194304  | 4194304 |      0 | 4194304 |
  17. |          0 | myjfs/chunks/0/0/1_4_4194304  | 4194304 |      0 | 4194304 |
  18. |          0 | myjfs/chunks/0/0/1_5_4194304  | 4194304 |      0 | 4194304 |
  19. |          0 | myjfs/chunks/0/0/1_6_4194304  | 4194304 |      0 | 4194304 |
  20. |          0 | myjfs/chunks/0/0/1_7_4194304  | 4194304 |      0 | 4194304 |
  21. |          0 | myjfs/chunks/0/0/1_8_4194304  | 4194304 |      0 | 4194304 |
  22. |          0 | myjfs/chunks/0/0/1_9_4194304  | 4194304 |      0 | 4194304 |
  23. |          0 | myjfs/chunks/0/0/1_10_4194304 | 4194304 |      0 | 4194304 |
  24. |          0 | myjfs/chunks/0/0/1_11_4194304 | 4194304 |      0 | 4194304 |
  25. |          0 | myjfs/chunks/0/0/1_12_4194304 | 4194304 |      0 | 4194304 |
  26. |          0 | myjfs/chunks/0/0/1_13_4194304 | 4194304 |      0 | 4194304 |
  27. |          0 | myjfs/chunks/0/0/1_14_4194304 | 4194304 |      0 | 4194304 |
  28. |          0 | myjfs/chunks/0/0/1_15_4194304 | 4194304 |      0 | 4194304 |
  29. |          1 | myjfs/chunks/0/0/3_0_4194304  | 4194304 |      0 | 4194304 |
  30. |          1 | myjfs/chunks/0/0/3_1_4194304  | 4194304 |      0 | 4194304 |
  31. |          1 | myjfs/chunks/0/0/3_2_4194304  | 4194304 |      0 | 4194304 |
  32. |          1 | myjfs/chunks/0/0/3_3_4194304  | 4194304 |      0 | 4194304 |
  33. |          1 | myjfs/chunks/0/0/3_4_4194304  | 4194304 |      0 | 4194304 |
  34. |          1 | myjfs/chunks/0/0/3_5_4194304  | 4194304 |      0 | 4194304 |
  35. |          1 | myjfs/chunks/0/0/3_6_4194304  | 4194304 |      0 | 4194304 |
  36. |          1 | myjfs/chunks/0/0/3_7_4194304  | 4194304 |      0 | 4194304 |
  37. |          1 | myjfs/chunks/0/0/3_8_4194304  | 4194304 |      0 | 4194304 |
  38. |          1 | myjfs/chunks/0/0/3_9_4194304  | 4194304 |      0 | 4194304 |
  39. |          1 | myjfs/chunks/0/0/3_10_4194304 | 4194304 |      0 | 4194304 |
  40. |          1 | myjfs/chunks/0/0/3_11_4194304 | 4194304 |      0 | 4194304 |
  41. |          1 | myjfs/chunks/0/0/3_12_4194304 | 4194304 |      0 | 4194304 |
  42. |          1 | myjfs/chunks/0/0/3_13_4194304 | 4194304 |      0 | 4194304 |
  43. |          1 | myjfs/chunks/0/0/3_14_4194304 | 4194304 |      0 | 4194304 |
  44. |          1 | myjfs/chunks/0/0/3_15_4194304 | 4194304 |      0 | 4194304 |
  45. |          2 | myjfs/chunks/0/0/4_0_4194304  | 4194304 |      0 | 4194304 |
  46. |          2 | myjfs/chunks/0/0/4_1_4194304  | 4194304 |      0 | 4194304 |
  47. |          2 | myjfs/chunks/0/0/4_2_4194304  | 4194304 |      0 | 4194304 |
  48. |          2 | myjfs/chunks/0/0/4_3_4194304  | 4194304 |      0 | 4194304 |
  49. |          2 | myjfs/chunks/0/0/4_4_4194304  | 4194304 |      0 | 4194304 |
  50. |          2 | myjfs/chunks/0/0/4_5_4194304  | 4194304 |      0 | 4194304 |
  51. |          2 | myjfs/chunks/0/0/4_6_4194304  | 4194304 |      0 | 4194304 |
  52. |          2 | myjfs/chunks/0/0/4_7_4194304  | 4194304 |      0 | 4194304 |
  53. |          2 | myjfs/chunks/0/0/4_8_4194304  | 4194304 |      0 | 4194304 |
  54. |          2 | myjfs/chunks/0/0/4_9_4194304  | 4194304 |      0 | 4194304 |
  55. |          2 | myjfs/chunks/0/0/4_10_4194304 | 4194304 |      0 | 4194304 |
  56. |          2 | myjfs/chunks/0/0/4_11_4194304 | 4194304 |      0 | 4194304 |
  57. |          2 | myjfs/chunks/0/0/4_12_4194304 | 4194304 |      0 | 4194304 |
  58. |          2 | myjfs/chunks/0/0/4_13_4194304 | 4194304 |      0 | 4194304 |
  59. |          2 | myjfs/chunks/0/0/4_14_4194304 | 4194304 |      0 | 4194304 |
  60. |          2 | myjfs/chunks/0/0/4_15_4194304 | 4194304 |      0 | 4194304 |
  61. |          3 | myjfs/chunks/0/0/5_0_4194304  | 4194304 |      0 | 4194304 |
  62. |          3 | myjfs/chunks/0/0/5_1_4194304  | 4194304 |      0 | 4194304 |
  63. |          3 | myjfs/chunks/0/0/5_2_4194304  | 4194304 |      0 | 4194304 |
  64. |          3 | myjfs/chunks/0/0/5_3_4194304  | 4194304 |      0 | 4194304 |
  65. |          3 | myjfs/chunks/0/0/5_4_4194304  | 4194304 |      0 | 4194304 |
  66. |          3 | myjfs/chunks/0/0/5_5_4194304  | 4194304 |      0 | 4194304 |
  67. |          3 | myjfs/chunks/0/0/5_6_4194304  | 4194304 |      0 | 4194304 |
  68. |          3 | myjfs/chunks/0/0/5_7_4194304  | 4194304 |      0 | 4194304 |
  69. |          3 | myjfs/chunks/0/0/5_8_4194304  | 4194304 |      0 | 4194304 |
  70. |          3 | myjfs/chunks/0/0/5_9_4194304  | 4194304 |      0 | 4194304 |
  71. |          3 | myjfs/chunks/0/0/5_10_4194304 | 4194304 |      0 | 4194304 |
  72. |          3 | myjfs/chunks/0/0/5_11_4194304 | 4194304 |      0 | 4194304 |
  73. |          3 | myjfs/chunks/0/0/5_12_4194304 | 4194304 |      0 | 4194304 |
  74. |          3 | myjfs/chunks/0/0/5_13_4194304 | 4194304 |      0 | 4194304 |
  75. |          3 | myjfs/chunks/0/0/5_14_4194304 | 4194304 |      0 | 4194304 |
  76. |          3 | myjfs/chunks/0/0/5_15_4194304 | 4194304 |      0 | 4194304 |
  77. +------------+-------------------------------+---------+--------+---------+
复制代码
附:juicefs info下令

  1. func info(ctx *cli.Context) error {
  2.     ...
  3.     // 获取文件对应的inode
  4.     inode, err = utils.GetFileInode(d)
  5.     ...
  6.     // 打开一个临时文件.control
  7.     f := openController(d)
  8.     ...
  9.     // 将数据写入到临时文件
  10.     _, err = f.Write(wb.Bytes())
  11.     ...
  12.     // 根据临时文件中的inode,读取chunk,slice,block信息
  13.     // 此函数中包含了一个reader.Read(sizeBuf[n:])操作,读取信息
  14.     err = resp.Decode(f)
  15.     ...
  16.     // 打印相关数据
  17. }
复制代码
参考文献

  https://juicefs.com/docs/zh/community/installation
  https://blog.csdn.net/easonwx/article/details/128635853?spm=1001.2014.3001.5501

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表