Redis高可用技术 二:主从复制、哨兵、Cluster集群

1. 主从复制

1.1 简介

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。

前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。

1.2 主从复制的作用

  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  • 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

1.3 主从复制的特性

  1. 一个master可以有多个slave;

  2. 一个slave只能有一个master;

  3. 数据流是单向的,master到slave;

  4. 主从复制底层依赖与RDB方式进行全量复制。

1.4 主从复制的工作原理

Redis主从之间的复制分为两点:

  1. 全量复制
  2. 增量复制

1.4.1 全量复制

Redis在第一次实现主从关系时会进行全量复制。
在这里插入图片描述

  1. Slave 通过 psync命令同步数据与Master建立socket长连接;

  2. Master 收到psync命令,执行bgsave语句生成RDB快照;

  3. Master发送RDB数据;

  4. Slave清空数据并加载Master发来的RDB数据;

  5. Master将生成RDB文件过程中,修改的数据,从repl buffer发送给Slave;

  6. Slave执行接收到的修改命令;

  7. Master通过socket长连接持续把写命令发送给从接单,保证数据一致性。

1.4.2 增量复制

如果由于网络原因造成原因造成主从断开,期间有数据写入master,再次形成主从时,会形成增量复制。
在这里插入图片描述

  1. Slave连接断开;

  2. Master最近数据的修改命令的缓存;

  3. Slave重新建立Socket长连接到master;

  4. Slave psync命令同步数据: offset偏移量控制;

  5. Master判断 Slave的offset。如果在repl backlog buffer中,Master会将缓存中从salve的offset之后数据一次性同步给salve节点,否则会全量同步;

  6. Master通过socket长连接持续把写命令发送给从节点,保证主从一致性。

1.5 Redis主从同步策略

主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。

当然,如果有需要,slave 在任何时候都可以发起全量同步。

redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步

2. 搭建Redis主从复制

在这里插入图片描述

节点服务器:
master 192.168.67.104
slave1 192.168.67.103
slave2 192.168.67.102

2.1 前置准备

#所有节点服务器配置
systemctl disable --now firewalld
#开机自动关闭防火墙

sed -i 's/enforcing/disabled/' /etc/selinux/config
#永久关闭selinux策略

所有节点编译安装redis数据库

#修改内核参数
vi /etc/sysctl.conf
vm.overcommit_memory = 1
net.core.somaxconn = 2048
#vm.overcommit_memory:该配置项用于设置内存超额分配策略。
#当值为 0 时,表示内核会根据实际情况动态分配内存,但这可能导致内存超额分配,当系统内存不足时,可能会引发OOM(Out of Memory)错误。
#将其设置为 1 可以禁用内存超额分配,确保只有在内存充足的情况下才能进行内存分配。这对于确保系统稳定性和可靠性是有帮助的。

#net.core.somaxconn:该配置项用于设置系统中允许的最大挂起连接数。
#当系统接收到大量并发连接请求时,如果系统的连接队列已满,则新的连接请求会被拒绝。
#通过增加 net.core.somaxconn 的值,可以增加系统的连接队列大小,从而提高系统处理并发连接请求的能力。

sysctl -p
#刷新参数

在这里插入图片描述

在这里插入图片描述

wget https://download.redis.io/releases/redis-7.0.13.tar.gz
#可以在官网上下载安装包
redis-7.0.9.tar.gz         #所需安装包

yum install -y gcc gcc-c++ make

tar zxvf /opt/redis-7.0.9.tar.gz -C /opt/
cd /opt/redis-7.0.9

在这里插入图片描述

make
make PREFIX=/usr/local/redis install     #指定安装目录
#由于Redis源码包中直接提供了 Makefile 文件,所以在解压完软件包后,不用先执行 ./configure 进行配置,可直接执行 make 与 make install 命令进行安装

在这里插入图片描述
在这里插入图片描述

mkdir /usr/local/redis/{conf,log,data}


cp /opt/redis-7.0.9/redis.conf /usr/local/redis/conf/
#建立用户redis来管理服务,更改工作目录的属主属组
useradd -M -s /sbin/nologin redis
chown -R redis.redis /usr/local/redis/
#创建管理用户并更改属主和属组

在这里插入图片描述

#添加环境变量
vi /etc/profile 

PATH=$PATH:/usr/local/redis/bin		
#增加一行
#可以直接使用redis命令

source /etc/profile
#刷新文件

在这里插入图片描述

vi /usr/local/redis/conf/redis.conf

bind 127.0.0.1 192.168.67.104				#87行,添加 监听的主机地址
protected-mode no					
#111行,将本机访问保护模式设置no。如果开启了,那么在没有设定bind ip且没有设密码的情况下,Redis只允许接受本机的响应
port 6379									#138行,Redis默认的监听6379端口
daemonize yes								#309行,设置为守护进程,后台启动
pidfile /usr/local/redis/log/redis_6379.pid		#341行,指定 PID 文件
logfile "/usr/local/redis/log/redis_6379.log"
#354行,指定日志文件
dir /usr/local/redis/data	#504行,指定持久化文件所在目录
requirepass abc123			#1037行,增加一行,设置redis密码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

vi /usr/lib/systemd/system/redis-server.service
[Unit]
Description=Redis Server
After=network.target

[Service]
User=redis
Group=redis
Type=forking
TimeoutSec=0
PIDFile=/usr/local/redis/log/redis_6379.pid
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

systemctl daemon-reload
#重新加载

#启动服务
systemctl start redis-server
systemctl enable redis-server

在这里插入图片描述

ss -lntp | grep 6379
#查看相关进程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 配置master节点

vim /usr/local/redis/conf/redis.conf
#修改redis主配置文件

bind 0.0.0.0							#87行,修改监听地址为0.0.0.0
protected-mode no						#111行,将本机访问保护模式设置no
port 6379								#138行,Redis默认的监听6379端口
daemonize yes							#309行,设置为守护进程,后台启动
pidfile /usr/local/redis/log/redis_6379.pid		#341行,指定 PID 文件
logfile "/usr/local/redis/log/redis_6379.log"	#354行,指定日志文件
dir /usr/local/redis/data				#504行,指定持久化文件所在目录
#requirepass abc123						#1037行,可选,设置redis密码
appendonly yes							#1380行,开启AOF

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

systemctl restart redis-server.service
#重启数据库

2.3 配置slave1-2节点

slave

vim /usr/local/redis/conf/redis.conf
#编辑redis主配置文件

bind 0.0.0.0							
#87行,修改监听地址为0.0.0.0

protected-mode no						
#111行,将本机访问保护模式设置no

port 6379								
#138行,Redis默认的监听6379端口

daemonize yes							
#309行,设置为守护进程,后台启动

pidfile /usr/local/redis/log/redis_6379.pid		#341行,指定 PID 文件

logfile "/usr/local/redis/log/redis_6379.log"	#354行,指定日志文件

dir /usr/local/redis/data				
#504行,指定持久化文件所在目录

replicaof 192.168.67.104 6379			
#528行,指定要同步的Master节点IP和端口

masterauth abc123						
#535行,可选,指定Master节点的密码,仅在Master节点设置了requirepass

requirepass abc123						
#1038行,可选,设置redis密码

appendonly yes							
#1380行,开启AOF

在这里插入图片描述

在这里插入图片描述

systemctl restart redis-server.service
#重启服务

slave2

#在slave1中
scp 192.168.67.102:/usr/local/redis/conf/redis.conf /usr/local/redis/conf/redis.conf
#远程传输配置文件

systemctl restart redis-server.service

在这里插入图片描述

2.4 主从复制结果验证

#前往master查看日志
tail -f /usr/local/redis/log/redis_6379.log 

在这里插入图片描述

#在Master节点上验证从节点:
redis-cli -a abc123 info replication -a

在这里插入图片描述

3. 哨兵模式

3.1 简介

在这里插入图片描述

主从切换技术的方法是:当服务器宕机后,需要手动一台从机切换为主机,这需要人工干预,不仅费时费力而且还会造成一段时间内服务不可用

为了解决主从复制的缺点,就有了哨兵机制

哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移
默认端口号:26379

3.2 哨兵的作用

  • 监控:哨兵会不断地检查主节点和从节点是否运作正常。

  • 自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其它从节点改为复制新的主节点。

  • 通知(提醒):哨兵可以将故障转移的结果发送给客户端。

3.3 结构组成

  • 哨兵节点:哨兵系统由一个或多个哨兵节点组成哨兵节点是特殊的redis节点,不存储数据。
  • 数据节点:主节点和从节点都是数据节点。

3.4 哨兵故障转移机制

在这里插入图片描述

由哨兵节点定期监控发现主节点是否出现了故障

  • 每个哨兵节点每隔1秒会向主节点、从节点及其它哨兵节点发送一次ping命令做一次心跳检测。
  • 如果主节点在一定时间范围内不回复或者是回复一个错误消息,那么这个哨兵就会认为这个主节点主观下线了(单方面的)。
  • 当超过半数哨兵节点认为该主节点主观下线了,这样就客观下线了。

当主节点出现故障,此时哨兵节点会通过Raft算法(选举算法)实现选举机制共同选举出一个哨兵节点为leader,来负责处理主节点的故障转移和通知。
所以整个运行哨兵的集群的数量不得少于3个节点。

由leader哨兵节点执行故障转移

将某一个从节点升级为新的主节点,让其它从节点指向新的主节点;
若原主节点恢复也变成从节点,并指向新的主节点;
通知客户端主节点已经更换。

注:客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。

3.5 主节点选举机制

  1. 过滤掉不健康的(已下线的),没有回复哨兵 ping 响应的从节点。
  2. 选择配置文件中从节点优先级配置最高的。(replica-priority,默认值为100)
  3. 选择复制偏移量最大,也就是复制最完整的从节点。

3.6 部署Redis哨兵模式

#节点服务器
master 192.168.67.104
slave1 192.168.67.103
slave2 192.168.67.102

3.6.1 修改所有节点 Redis 哨兵模式的配置文件

cp /opt/redis-7.0.9/sentinel.conf /usr/local/redis/conf/
#拷贝模板文件

chown redis.redis /usr/local/redis/conf/sentinel.conf
#更改文件属主和属组

在这里插入图片描述

vi /usr/local/redis/conf/sentinel.conf
#编辑配置文件

protected-mode no							
#6行,关闭保护模式

port 26379									#10行,Redis哨兵默认的监听端口

daemonize yes								#15行,指定sentinel为后台启动

pidfile /usr/local/redis/log/redis-sentinel.pid		
#20行,指定 PID 文件

logfile "/usr/local/redis/log/sentinel.log"	#25行,指定日志存放路径

dir /usr/local/redis/data					#54行,指定数据库存放路径

sentinel monitor mymaster 192.168.67.104 6379 2
#73行
#指定该哨兵节点监控192.168.67.104:6379这个主节点
#该主节点的名称是mymaster,
#最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移

sentinel auth-pass mymaster abc123			#76行指定Master节点的密码,仅在Master节点设置了requirepass

sentinel down-after-milliseconds mymaster 3000
#114行,判定服务器down掉的时间周期,默认3000毫秒(3秒)

sentinel failover-timeout mymaster 180000	#214行,同一个sentinel对同一个master两次failover之间的间隔时间(180秒)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6.2 实现基于vip的故障漂移

#VIP地址漂移
#修改哨兵配置文件279行,添加脚本路径
sentinel client-reconfig-script mymaster /usr/local/redis/conf/fail.sh

在这里插入图片描述

#!/bin/bash
MASTER_IP=$6
#表示传递的第六个参数,即新Master的地址
INTERFACE="ens33"
LOCAL_IP=$(ifconfig $INTERFACE | awk 'NR==2 {print $2}')
#本机IP 网卡ens33对应
VIP="192.168.2.200"
#设定VIP
NETMASK="24"
KEY="1"

#判断当前节点是否为主节点
if [ "$MASTER_IP" = "$LOCAL_IP" ];then
/sbin/ifconfig ${INTERFACE}:${KEY} ${VIP}/${NETMASK}
#如果是,将设定的VIP绑定到指定的网络接口上
exit 0
else
/sbin/ifconfig ${INTERFACE}:${KEY} down
#如果不是,将指定的网络接口和绑定的VIP停止
fi
exit 1


chmod +x fail.sh
#给脚本加执行权限

在这里插入图片描述

#Master节点的脚本和配置文件传输给Slave1
scp /usr/local/redis/conf/sentinel.conf 192.168.67.103:/usr/local/redis/conf/sentinel.conf
scp /usr/local/redis/conf/fail.sh 192.168.67.103:/usr/local/redis/conf/

#Master节点的脚本和配置文件传输给Slave2
scp /usr/local/redis/conf/sentinel.conf 192.168.67.102:/usr/local/redis/conf/sentinel.conf
scp /usr/local/redis/conf/fail.sh 192.168.67.102:/usr/local/redis/conf/


chown redis.redis /usr/local/redis/conf/sentinel.conf
#复制过后需要更改属主和属组

在这里插入图片描述
在这里插入图片描述

3.6.3 启动哨兵模式

注:一定要先启动master,再启动slave

cd /usr/local/redis/conf/

redis-sentinel sentinel.conf &

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.6.4 查看哨兵信息

redis-cli -p 26379 info Sentinel

在这里插入图片描述

#执行脚本
#添加VIP
bash fail.sh 1 1 1 1 1 192.168.67.104 1
ifconfig

在这里插入图片描述

3.6.5 故障模拟测试

观察各个节点的master、slave状态,还有VIP地址能否自动漂移。

#关闭主节点的Redis服务
systemctl stop redis-server
#通过slave1观察是否自动故障转移
redis-cli -h 192.168.67.103 -p 26379

info sentinel

在这里插入图片描述

#前往slave1查看VIP是否漂移
ifconfig

在这里插入图片描述

#重新启动master节点redis服务
systemctl start redis-server

#连接到redis
redis-cli -a abc123 -h 192.168.67.104 info replication

#观察两个配置文件 
#可以看到配置文件自动被修改,原来的master状态变为slave

在这里插入图片描述
在这里插入图片描述

4. Redis集群

4.1 集群的简单介绍

集群,即Redis Cluster,是Redis 3.0开始引入的分布式存储方案。

集群由多组节点(Node)组成,Redis的数据分布在这些节点中。

集群中的节点分为主节点从节点

  • 只有主节点负责读写请求和集群信息的维护
  • 从节点只进行主节点数据和状态信息的复制

4.2 集群的作用

可以归纳为两点

4.2.1 数据分区

数据分区(或称数据分片)是集群最核心的功能。

集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;

另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。

注:Redis单机内存大小受限问题

例如:
如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。

4.2.2 高可用

  • 集群支持主从复制和主节点的自动故障转移(与哨兵类似);
  • 当任一节点发生故障时,集群仍然可以对外提供服务。

4.3 集群的数据分片

  1. Redis集群引入了哈希槽的概念
  2. Redis集群有16384个哈希槽(编号0-16383)
  3. 集群的每组节点负责一部分哈希槽
  4. 每个Key通过CRC16校验后对16384取余来决定放置哪个哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
#以3个节点组成的集群为例:
节点A包含0到5460号哈希槽
节点B包含5461到10922号哈希槽
节点C包含10923到16383号哈希槽

#Redis集群的主从复制模型
集群中具有A、B、C三个节点,如果节点B失败了,整个集群就会因缺少5461-10922这个范围的槽而不可以用。
为每个节点添加一个从节点A1、B1、C1整个集群便有三个Master节点和三个slave节点组成,在节点B失败后,集群选举B1位为的主节点继续服务。当B和B1都失败后,集群将不可用。

4.4 搭建Redis群集

在这里插入图片描述
Redis的集群一般需要6个节点,3主3从。

方便起见,这里在同一台服务器上模拟。

4.4.1 前置准备

服务器IP主端口从端口
Node1节点192.168.2.10660016004
Node2节点192.168.2.10660026005
Node3节点192.168.2.10660036006

4.4.2 创建集群管理目录及文件

cd /usr/local/redis/
mkdir -p redis-cluster/redis600{1..6}

#复制 Redis 配置文件和可执行文件到不同目录
for i in {1..6}
do
#执行复制 循环6次
cp /opt/redis-7.0.9/redis.conf /usr/local/redis/redis-cluster/redis600$i
cp /opt/redis-7.0.9/src/redis-cli /opt/redis-7.0.9/src/redis-server /usr/local/redis/redis-cluster/redis600$i
done

在这里插入图片描述

#创建相应pid和日志文件
touch redis_6001.pid
touch redis_6001.log
#重复操作

在这里插入图片描述

4.4.3 开启Redis群集功能

其他5个文件夹的配置文件配置类似,6个端口都要不一样。

cd /usr/local/redis/redis-cluster/redis6001

vim redis.conf

#bind 127.0.0.1								#87行,注释掉bind项,默认监听所有网卡

protected-mode no								#111行,关闭保护模式
port 6001										#138行,修改redis监听端口
daemonize yes									#309行,设置为守护进程,后台启动
pidfile /usr/local/redis/log/redis_6001.pid		#341行,指定 PID 文件
logfile "/usr/local/redis/log/redis_6001.log"	#354行,指定日志文件
dir ./											#504行,指定持久化文件所在目录
appendonly yes									#1379行,开启AOF
cluster-enabled yes								#1576行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf				#1584行,取消注释,群集名称文件设置
cluster-node-timeout 15000						#1590行,取消注释群集超时时间设置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#将6001的配置文件,分别复制给2-6
cp redis.conf ../redis6002/
cp redis.conf ../redis6003/
cp redis.conf ../redis6004/
cp redis.conf ../redis6005/
cp redis.conf ../redis6006/

在这里插入图片描述

#使用sed,直接替换端口号
sed -i 's/6001/6002/' ../redis6002/redis.conf
#以6002为例,其余操作相同

sed -n '/6002/p' redis.conf
#查看是否更改成功

在这里插入图片描述

4.4.4 启动所有redis节点

#进入各个节点文件
redis-server redis.conf
#执行命令,启动节点

ps -ef | grep redis
#查看进程

在这里插入图片描述

redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
#六个实例分为三组,每组一主一从,前面的做主节点,后面的做从节点。下面交互的时候 需要输入 yes 才可以创建。
#--replicas 1 表示每个主节点有1个从节点。

在这里插入图片描述
在这里插入图片描述

4.4.5 测试集群

#登录6001
redis-cli -p 6001 -c					
#加-c参数,节点之间就可以互相跳转
cluster slots			
#查看节点的哈希槽编号范围

在这里插入图片描述

#测试
127.0.0.1:6002> set name scj
127.0.0.1:6001> cluster keyslot name
#查看name键的槽编号

redis-cli -p 6005 -c
127.0.0.1:6004> keys *						#对应的slave节点也有这条数据,但是别的节点没有

在这里插入图片描述

#连接到6001节点并获取集群中的节点信息
redis-cli -p 6001 -c cluster nodes

在这里插入图片描述

4.5 扩充Cluster集群

4.5.1 再次创建集群管理目录及文件

cd /usr/local/redis/
mkdir -p redis-cluster/redis600{7..8}
#复制 Redis 配置文件和可执行文件到不同目录
for i in {7..8}
do
cp /opt/redis-7.0.9/redis.conf /usr/local/redis/redis-cluster/redis600$i
cp /opt/redis-7.0.9/src/redis-cli /opt/redis-7.0.9/src/redis-server /usr/local/redis/redis-cluster/redis600$i
done

在这里插入图片描述

#创建pid及日志文件
touch redis_6007.log
touch redis_6007.pid
#重复操作

在这里插入图片描述

4.5.2 修改配置文件并开启集群功能

cp ../redis6001/redis.conf redis.conf
#覆盖原配置文件
sed -i 's/6001/6007/' redis.conf
#修改其中端口号
sed -n '/6007/p' redis.conf

#重复操作

在这里插入图片描述
在这里插入图片描述

#修改完成后开启集群功能
./redis-server ./redis.conf

ps -ef | grep redis

在这里插入图片描述

4.5.3 将7-8添加如集群中

#创建一个新的主节点127.0.0.1:6007。命令里需要指定一个已有节点以便于获取集群信息,本例是指定的127.0.0.1:6001
redis-cli -p 6001 --cluster add-node 127.0.0.1:6007 127.0.0.1:6001
或
redis-cli -p 6001
cluster meet 127.0.0.1 6007
cluster meet 127.0.0.1 6008

在这里插入图片描述

cluster nodes

在这里插入图片描述

#将127.0.0.1:6008创建为127.0.0.1:6007的从节点。命令里需要指定一个已有节点以便于获取集群信息和主节点的node ID
redis-cli -p 6007 --cluster add-node 127.0.0.1:6008 127.0.0.1:6007 --cluster-slave --cluster-master-id 27b680c2a455f25b9a4192fa4bc48e496ef6c5d2 
或
redis-cli -p 6008
cluster replicate 27b680c2a455f25b9a4192fa4bc48e496ef6c5d2 

在这里插入图片描述

#新加入的主节点是没有槽数的,只有初始化集群的时候,才会根据主的数据分配好,如新增的主节点,需要手动分配
redis-cli -p 6007 --cluster reshard 127.0.0.1:6001
#从6001分配哈希槽到6007

在这里插入图片描述
在这里插入图片描述

#查看集群状态
cluster nodes

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值