Day40-Rsync企业级备份工具讲解

1. rsync客户端命令参数

常用组合:-avz或者-vzrtopg(rtopg=a)

rsync命令参数:
-v, --verbose  显示输出过程
-z, --compress 压缩
-a, --archive  多参数集合(-rtopgDl)
	-r, --recursive 递归
	-t, --times    保持修改时间属性
	-o, --owner    保持属主不变
	-p, --perms    保持权限不变
	-g, --group    保持用户组不变
	-l, --links    保持拷贝软连接
-q, --quiet    安静的拷贝
--bwlimit=KBPS 限制I/O带宽,KBytes per second。
--delete       删除
--exclude      排除
--exclude-from 从文件中排除
命令参数参数说明
-v,–verbose详细模式输出,传输时的进度等信息
-z,–compress传输时进行压缩以提高传输效率,–compress-level=NUM 可按级别压缩。局域网可以不用压缩
-a,–archive归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rtopgDl
-r,–recursive 归类于-a 参数对子目录以递归模式,即目录下的所有目录都同样传输,注意是小写r
-t,–times 归类于-a 参数保持文件时间信息
-o,–owner 归类于-a 参数保持文件属主信息
-p,–perms 归类于-a 参数保持文件权限
-g,–group 归类于-a 参数保持文件属组信息
-P,–progress显示同步的过程及传输时的进度等信息
-D,–devices 归类于-a 参数保持设备文件信息
-l,–links 归类于-a 参数保留软链接(小写字母l)
e,–rsh=COMMAND.使用的信道协议,指定替代rsh的 shel 程序。例如:ssh
–exclude=PATTERN指定排除不需要传输的文件信息(和 tar 参数一样)
–exclude-from=file文件名所在的目录文件,即可以实现排除多个文件(和 tar 参数一样)
–bwlimit=RATE限速功能单位是 KB/S 案例:某 DBA 做数据同步,带宽占满,导致用户无法访问网站
–delete让目标目录 SRC 和源目录数据 DST一致,即无差异同步数据

2. rsync客户端连接时候报错及解决。

错误1:

[root@nfs01 ~]# rsync -avz  /data/  rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
@ERROR: invalid uid rsync
rsync error: error starting client-server protocol (code 5) at main.c(1649) [sender=3.1.2]

#解答:没有rsync用户
[root@backup ~]# useradd rsync
[root@backup ~]# id rsync
uid=1001(rsync) gid=1001(rsync)=1001(rsync)
[root@backup ~]# mkdir -p /backup
[root@backup ~]# chown -R rsync.rsync /backup/
[root@backup ~]# ls -ld /backup/
drwxr-xr-x 2 rsync rsync 6 415 12:12 /backup/

错误2:

[root@nfs01 ~]# rsync -avz /etc/hosts rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
sending incremental file list
hosts
rsync: chgrp ".hosts.YDuTjO" (in backup) failed: 【Operation not permitted】 (1)

sent 223 bytes  received 124 bytes  694.00 bytes/sec
total size is 332  speedup is 0.96
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1178) [sender=3.1.2]

# 解答:增加如下参数到/etc/rsyncd.conf
fake  super  = yes #不用root用户也可以存储文件的完整属性。
This allows the full attributes of a file to  be  stored  without having to have the daemon actually running as root.
[root@backup ~]# grep fake /etc/rsyncd.conf
fake super = yes
# 改完配置,要重启服务:
[root@backup ~]# systemctl restart rsyncd

[root@nfs01 ~]# rsync -avz  /etc/  rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
@ERROR: auth failed on module backup
rsync error: error starting client-server protocol (code 5) at main.c(1649) [sender=3.1.2]
# 解答:用户认证有问题,用户密码错误,密码文件错误。

3. 企业工作遇到错误解决思路:

  1. 尽快恢复业务。
  2. 线下模拟重现错误。
  3. 找到原因和解决办法。
  4. 修复线上环境。

4. 多模块复制

  1. 多模块复制,修改配置如下
[root@backup ~]# tail -2 /etc/rsyncd.conf
[oldboy]
path = /data/
  1. 重启
systemctl restart rsyncd
  1. 创建/data目录,并授权
mkdir /data -p
chown -R rsync.rsync /data
ls -ld /data
  1. 测试
[root@nfs01 ~]# rsync -avz  /etc  rsync_backup@172.16.1.41::oldboy --password-file=/etc/rsync.password

5. 排除指定目录和文件数据复制(没有企业场景)

普通排除(–exclude)
排除2.txt

[root@nfs01 ~]# rsync -avz --exclude=2.txt rsync_backup@172.16.1.41::backup /tmp/ --password-file=/etc/rsync.password
receiving incremental file list
./
.pwd.lock
.updated
1.txt
3.txt
4.txt
5.txt

排除多个文件。

[root@nfs01 ~]# rsync -avz --exclude={1,3}.txt rsync_backup@172.16.1.41::backup /tmp/ --password-file=/etc/rsync.password
receiving incremental file list
./
2.txt
4.txt
5.txt

排除的多个文件有序列的方式

[root@nfs01 ~]# rsync -avz --exclude={1..3}.txt rsync_backup@172.16.1.41::backup /tmp/ --password-file=/etc/rsync.password
receiving incremental file list
./
4.txt
5.txt

从文件中排除(–exclude-from=/opt/oldboy.txt)

[root@nfs01 ~]# echo {1..3}.txt|xargs -n 1 >/opt/oldboy.txt #列出文件名
[root@nfs01 ~]# cat /opt/oldboy.txt
1.txt
2.txt
3.txt

[root@nfs01 ~]# rsync -avz --exclude-from=/opt/oldboy.txt rsync_backup@172.16.1.41::backup /tmp/ --password-file=/etc/rsync.password
receiving incremental file list
./
4.txt
5.txt

6. 主机之间数据无差异复制(企业会应用)

企业案例:爱奇艺视频网站
本地目录(新增数据)====>服务器上同步(老的数据)
–delete
服务器上老的数据全部被删除,同时把本地新增数据更新。

本地无差异复制

[root@nfs01 ~]# mkdir /null
[root@nfs01 ~]# mkdir /data -p
[root@nfs01 ~]# touch /data/{a..g}.txt
[root@nfs01 ~]# ls /data
a.txt  b.txt  c.txt  d.txt  etc  e.txt  f.txt  g.txt
rsync -avz --delete /null/ /data/  #让/data目录和/null目录数据一致(/data目录数据丢失风险)

守护进程模式
客户端推:服务端/backup目录数据丢失风险

rsync -avz --delete /null/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
#让服务端/backup目录和客户端/null目录数据一致(服务端/backup目录数据丢失风险)

客户端拉:客户端/data目录数据丢失风险

rsync -avz --delete rsync_backup@172.16.1.41::backup /data/ --password-file=/etc/rsync.password
#让客户端/data目录和服务端/backup目录和数据一致(客户端/data目录数据丢失风险)

思考明白:–delete慎用。

7. Rsync断点续传和限速

--partial	
默认情况下,rsync将删除所有部分传输的文件,如果传输被中断。在某些情况下,保留部分已经传输的文件是所希望的。使用--partial参数告知rsync保留部分传输过的文件,可以使该文件剩余部分的传输更快速

--partial-dir=DIR	
保留部分传输文件时,比--partial参数更好的方法是指定一个目录来保存部分数据(而不是将其写入目标文件)。在下一个传输过程中,rsync将使用这个dir中的文件作为数据,以加快恢复传输的速度,并在它达到目的后将其删除

--bwlimit=KBPS	
这个参数允许指定数据最大传输速率为每秒多少K,当使用rsync传输大文件时,参数效果最有效(例如在兆字节以上时)。根据rsync传输的性质,采用数据块发送,如果rsync确定传输速度太快,可以在发送下一个数据块之前进行等待。使平均的传输速率等价于指定的限制速率。如果设定为0将不会做速率限制。

7.1 限速企业案例

上市公司运维总监的下属:
某上市公司,白天高峰期某DBA人员从数据库服务器通过rsync将上百GB数据复制到备份服务器,导致数据库库服务器带宽占满,造成用户无法访问网站的悲剧。其实可以利用rsync限速功能,将复制速度限制在剩余带宽的1/3或者1/2,可能就不会出现故障了,当然了,高峰期最好不做大数据复制行为,这里利用限速功能模拟测试:

限速实践:

rsync -avz --bwlimit=100 /data/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password

7.2 --delete企业工作场景:

rsync推送:数据备份,上传。
本地有啥,远端就有啥,本地没有的远端有也要删除,会造成服务器端的目录数据丢失,再备份和上传场景一般不需要–delete功能,除非是像NFS实时复制数据到备份服务器上必须要保持两边一致的情形。

rsync拉取企业工作场景:代码发布,下载(官方yum源)。
远端有啥,本地(客户端)就有啥,远端没有的本地有也要删除。会造成本地目录数据丢失。
无差异复制两台服务器之间,必须要求数据一致,且时时性又不是很高的情况,如两台负载均衡下面Web服务器之间的同步,或者高可用双机配置之间的同步、NFS共享数据的实时复制等。rsync无差异同步非常的危险,而且,有很多的替代方案,因此,生产场景没有特殊的需求,应避免使用。写了这么多内容的目的是警告读者,这个参数很危险,请慎用,切记。有很多朋友有过血的教训了,就在老男孩在写作本文时,其中一台演示机就差一点被从根开始误删了,幸亏老男孩有操作前,备份的习惯。

7.3 Rsync 企业级应用经验

7.3.1 Rsync 排错思路

  • 排错必备思想:要对部署流程步骤掌握熟练,熟悉 rsync 数据同步原理,并且要学会多看日志,rsync 命令行输出日志文件为/var/log/rsyncd.log。
  • 排错能力练习:模拟错误(两个人一个人搞错了,一个人排错),重视日常错误总结。

7.3.2 Rsync 服务端排错思路

  1. 查看rsync服务配置文件路径是否正确,正确的默认路径为:/etc/rsyncd.conf
  2. 查看配置文件里host allow,host deny,允许的ip网段是否是允许客户端访问的 ip 网段。
  3. 查看配置文件中path参数里的路径是否存在,权限是否正确(正常应为配置文件中的UID参数对应的属主和组)。
  4. 查看rsync服务是否启动。查看命令为:ps -ef l grep rsync。端口是否存在 netstat -Int | grep 873
  5. 查看iptables防火墙和selinux是否开启允许rsync服务通过,也可考虑关闭。
  6. 查看服务端rsync配置的密码文件是否为600的权限,密码文件格式是否正确,正确格式用户名:密码,文件路径和配置文件里的secrect files参数对应。
  7. 如果是推送数据,要查看下,配置rsyncd.conf文件中用户是否对模块下目录有可读写的权限。

7.3.3 Rsync 客户端排错思路

  1. 查看客户端rsync配置的密码文件是否为600的权限,密码文件格式是否正确,注意:仅需要有密码,并且和服务端的密码一致。
  2. 用telnet连接rsync服务器ip地址 873 端口(telnet 172.16.1.41 873),查看服务是否启动(可测试服务端防火墙是否阻挡)。
  3. 客户端执行命令时,语法格式书写不正确,此命令的细节要记清楚,尤其语法格式中的双冒号及随其后的oldboy为模块名称。

8. 利用软件自身参数实现安全复制(局域网内复制)

rsync服务的安全配置信息说明:

hosts allow = 172.16.1.0/24  #白名单,白名单更安全。
hosts deny = 0.0.0.0/32      #黑名单

拒绝和允许安全配置参数二选一进行配置,若同时设置可能会造成安全策略设置冲突导致失效的情况

当rsync服务配置文件中,允许和阻止安全策略同时配置时,某些情况会产生策略冲突问题,影响安全策略生效的预期结果。为避免这种情况的出现,建议在生产环境中,仅采用一种安全策略机制进行配置,不要hosts allow(白名单)和hosts deny(黑名单)两个参数同时配置。
1)只有白名单(hosts allow)进行配置的时候,黑名单(hosts deny)需要进行注释,默认不匹配白名单的访问都将被阻止。
2)只有黑名单(hosts deny)进行配置的时候,白名单(hosts allow)需要进行注释,默认不匹配黑名单的访问都将被允许
特别注意:二选一进行配置

配置防火墙实现安全控制
配置iptables防火墙允许rsync服务,根据rsync服务运行的端口信息,即rsync服务运行在在 873/tcp端口上:

[root@backup ~]# netstat -lnt|grep 873
tcp        0      0 0.0.0.0:873                 0.0.0.0:*                   LISTEN      
tcp        0      0 :::873                      :::*                        LISTEN  

在生产环境下防火墙规则默认禁止所有的前提下可以配置如下三行,允许rsync在可信任的环境内通信, 加入到/etc/sysconifg/iptables中,然后重起iptables使生效,systemctl restart iptables。

-A INPUT -s 124.42.63.99/27 -p tcp -m tcp --dport 873 -j ACCEPT  
#←允许固定的办公网发布程序传输同步。

-A INPUT -s 192.168.1.0/255.255.255.0 -p tcp -m tcp --dport 873 -j ACCEPT 	
#←允许IDC内网网段间连接传输同步。

-A INPUT -s 203.81.19.0/255.255.255.0 -p tcp -m tcp --dport 873 -j ACCEPT 	
#←允许IDC内网网段间连接传输同步。

9. Rsync企业常用工作场景

9.1 Rsync复制工具优缺点

Rsync优点

  • 增量备份,支持socket(daemon)守护进程模式,集中备份(支持推拉模式备份)。
  • 远程SHELL通道模式还可以加密(SSH)传输;
  • socket(daemon)需要加密传输,可以利用vpn服务或ipsec服务。

Rsync缺点

  • 海量小文件复制的时候,rsync进程可能会停止僵死或效率不高。
  • 一次性远程拷贝可以用scp,如果大量小文件可打成压缩包再拷贝。
--backup-dir 将备份文件(如~filename)存放在在目录下。
-suffix=SUFFIX 定义备份文件前缀。
-u, --update 仅仅进行更新,也就是跳过所有已经存在于DST,并且文件时间晚于要备份的文件,不覆盖更新的文件。
-l, --links 保留软链结。
-L, --copy-links 想对待常规文件一样处理软链结。
--copy-unsafe-links 仅仅拷贝指向SRC路径目录树以外的链结。
--safe-links 忽略指向SRC路径目录树以外的链结。
-H, --hard-links 保留硬链结。
-p, --perms 保持文件权限。
-o, --owner 保持文件属主信息。
-g, --group 保持文件属组信息。
-D, --devices 保持设备文件信息。
-t, --times 保持文件时间信息。
-S, --sparse 对稀疏文件进行特殊处理以节省DST的空间。
-n, --dry-run现实哪些文件将被传输。
-w, --whole-file 拷贝文件,不进行增量检测。
-x, --one-file-system 不要跨越文件系统边界。
-B, --block-size=SIZE 检验算法使用的块尺寸,默认是700字节。
-e, --rsh=command 指定使用rsh、ssh方式进行数据同步。
--rsync-path=PATH 指定远程服务器上的rsync命令所在路径信息。
-C, --cvs-exclude 使用和CVS一样的方法自动忽略文件,用来排除那些不希望传输的文件。
--existing 仅仅更新那些已经存在于DST的文件,而不备份那些新创建的文件。
--delete 删除那些DST中SRC没有的文件。
--delete-excluded 同样删除接收端那些被该选项指定排除的文件。
--delete-after 传输结束以后再删除。
--ignore-errors 及时出现IO错误也进行删除。
--max-delete=NUM 最多删除NUM个文件。
--partial 保留那些因故没有完全传输的文件,以是加快随后的再次传输。
--force 强制删除目录,即使不为空。
--numeric-ids 不将数字的用户和组id匹配为用户名和组名。
--timeout=time ip超时时间,单位为秒。
-I, --ignore-times 不跳过那些有同样的时间和长度的文件。
--size-only 当决定是否要备份文件时,仅仅察看文件大小而不考虑文件时间。
--modify-window=NUM 决定文件是否时间相同时使用的时间戳窗口,默认为0。
-T --temp-dir=DIR 在DIR中创建临时文件。
--compare-dest=DIR 同样比较DIR中的文件来决定是否需要备份。
-P 等同于 --partial。
--progress 显示备份过程。
-z, --compress 对备份的文件在传输时进行压缩处理。
--exclude=PATTERN 指定排除不需要传输的文件模式。
--include=PATTERN 指定不排除而需要传输的文件模式。
--exclude-from=FILE 排除FILE中指定模式的文件。
--include-from=FILE 不排除FILE指定模式匹配的文件。
--version 打印版本信息。
--address 绑定到特定的地址。
--config=FILE 指定其他的配置文件,不使用默认的rsyncd.conf文件。
--port=PORT 指定其他的rsync服务端口。
--blocking-io 对远程shell使用阻塞IO。
-stats 给出某些文件的传输状态。
--progress 在传输时现实传输过程。
--log-format=formAT 指定日志文件格式。
--password-file=FILE 从FILE中得到密码。
--bwlimit=KBPS 限制I/O带宽,KBytes per second。

9.2 全网备份实战流程

  • rsync服务器搭建部署。
  • web和nfs01服务器搭建部署;
    • 验证rsync命令能否推送成功;
    • 开发脚本实现打包备份、推送、校验、删除。
    • 配置定时任务每天0点定时推送。(0时是时间的一个分割点)
  • rsync服务器
    • 开发脚本实现校验、删除、报警。
    • 配置实时任务每天6点实时执行。

1.第一个里程碑-在backup上部署rsync服务
在backup server上部署rsync服务(省略),
并且在web01和nfs01客户端服务器测试推送成功(省略)。

mkdir /backup -p
rsync -avz  /backup/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password

2.第二个里程碑-客户端本地开发打包脚本,并实现定时任务执行脚本
nginx webserver,NFS dataserver本地打包备份脚本实现。
web01服务器待备份信息:

a)/var/spool/cron/root /etc/rc.local /server/scripts。
b)/var/html/www、/app/logs。

解答:

mkdir -p /var/html/www /app/logs

1)备份脚本

[root@web01 scripts]# cat bak.sh 
Path="/backup/$(hostname -i)"
[ -f $Path ]||mkdir -p $Path
#备份
cd $Path &&\
tar zcf conf_$(date +%F).tar.gz /var/spool/cron/root /etc/rc.local /server/scripts 2>/dev/null
tar zcf www_$(date +%F).tar.gz /var/html/www 2>/dev/null
tar zcf logs_$(date +%F).tar.gz /app/logs 2>/dev/null
#推送
rsync -az  /backup/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
#删除7天前的数据
find /backup -type f -name "*.tar.gz" -mtime +7|xargs rm -f

2)定时任务

[root@web01 scripts]# crontab -l|tail -2 
#bak local data by oldboy for leader at 2030.6.29
00 00 * * * /bin/sh /server/scripts/bak.sh &>/dev/null

# nfs01服务器待备份信息:
[root@nfs01 scripts]# cat bak.sh 
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

Path1="/backup/$(hostname -i)"
[ -f $Path1 ]||mkdir -p $Path1
#备份
cd $Path1 &&\
tar zcfh conf_$(date +%F -d -1day).tar.gz /var/spool/cron/root /etc/rc.local /server/scripts 2>/dev/null
#推送
rsync -az  /backup/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
#删除7天前的数据
find /backup -type f -name "*.tar.gz" -mtime +7|xargs rm -f

[root@nfs01 scripts]# crontab -l|tail -2
########
00 00 * * * /bin/sh /server/scripts/bak.sh  &>/dev/null

3)服务器检查数据完整性,并且发送给管理员信箱

md5sum
[root@nfs01 scripts]# touch oldboy.txt
[root@nfs01 scripts]# md5sum oldboy.txt
d41d8cd98f00b204e9800998ecf8427e  oldboy.txt
[root@nfs01 scripts]# echo 11 > oldboy.txt
[root@nfs01 scripts]# md5sum oldboy.txt
166d77ac1b46a1ec38aa35ab7e628ab5  oldboy.txt

1.在文件打包之后,传输之前获取到指纹(原始数据)
2.在传到服务器上以后,重新对文件做获取指纹。
3.如何判断文件在传输过程中没有发生变化。
对比:【重新获取的指纹】 和 【传输之前获取到指纹】
如果一样,表示文件完整,如果不一样,表示文件有修改或损坏。

# 利用md5sum -c的功能实现比对前后的指纹
[root@nfs01 scripts]# md5sum oldboy.txt >zhiwen.log
[root@nfs01 scripts]# cat zhiwen.log
166d77ac1b46a1ec38aa35ab7e628ab5  oldboy.txt
[root@nfs01 scripts]# md5sum -c zhiwen.log 
oldboy.txt: 确定
[root@nfs01 scripts]# echo 111 >oldboy.txt 
[root@nfs01 scripts]# md5sum -c zhiwen.log 
oldboy.txt: 失败
md5sum: 警告:1 个校验和不匹配

web01下的bak.sh

Path="/backup/$(hostname -i)"
[ -f $Path ] || mkdir -p $Path
date=$(date +%F -d -1day)
#备份
cd $Path &&\
tar zcfh conf_${date}.tar.gz /var/spool/cron/root /etc/rc.d/rc.local /server/scripts 2>/dev/null
tar zcf www_${date}.tar.gz /var/html/www 2>/dev/null
tar zcf logs_${date}.tar.gz /app/logs 2>/dev/null
#获取原始指纹
find $Path -type f -name "*_${date}.tar.gz"|xargs md5sum >$Path/$(hostname -i)_zhiwen_${date}.log
#推送
rsync -az /backup/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password
#删除7天前的数据
find /backup -type f -name "*.tar.gz" -mtime +7|xargs rm -f

backup服务器上检查指纹脚本

find /backup/ -type f -name "*.log" | xargs md5sum -c >/backup/result_$(date +%F -d -1day).log
mail -s "$(date +%F -d -1day)backup result" </backup/result_$(date +%F -d -1day).log

backup本身备份
老男孩backup备份脚本_bak.sh

#!/bin/sh
# by oldboy at 20200927
# www.oldboyedu.com
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
IP=$(ifconfig eth1|awk -F "[ :]+" 'NR==2{print $3}')
BakPath=/backup
mkdir $BakPath/$IP -p
if [ $(date +%w) -eq 2 ];then
 date="$(date +%F -d "-1day")_week1"
else
 date="$(date +%F -d "-1day")"
fi

cd / &&\
tar zcfh $BakPath/$IP/sys_config_${date}.tar.gz var/spool/cron etc/rc.local server/scripts &&\
tar zcfh $BakPath/$IP/webdata_${date}.tar.gz var/html/www/ &&\
tar zcf $BakPath/$IP/access_log_${date}.tar.gz app/logs &&\

find $BakPath -type f -name "*.tar.gz"|xargs md5sum >$BakPath/$IP/flag_${date}

###bak data to backupserver by oldboy at 20160927
rsync -az $BakPath/ rsync_backup@172.16.1.41::backup --password-file=/etc/rsync.password

###del data 7 days ago.
find $BakPath -type f  -mtime +7|xargs rm -f

老男孩backup删除脚本_check_and_del

#!/bin/sh
# by oldboy at 20160927
# www.oldboyedu.com
IP=$(hostname -i)
Path=/backup

#保持每周1的副本
if [ $(date +%w) -eq 2 ];then
 date="$(date +%F -d "-1day")_week1"
else
 date="$(date +%F -d "-1day")"
fi
LANG=en
find /backup -type f -name "*${date}*.log"|xargs md5sum -c >>$Path/${date}_result.log 2>&1
mail -s "$date bak result" oldboytraining@163.com <$Path/${date}_result.log
find /backup/ -type f -mtime +7 ! -name "*week1*"|xargs rm -f
find /backup/ -type f -mtime +180|xargs rm -f
  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值