Linux上的新一代文件系统-Btrfs使用

Linux上的新一代文件系统-Btrfs使用

准备工作

Btrfs 支持已经包含在linuxlinux-lts的内核中。

要使用一些用户空间工具的话,需要安装 不在 base 包组中的而且基础操作必须的 btrfs-progs 软件包。

如果你需要从 Btrfs 文件系统引导(比如说你的内核和内存盘在一个 Btrfs 的分区上),请检查你的 启动引导器 是否支持 Btrfs。

创建文件系统

下文展示了如何创建一个新的 Btrfs 文件系统。要将一个 ext3/4 分区转换为 Btrfs,请参考 #从 Ext3/4 转换。要使用无分区的配置,请参考 #无分区 Btrfs 磁盘

查阅 mkfs.btrfs(8) 以获取更多信息。

单一设备上的文件系统

在分区 /dev/partition 上创建一个 Btrfs 文件系统:

# mkfs.btrfs -L mylabel /dev/partition

Btrfs 的默认块大小为 16KB。 要使用更大的 blocksize 数据/元数据的话,可以通过指定 -n 来修改 nodesize,正如本例所示的设置为 16KB:

# mkfs.btrfs -L mylabel -n 16k /dev/partition

多设备文件系统

Warning: Btrfs 的 RAID 5 和 RAID 6 模式存在致命缺陷, 不应当用于任何场景,除非用来做丢失数据的测试。 查阅 the Btrfs page on RAID5 and RAID6 以获取最新动态。

多个设备可以用来创建一组 RAID。支持的RAID级别有 RAID 0,RAID 1,RAID 10,RAID 5 和 RAID 6。数据和元数据的 RAID 等级可以独立地用 -d-m 参数指定。默认情况下元数据使用镜像 (RAID1),而数据则会被条带化 (RAID0)。参阅 Btrfs Wiki:在多个设备上使用 btrfs 或查阅 mkfs.btrfs 的手册页获得更多信息.

# mkfs.btrfs -d raid0 -m raid1 /dev/part1 /dev/part2 ...

要将多个 Btrfs 设备作为一个池使用的话,你需要将 udev 钩子或者 btrfs 钩子加入到 /etc/mkinitcpio.conf 中。查阅 Mkinitcpio (简体中文)#常用钩子以获取更多信息。

Note:
  • 磁盘阵列中的各个磁盘大小不一样可能会导致不能使用所有磁盘的完整空间。为了充分利用所有磁盘的容量,使用 -d single 而不是 -d raid0 -m raid1 (元数据镜像,数据非镜像且非条带化)
  • 挂载一个这样的文件系统可能会导致除了对应的 .device 的所有任务卡死且 Systemd 可能因为无法正确处理多设备 btrfs 文件系统上的每一个设备而不能正常启动,详见这个 BUG 报告
  • 有些启动加载器不支持多设备文件系统,比如 Syslinux

RAID 中有关于维护多设备上的 btrfs 文件系统的一些建议.

配置文件系统

写时复制 (CoW)

默认情况下 btrfs 对所有文件使用 写时复制 (CoW)。参阅the Btrfs Sysadmin Guide section 以获取实现细节以及它的优点和缺点。

停用 CoW

要对某个子卷上的新文件停用写时复制,使用 nodatacow 挂载选项。这只会影响新创建的文件,写时复制仍然会在已存在的文件上生效。nodatacow 参数同样会禁用压缩。参阅 btrfs(5) 以了解细节。

Note: 来自 Btrfs Wiki Mount options: within a single file system, it is not possible to mount some subvolumes with nodatacow and others with datacow. The mount option of the first mounted subvolume applies to any other subvolumes.
Note: 根据 Btrfs Wiki Mount options: 在单个文件系统中,无法使用 nodatacow 参数挂载某些子卷,而其他的使用 datacow 参数。第一个被挂载子卷的挂载参数将会应用于其他所有子卷。

要单文件或目录禁用写时复制特性,请使用下面的命令:

$ chattr +C [文件/目录的地址(path)]

这会为这个文件的单个引用停用写时复制,如果这个文件不只有一个引用(例如通过 cp --reflink=always 生成或者在文件系统快照中),写时复制依然生效.

Note: 来自 chattr 的手册页:在btrfs上,'C' 标志应该被设置在新建的或者是空白的文件/目录,如果被设置在已有数据的文件,当块分配给该文件时,文件将不确定是否完全稳定。如果'C' 标志被设置给一个目录,将不会影响目前的目录,但在该目录创建的新文件将具有No_COW属性。
Tip: 可以用下面的方法为已存在的文件或目录停用写时复制:
$ mv /path/to/dir /path/to/dir_old
$ mkdir /path/to/dir
$ chattr +C /path/to/dir
$ cp -a /path/to/dir_old/* /path/to/dir
$ rm -rf /path/to/dir_old

需要保证这个过程中目标文件不会被使用,同时注意下面描述的 mvcp --reflink 并不起作用.

创建轻量副本

默认情况下,使用 cp 复制 Btrfs 文件系统上的文件时,会创建实际副本。要创建引用原始数据的轻量级副本,请使用 reflink 选项:

$ cp --reflink source dest

参阅 cp 的手册页获得关于 --reflink 标志的更多信息。

压缩

Btrfs支持透明压缩,这意味着分区里的每个文件都被自动压缩。这不单减小了文件的大小,在某些特定的场景下(比如单线程、重文件 I/O)还提高了性能,尽管在其他的场景下(比如多线程和/或具有大文件 I/O 的 CPU 密集型任务)显著得影响了性能。使用更快的压缩算法比如 zstdlzo 通常可以获得更好的性能,这个性能测试 提供了详细的对比。

压缩可以通过使用挂载参数 compress 来启用,它的可选值包括 zliblzozstd 或者是 no (不启用压缩)。只有在加入挂载选项后创建或修改的文件才会被压缩。

不过也可以在安装以后通过 btrfs filesystem defragment -calg (也可以使用其它压缩算法,例如 zlib / lzo) 压缩一个分区 (例如从 ext3/4 转换以后的文件系统).

要将整个文件系统通过 zstd 重新压缩,运行下面的命令:

# btrfs filesystem defragment -r -v -czstd /

在一个新的 btrfs 分区上安装 Arch Linux 时,要充分利用压缩特性,最好安装时就启用压缩功能。在File systems 时使用 compress 参数: mount -o compress=lzo /dev/sdxY /mnt/.在 时把 compress=lzo 添加到 fstab 中的根目录中的选项上。

Tip: 通过 chattr +c ,也可以在不使用 compress 选项的情况下为单个文件启用压缩属性.对目录启用会使这个目录下新文件自动压缩.
Warning:
  • 如果你使用 zstd 这个参数的话,使用没有 zstd 支持的旧版本内核或者 btrfs-progs 可能不能读取或者修复你的文件系统。
  • GRUBrEFInd 目前缺少对 zstd 的支持,请使用没有启用 zstd 选项的独立 boot 分区或者使用其他已被支持的算法重新压缩引导文件,比如:
    $ btrfs filesystem defragment -v -clzo /boot/*

子卷

"btrfs 子卷不是 (也不能看作) 块设备,一个子卷可以看作 POSIX 文件名字空间.这个名字空间可以通过子卷上层访问,也可以独立挂载."[1]

每个 btrfs 文件系统都有一个 ID 为 5 的顶层子卷。它可以挂载为 /(默认情况下),或者可以挂载为另一个子卷。子卷可以在文件系统中移动,它们通过其 ID 而不是路径来标识。

参阅下面的链接获得更多信息:

创建子卷

要创建一个子卷:

# btrfs subvolume create /path/to/subvolume
列出子卷列表

要列出当前路径 (path) 下的子卷:

# btrfs subvolume list -p path
删除子卷

要删除一个子卷:

# btrfs subvolume delete /path/to/subvolume

只是移除子卷的目录 /path/to/subvolume 而不使用这个命令并不会删除一个子卷.

挂载子卷

可以使用 subvol=/path/to/subvolumesubvolid=objectid' 挂载标志来安装子卷,就像文件系统分区一样。例如,您可以拥有一个名为 subvol_root 的子卷,并将其挂载为 /。通过在文件系统的顶层创建各种子卷,然后将它们安装在适当的挂载点,可以模仿传统的文件系统分区。 因此,可以使用#Snapshots[broken link: invalid section]轻松地将文件系统(或其一部分)恢复到先前的状态。

Tip: 为了方便地修改子卷的结构,请考虑创建新的子卷,然后挂载为 / 而不是使用顶层子卷 (ID=5) 挂载为根目录(这是默认行为)。

 

Note: “大多数挂载选项适用于 整个文件系统,并且只有要挂载的第一个子卷的选项才会生效。 这是因为没有实现,未来可能会发生变化。” [2] 查阅 Btrfs Wiki FAQ 以了解哪些挂载参数能够被用于独立的子卷

参阅 Snapper#Suggested filesystem layout, Btrfs SysadminGuide#Managing SnapshotsBtrfs SysadminGuide#Layout 获得子卷应用的示例.

有关特定于btrfs的挂载选项的完整列表,请参阅 btrfs(5)

改变默认子卷

如果挂载时不指定 subvol= 选项便会挂载默认子卷.要改变默认子卷:

# btrfs subvolume set-default subvolume-id /

subvolume-id 可以通过#列出子卷列表获得.

Note: 在安装了 GRUB 的系统上,在改变默认子卷以后不要忘记运行 grub-install . 参见 this forum thread.

通过 btrfs subvolume set-default 修改默认子卷将会导致文件系统的最顶层无法访问,除非使用 subvol=/ 或者 subvolid=5 挂载参数。[3]

配额

Warning: Qgroup 尚且不稳定且在有(过多)快照的子卷上应用配额可能会导致性能问题,比如在删除快照的时候。 此外,这里还有更多 已知问题.

Btrfs中的配额支持是通过使用配额组或 qgroup 在子卷级别实现的:默认情况下,每个子卷都以 0/<subvolume id> 的形式分配配额组。 但是,如果需要的话,可以使用任意数字创建配额组。

要使用 qgroup,你需要首先启用它:

# btrfs quota enable <path>

从此时开始,新创建的子卷将由这些配额组控制。 为了能够为已创建的子卷启用配额,首先正常启用配额,然后使用它们的 <subvolume id> 为每个子卷创建一个配额组,再重新扫描它们:

# btrfs subvolume list <path> | cut -d' ' -f2 | xargs -I{} -n1 btrfs qgroup create 0/{} <path>
# btrfs quota rescan <path>

Btrfs 中的配额组形成树层次结构,其中 qgroup 附加到子卷。大小限制由每个 qgroup 独立配置且在并在包含给定子卷的树中达到任何限制时应用。

配额组的限制可以应用于总数据使用,非共享数据使用,压缩数据使用或全部。文件复制和文件删除可能都会影响限制,因为如果删除原始卷的文件并且只剩下一个副本,则另一个 qgroup 的非共享限制可能会更改。例如,新快照几乎与原始子卷共享所有块,对子卷的新写入将向专用限制提升,一个卷中的公共数据的删除将升高到另一个卷中的专用限制。

要对 qgroup 应用限制,请使用命令 btrfs qgroup limit。根据你的使用情况,使用总限制,非共享限制( -e)或压缩限制( -c)。

显示文件系统使用中给定路径的使用情况和限制:

# btrfs qgroup show -reF <path>

提交间隔

将数据写入文件系统的频率由 Btrfs 本身和系统的设置决定。Btrfs 默认设置为 30 秒检查点间隔,新数据将在 30 秒内被提交到文件系统。 这可以通过在 /etc/fstab 增加 commit 挂载参数来修改:

LABEL=arch64 / btrfs defaults,noatime,compress=lzo,commit=120 0 0

系统范围的设置也会影响提交间隔。它们包括 /proc/sys/vm/* 下的文件,这超出了本维基文章的范围,因此不再赘述。 它们的内核文档位于 Documentation/sysctl/vm.txt

SSD TRIM

Btrfs 文件系统能够从支持 TRIM 命令的 SSD 驱动器中释放未使用的块。

有关启用和使用 TRIM 的更多信息,请参阅 Solid State Drives#TRIM

 

使用

显示已使用的/空闲空间

df 这样的用户空间工具可能不会准确的计算剩余空间 (因为并没有分别计算文件和元数据的使用情况) 。推荐使用 btrfs filesystem usage 来查看使用情况。比如说:

# btrfs filesystem usage /
Note: The btrfs filesystem usageRAID5/RAID6 设备上可能无法正常工作。

查看 [4] 以获取更多信息。

碎片整理

Btrfs 支持通过配置 挂载参数 autodefrag 来实现在线的碎片整理。要手动整理你的根目录的话,可以使用:

# btrfs filesystem defragment -r /

使用不带 -r 开关的上述命令将导致仅整理该目录的子卷所拥有的元数据。这允许通过简单地指定路径进行单个文件碎片整理。

对具有 CoW 副本(快照副本或使用cp --reflink或 bcp 创建的文件)进行碎片整理以及使用带压缩算法的 -c 开关进行碎片整理可能会导致生成两个不相关的文件从而增加磁盘使用量。

RAID

Btrfs 提供对 RAID 一类的 #多设备文件系统的原生支持.参阅 the Btrfs wiki page 获得更多信息. Btrfs 管理员手册 提供了技术背景信息.

Warning: 奇偶校验 RAID(RAID 5/6)代码中存在多个严重的数据丢失错误。 检查 Btrfs 的 Wiki RAID5/6 page 和 BUG 汇报 linux-btrfs mailing list 以获取更多信息。

Scrub

Btrfs Wiki 术语表中写到 scrub 是一种 "在线文件系统检查工具".它读取文件系统中的文件和元数据,并使用校验值和 RAID 存储上的镜像区分并修复损坏的数据.

Warning: 运行 scrub 会阻止系统待机, 详见 这个讨论.
手动启动

启动一个(后台运行的)包含 / 目录的文件系统在线检查任务:

# btrfs scrub start /

检查该任务的运行状态:

# btrfs scrub status /
通过服务或者定时器启动

btrfs-progs 软件包带有 btrfs-scrub@.timer 系统单元,用来每月运行 scrub 命令.通过添加挂载点的参数来启用它,例如btrfs-scrub@-.timer (/) 或者 btrfs-scrub@home.timer (/home).

也可以通过启动 btrfs-scrub@.service 来手动运行 scrub (使用同样的挂载点参数) ,相对于 # btrfs scrub 这么做的优点是会记录在 Systemd 日志中。

 

Balance

“Balance 将会通过分配器再次传递文件系统中的所有数据。它主要用于在添加或删除设备时跨设备重新平衡文件系统中的数据。如果设备出现故障,余额将为冗余 RAID 级别重新生成缺失的副本。”[5]。参阅 上游的 FAQ.

在单设备文件系统上,余额对于(临时)减少分配但未使用(元)数据块的数量也是有用的。有时候这对于解决 "filesystem full" 故障 来说也是必须的。

# btrfs balance start /
# btrfs balance status /

快照

"快照是和特定子卷共享文件和元数据的特殊子卷, 利用了 btrfs 的写时复制特性." 详见 Btrfs Wiki SysadminGuide#Snapshots.

要创建一个快照:

# btrfs subvolume snapshot source [dest/]name

source为要创建快照的对象,[dest/]name为快照安放路径。

加入 -r 参数可以创建一个只读快照. 为只读快照创建一个快照可以获得一个只读快照的可写入版本.

Note: 快照不是递归包含的,这意味着子卷内的子卷在快照里是空目录。

发送和接收

可以通过 send 命令发送一个快照,通常会与 btrfs 中的 receive 组成管道.例如将快照 /root_backup (也许是/的备份) 发送到 /backup:

# btrfs send /root_backup | btrfs receive /backup

只能发送只读快照,上面的命令在将子卷复制到外部设备 (例如备份驱动器) 时会很有用.

也可以只发送两个快照间发生变化的部分,例如如果你已经发送了快照 root_backup ,然后又建立了一个新的只读快照 root_backup_new ,可以这样完成增量发送:

# btrfs send -p /root_backup /root_backup_new | btrfs receive /backup

现在你 /backup 的快照会是 root_backup_new.

参阅 Btrfs Wiki's Incremental Backup page 获得更多信息 (例如使用工具自动化这一过程)。

去重

使用写时复制,Btrfs能够复制文件或整个子卷而无需实际复制数据。但是,无论何时更改文件,都会创建一个新的 “真正的” 副本。重复数据删除更进一步,通过主动识别共享公共序列的数据块并将它们组合到具有相同写时复制语义的范围内。

专用于 Btrfs 分区去重的工具包括 duperemoveAUR,bedupAUR 和 btrfs-dedup。人们可能还希望仅使用基于文件的级别对数据进行重复数据删除,比如 rmlint 或者 jdupesAUR。有关这些程序的可用功能的概述和其他信息,请查看上游 Wiki 条目

此外,Btrfs开发人员正致力于带内(也称为同步或内联)重复数据删除,这意味着在将新数据写入文件系统时完成重复数据删除。目前,它仍然是一个在 out-of-tree 开发的实验。愿意测试新功能的用户可以阅读相关的内核 Wiki 页

已知问题

一些在尝试之前应该知道的限制。

加密

Btrfs 目前还没有内建的加密支持,但未来可能加入此功能。可以在运行mkfs.btrfs前加密分区,参阅Dm-crypt with LUKS.

(如果已经创建了文件系统,可以使用EncFSTrueCrypt,但是这样会无法使用 btrfs 的一些功能。)

交换文件

Btrfs 不支持交换文件,因为 Btrfs 有潜在的文件系统损坏风险,没有加入交换文件需要的功能,参阅这里。交换文件可以挂载到 loop 设备中,但是性能比较差。systemd-loop-swapfileAUR[broken link: archived in aur-mirror]提供了需要的服务文件。

TLP

使用 TLP 需要特殊的预防措施,以避免文件系统损坏。有关更多信息,请参阅TLP#Btrfs

提示和技巧

无分区 Btrfs 磁盘

Warning: 大多数用户不希望这种类型的设置,应该在常规分区上安装 Btrfs。 此外,GRUB 强烈建议不要安装到无分区磁盘。

Btrfs 能在整个设备上使用,替代 MBRGPT 分区表,但是并不要求一定这么做,最简单的方法是 在一个已存在的分区上创建 btrfs 文件系统[broken link: invalid section]. 如果你选择用 btrfs 替代分区表, 可以用 子卷[broken link: invalid section]模拟不同的分区。下列是在单个无分区设备上使用 Btrfs 文件系统的限制:

运行下面的命令把整个设备的分区表替换成 btrfs:

# mkfs.btrfs /dev/sdX

如果设备上存在分区表,则需要使用:

# mkfs.btrfs -f /dev/sdX

例如 /dev/sda 而不是 /dev/sda1. 后一种形式会格式化现有的分区而不是替换掉原有的分区表.

像使用普通的 MBR 分区表存储设备一样安装 启动管理器, 参考 Syslinux#Manual installGRUB/Tips and tricks#Install to partition or partitionless disk

从 Ext3/4 转换

Warning: 到2015年中后期, btrfs 邮件列表中报告了多起失败的转换.尽管近期的更新有所修复,但还是建议小心使用.在开始之前确定你有 可用的备份并且愿意承担丢失数据的风险. 详见 Btrfs Wiki:从 Ext3 文件系统转换 .

从安装 CD 启动,然后转化分区:

# btrfs-convert /dev/partition

挂载转换后的分区并修改/etc/fstab文件,指定分区类型(type 为 btrfs,fs_passno [最后一列] 修改为0,Btrfs在启动时并不进行磁盘检查). 还要注意的是分区的UUID将有改变,所以使用UUID时,更新fstab中相应的条目。 chroot 到系统并重建 GRUB 条目(如果对此过程不熟悉,参考Install from existing LinuxGRUB). 如果正在转换根目录,还需要在 chroot 环境中重建初始化内存盘 (mkinitcpio -p linux). 如果 GRUB 不能启动 (例如 'unknown filesystem' 错误),则需要重新安装 (grub-install /dev/partition) 并生成配置文件 (grub-mkconfig -o /boot/grub/grub.cfg).

确认没有问题后,完成转换通过删除备份ext2_saved子卷,请注意,如果没了它(备份子卷),你将没办法还原回 ext3/4 文件系统。

# btrfs subvolume delete /ext2_saved

最后通过 balance 回收空间.

请记住,之前安装的某些应用程序必须适配 Btrfs。值得注意的是 TLP#Btrfs 需要特别小心以避免文件系统损坏,但其他应用程序也可能从某些功能中获益。

Checksum 硬件加速

要验证Btrfs校验和是否是硬件加速:

$ dmesg | grep crc32c
Btrfs loaded, crc32c=crc32c-intel

如果你看到 crc32c=crc32c-generic,这很有可能是因为你的根分区是 Btrfs,你将会需要编译 crc32c-intel 进入内核并启用它。将 crc32c-intel 放入 mkinitcpio.conf不会 生效的。

损坏恢复

btrfs-check 不能在一个已挂载的文件系统上工作。为了能够在不从 Live USB 启动的情况下使用 btrfs-check,需要将其添加到初始内存盘:

/etc/mkinitcpio.conf
BINARIES=("/usr/bin/btrfs")

Regenerate the initramfs

之后如果启动时出现问题,则可以使用该实用程序进行修复。

Note: 如果 fsck 进程必须使空间缓存(和/或其他缓存?)无效,那么后续引导挂起一段时间是正常的(它可能会给出关于 btrfs-transaction 挂起的控制台消息)。系统应该在一段时间后从中恢复。

查阅 Btrfs Wiki 页 以获取更多信息。

引导进入快照

为了能够引导进入快照,你必须通过 内核参数 rootflags=subvol=/path/to/subvolume 来指定子卷,同时需要修改 /etc/fstab 使用 subvol= 来指定相同的子卷。或者,子卷可以用其 id 来指定 - 例如可以用例如可检索的。 btrfs subvolume list /root/path - 和rootflags=subvolid=objectid 分别作为内核参数subvolid= objectid 作为 /etc/fstab 中的挂载选项。

如果使用 GRUB,则可以在 grub-btrfsgrub-btrfs-gitAUR 的帮助下重新生成配置文件时使用 Btrfs 快照自动填充启动菜单。

Use Btrfs subvolumes with systemd-nspawn

查阅 Systemd-nspawn#Use Btrfs subvolume as container rootSystemd-nspawn#Use temporary Btrfs snapshot of container 等文章。

故障排除

参阅 Btrfs Problem FAQ 获得排除一般问题的信息.

GRUB

分区偏移
Note: 在试图将 core.img 嵌入到已经分区的磁盘上时可能会发生偏移问题. 这意味着可以把 corg.img 嵌入到 btrfs 池或是无分区磁盘 (例如 /dev/sdX) 上.

Grub 2可以启动 Btrfs 分区,但是因为模块比较大, grub-install 安装的 core.img 文件超过了 MBR 与第一个分区之间的空间大小 (63 扇区/31.5KiB) .更新后的 fdiskgdisk 的磁盘工具会通过第一个分区前空出 1-2M 的空间避免此问题.

Missing root

如果启动 RAID 卷设备后编辑了 /usr/share/grub/grub-mkconfig_lib 移除了 echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}" 中的引号,可能会遇到 error no such device: root 问题,重新生成 GRUB 设置文件应该能避免这个问题.

BTRFS: open_ctree failed

2014 年 11 月的 systemdmkinitcpio 中的 bug 可能导致使用 mkinitcpio.confbtrfs hook 的用户启动多设备文件系统的 btrfs 卷时出现错误\:

BTRFS: open_ctree failed
mount: wrong fs type, bad option, bad superblock on /dev/sdb2, missing codepage or helper program, or other error

In some cases useful info is found in syslog - try dmesg|tail or so.

You are now being dropped into an emergency shell.

一个临时解决方案是从 HOOKS 中移除 btrfs 并把它放入 MODULES 中,通过 mkinitcpio -p linux 重新生成 initramfs 并重新启动.

参阅 原来的论坛讨论FS#42884 获得更多的信息和讨论.

另外如果在挂载 RAID 卷组时缺少某个卷时也有可能会发生这个错误.这种情况下你需要把 degraded 加入到 /etc/fstab 中,如果根目录在卷组上,同时需要加入 rootflags=degraded 内核参数

检查 btrfs 文件系统

Warning: btrfs (特别是 btrfs check 命令)仍在开发阶段, 强烈建议在加上 --repair 参数运行 btrfs check 时做一个 备份.

btrfs check 可以检查并修复一个未挂载的 btrfs 文件系统.但是由于它并未开发完成,它并不能修复某些错误 (即使这些错误没导致无法挂载).

参阅 Btrfsck 获得更多信息.

另见

更多参考

转载于:https://my.oschina.net/u/2306127/blog/3009041

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值