redis

安装redis

安装c语言的编译环境

执行

yum install gcc
yum install gcc-c++

解压

tar -zxvf redis-6.2.5.tar.gz

进入redis-6.2.5目录

执行make 注:如果未安装gcc会安装失败,执行make distclean之后再执行一遍make

再执行make install

启动

1、前台启动

redis-server

2、后台启动

创建目录

[root@hadoop102 ~]# mkdir myredis

复制

[root@hadoop102 redis-6.2.5]# cp redis.conf /root/myredis

修改redis.conf文件将里面的daemonize no 改成 yes,让服务在后台启动

注释bind 127.0.0.1 -::1,能远程访问

启动

 redis-server myredis/redis.conf 

登入

redis-cli 

关闭

redis-cli shutdown

指定端口关闭

redis-cli -p 端口号 shutdown

redis相关知识介绍

端口:6379

使用select 来选择数据库

统一密码管理,所有库使用同样的密码

dbsize查看当前数据库的key的数量

flushdb清空当前库

flushall清空全部库

单线程+多路复用

key操作

添加元素

hadoop102:6379> set k1 lucy;

keys * 查看当前库所有key (匹配:key*1)

exists key判断某个key是否存在

type key查看你的key是什么类型

del key删除指定的key数据

unlink key根据value选择非阻塞删除,仅将keys可从keyspace元数据中删除,真正删除会在后续异步操作

expire key 10 10秒钟,给指定的key设置过期时间

ttl key查看当前时间key的过期时间

dbsize查看当前数据库的key的数量

flushdb清空当前库

flushall清空全部库

数据类型

String

String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

常用命令

get key获得值

set key添加值

append key追加值

strlen key获得值的长度

setnx key只有在key不存在时设置key的值

incr key将 key 中储存的数字值增1只能对数字值操作,如果为空,新增值为1

decr key将key中储存的数字值减1只能对数字值操作,如果为空,新增值为-1

incrby/decrby <步长> 将 key 中储存的数字值增减。自定义步长

mset key1 value1 key2 value2 … 同时设置一个或多个key-value对

mget k1 k2 …获取一个或多个value

msetnx k1 value1 k2 value2 key不存在就设置

getrange key 起始位置 结束位置 获得值的范围,类似Java中的substring

setrange key1 起始位置 value 用value覆写key所存储的字符串值,从起始位置开始

setex key 过期时间 value 设置设置key-value的时候设置过期时间,单位是秒

getset key value 设置新值并获得旧值

List

单键多值
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

image-20210909095407115

常用命令

lpush/rpush key value1 value2 value3 …从左边/右边插入一个或多个值

ipop/rpop key从左边/右边获取一个值,值在键在,值亡键亡,取完就清除

rpoplpush k1 k2 将k1右边的值插入到k2的左边

lrange key start stop 按照索引下标获得元素(从左到右)

lrange k1 0 -1能获得所有的值

lindex key index按照索引下标获得元素(从左到右)

llen key获得列表长度

linsert key before value newvalue 再value的前面插入newvalue

lrem key n value从左边删除n个value(从左到右)

lset key index value将列表key下表为index的值替换成value

set

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的复杂度都是O(1)。

常用命令

sadd key value1 value2… 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略

smembers key 取出集合的所有值

sismember key value 判断集合key是否含有该value值,有返回1,没有返回0

scard key 返回该集合的元素个数

srem key value1 value2删除集合中的某个元素

spop key 随机从该集合吐出一个值

srandmember key n 随机从该集合中取出n个值,不会从该集合中删除

smove source destionation value把集合中的一个值从一个集合移动到另一个集合

sinter k1 k2 返回两个集合的交集元素

sunion k1 k2 返回两个集合并集元素

sdiff k1 k2 返回k1中的差集元素

hash

Redis hash 是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
类似Java里面的Map<String,Object>

在这里插入图片描述

常用命令

hset k field v 给k集合中的field赋值v

hget k field 从k集合field取出value

hexists k field查看hash表key中,给定域field是否存在

hmset k1 field1 value1 field2 vlue2…批量设置hash

hexists k field 查看哈希表key中,给定域field是否存在

hkeys k 列出该hash集合的所有field

hvals k 列出该hash集合的所有value

hincrby key field increment 为哈希表key中的域field的值加上增量increment

hsetnx key field value 将哈希表key的域的值设置为value,当且仅当field不存在

Zset

Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的所有成员都关联了一个评分(score) ,这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了 。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

常用命令

zadd key score1 value1 score2 value2 将一个或多个member元素及其score值加入到有序集key当中

zrange key start stop [withscore] 返回有序集key中,下标start和stop之间的元素,带withscore,可以让分数一起和值返回到结果集

zrangebyscore key min max [withscores] [limit offset count]返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列

zrevrangebyscore key max min [withscores] [limit offset count]同上,改为从大到小排列。

zincrby key increment value为元素的score加上增量

zrem key value删除该集合下,指定值的元素

zcount key min max统计该集合,分数区间内的元素个数

zrank key value返回该值在集合中的排名,从0开始。

redis的发布和订阅

redis发布订阅(pub/sub)是一种消息通信模式:发送者pub发送消息,订阅者(sub)接收信息

redis客户端可以订阅任何数量的频道。

发布和订阅

客户端可以订阅频道

在这里插入图片描述

当给这个频道发布消息后,消息就会发给订阅的客户端

在这里插入图片描述

发布订阅命令实现

1、打开一个客户端订阅channel1

subscribe channel1

2、打开另一个客户端,给channel1发布消息hello
在这里插入图片描述

返回的1是订阅者数量

3、接受到信息
在这里插入图片描述

新数据类型

Bitmaps

Bitmaps本身不是一种数据类型,实际上它就是字符串,但是它可以对字符串进行位操作

Bitmaps单独提供了一套命令,所以在Redis中使用Bitmaps和使用字符串的方法不太相同。可以把bitmaps想象成一个以位为单位的数组,数组的每个单元只能存储0和1,数组的下标在bitmaps中叫偏移量

命令

setbit key offset value 设置bitmaps中某个偏移量的值(0或1)

getbit key offset

bitcount key [start end](从start 到 end)字节比特值为1的数量

bitop and(or/not/xor) destkey k1 [key …]

bitop是一个复合操作,它可以做多个bitmaps的and(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在destkey中

计算两天都登入的用户

hadoop102:6379> setbit unique:users:20201104 1 1(integer) 0hadoop102:6379> setbit unique:users:20201104 2 1(integer) 0hadoop102:6379> setbit unique:users:20201104 5 1(integer) 0hadoop102:6379> setbit unique:users:20201104 9 1(integer) 0hadoop102:6379> setbit unique:users:20201105 0 1(integer) 0hadoop102:6379> setbit unique:users:20201105 1 1(integer) 0hadoop102:6379> setbit unique:users:20201105 4 1(integer) 0hadoop102:6379> setbit unique:users:20201105 9 1

求交集

hadoop102:6379> bitop and unique:users:and unique:users:20201104 unique:users:20201105

HyperLogLog

Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。

但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

什么是基数

比如数据集{1,3,5,7,5,7,8},那么这个数据集的基数为{1,3,5,7,8},基数为5

命令

pfadd key element … 添加指定的元素到HyperLogLog中,添加成功返回1,不成功返回0

pfcount k1… 显示元素数量

pfmerge destkey sourcerkey sourcekey … 将一个或多个hll合并后的结果存储在另一个hll中

Geospatial

geo地理信息的缩写,该类型,就是元素的2维坐标,在地图上是经纬度。redis基于该类型,提供了经纬度的设置,查询,范围查询,距离查询,经纬度hash等常见操作

命令

geoadd key longitude latitude memeber … 添加地理位置(经度,纬度,名称)

hadoop102:6379> geoadd china:city 121.47 31.23 shanghai 106.6 29.53 chongqing

geopos key member …获得指定区域的坐标值

geodist key member1 member2 [m|km|ft|mi]获取两个位置之间的直线距离

m米,默认单位

km千米

ft英尺

mi英里

georadius key longitude latitude radius m|km|ft|mi 以给定的经纬度为中心,找出某一半径内的元素

jedis操作

<dependency>            <groupId>redis.clients</groupId>            <artifactId>jedis</artifactId>            <version>3.3.0</version>        </dependency>
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class jedisDemo {
    public static void main(String[] args) {
        Jedis jedis=new Jedis("hadoop102",6379);
        String value=jedis.ping();
        System.out.println(value);
    }
    @Test
    public void demo1(){
        Jedis jedis =new Jedis("hadoop102",6379);
        Set<String> keys = jedis.keys("*");
        for (String key : keys) {
            String type = jedis.type(key);
            //if(type.equals("string")) System.out.println(jedis.get(key)+" "+key);
            if(type.equals("set")) System.out.println(jedis.smembers(key).toString());
            if(type.equals("list")) System.out.println(jedis.lrange(key,0,-1));
            if(type.equals("hash")){
                System.out.println(jedis.hkeys(key));
                System.out.println(jedis.hvals(key));
            }
        }
    }
    @Test
    public void demo2(){
        Jedis jedis=new Jedis("hadoop102",6379);
        jedis.lpush("key1","lucy","mary","jack");
    }
    @Test
    public void demo3(){
        Jedis jedis=new Jedis("hadoop102",6379);
        Map<String,String> map =new HashMap<String,String>();
        map.put("name","jack");
        map.put("age","18");
        map.put("agent","boy");
        map.put("identity","student");
        map.put("nation","China");
        jedis.hset("ke2", map);
    }
}

Redis事务

事务

redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行地过程中,不会被其他客户端发送来的命令请求打断。

redis事务的主要作用就是串联多个命令防止别的命令插队。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。
    -
discard取消事务,放弃执行事务块内所有的命令
exec执行所有事物块内的命令
multi标记一个事物块的开始
unwatch取消watch命令对所有key的监视
watch key…监视一个或多个key,如果在事务执行之前这个key被其它命令所改动,那么事务将被打断
hadoop102:6379> multiOKhadoop102:6379(TX)> set key1 value1QUEUEDhadoop102:6379(TX)> set key2 value2QUEUEDhadoop102:6379(TX)> exec1) OK2) OK

不执行

hadoop102:6379> multiOKhadoop102:6379(TX)> set a1 v1QUEUEDhadoop102:6379(TX)> set a2 v2QUEUEDhadoop102:6379(TX)> discardOK

事务的错误处理

组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消

hadoop102:6379> multi
OK
hadoop102:6379(TX)> set b1 v1
QUEUED
hadoop102:6379(TX)> set b2 v2
QUEUED
hadoop102:6379(TX)> set b3
(error) ERR wrong number of arguments for 'set' command
hadoop102:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.

如果执行阶段某个命令报出来错误,则只有报错的命令不会被执行,而其它的命令都正常执行

hadoop102:6379> multi
OK
hadoop102:6379(TX)> set m1 v1
QUEUED
hadoop102:6379(TX)> incr m1
QUEUED
hadoop102:6379(TX)> set m2 v2
QUEUED
hadoop102:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK

锁机制

悲观锁

每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁

每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。

•在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

三特性

单独的隔离操作 ,事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

单独的隔离操作,事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

不保证原子性,Redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

redis持久化

RDB (Redis DataBase)

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。

如何执行

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

关于fork

•Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

rdb的保存文件

•在redis.conf中配置文件名称,默认为dump.rdb

路径默认在启动目录下

打开redis.conf

添加save 20 3

意思为,三个key变化后,20秒后保存

手动保存快照

命令save: 只管保存,其它不管,全部阻塞。手动保存,不建议

bgsave:redis会在后台异步进行快照操作,快照同时还可以响应客户端请求

rdb的备份

将dump.rdb文件复制到别的地方保存

AOF (Append Of File)

以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据,换言之,Redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

开启AOF

AOF默认不开启

改成yes

文件默认为appendonly.aof

AOF和RDB同时开启

系统默认取aof的数据(数据不会存在丢失)

备份和异常恢复

AOF同步频率设置

appendfsync always

始终同步,每次redis的写入都会立刻记入日志;性能较差但数据完整性较好

appendfsync everysec

每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失

appendfsync no

redis不主动进行同步,把同步时机交给操作系统

Rewrite压缩

AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof。

如何实现重写

AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

何时重写

重写虽然可以节约大量磁盘空间,减少恢复时间。但是每次重写还是有一定的负担的,因此设定Redis要满足一定条件才会进行重写。

系统载入时或者上次重写完毕时,Redis会记录此时AOF大小,设为base_size,如果Redis的AOF当前大小>= base_size +base_size*100% (默认)且当前大小>=64mb(默认)的情况下,Redis会对AOF进行重写

主从复制

主从复制,就是主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主

配置一从二主

在/root/myredis目录下创建文件redis6379.cof和redis6380.conf,redis6381.conf

内容分别为

include /root/myredis/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
include /root/myredis/redis.conf
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
include /root/myredis/redis.conf
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump6381.rdb

启动服务

[root@hadoop102 ~]# redis-server myredis/redis6379.conf 
[root@hadoop102 ~]# redis-server myredis/redis6380.conf
[root@hadoop102 ~]# redis-server myredis/redis6381.conf

查看是否启动

分别开新的窗口登入

[root@hadoop102 myredis]# redis-cli -p 6379

info replication打印主从复制的相关信息

slaveof ip port成为某个实例的从服务器

在从机上执行

127.0.0.1:6380> slaveof localhost 6379127.0.0.1:6381> slaveof localhost 6379

从机只能读,不能写

从机挂掉后,不能实现主从复制,从机需要重新配置,主机的内容会重新复制一遍

主机挂掉后,从机不变,主机重启后还是主机

复制原理

每次从机联通后,都会给主机发送sync指令

主机立刻进行存盘操作,发送RDB文件,给从机

从机收到RDB文件后,进行全盘加载

之后每次主机的写操作,都会立刻发送给从机,从机执行相同的命令

薪火相传

上一个slave可以是下一个slave的Master,slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险。

用 slaveof

中途变更转向:会清除之前的数据,重新建立拷贝最新的

风险是一旦某个slave宕机,后面的slave都没法备份

反客为主

当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改

用 slaveof no one 将从机变为主机。

哨兵模式

反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库.

配置

调整为一主二仆模式

自定义的myredis目录下新建sentinel.conf文件

在配置文件中填写内容:

​ sentinel monitor mymaster 127.0.0.1 6379 1

其中mymaster为监控对象起的服务器名称,1 为 至少有多少个哨兵同意迁移的数量。

启动哨兵:执行redis-sentinel /root/myredis/sentinel.conf

[root@hadoop102 myredis]# redis-sentinel /root/myredis/sentinel.conf

关闭主机

更换主机

集群

无中心化,连接任意一台主机和从机,都能操作集群

搭建集群

把以前的rdb文件删掉,以免造成影响

制作6个实例,6379,6380,6381,6389,6390,6391

拷贝多个redis.conf文件

开启daemonize yes

Pid文件名字

指定端口

Log文件名字

Dump.rdb名字

Appendonly关掉或者换名字

include /root/myredis/redis.conf
pidfile /var/run/redis_6391.pid
port 6391
dbfilename dump6391.rdb
cluster-enabled yes
cluster-config-file nodes-6391.conf
cluster-node-timeout 15000

启动所有服务

redis-server myredis/redis6379.conf 
redis-server myredis/redis6380.conf 
redis-server myredis/redis6381.conf 
redis-server myredis/redis6389.conf 
redis-server myredis/redis6390.conf 
redis-server myredis/redis6391.conf

将六个节点合成一个集群

[root@hadoop102 ~]# cd /opt/module/redis-6.2.5/src

执行

redis-cli --cluster create --cluster-replicas 1 192.168.1.102:6379 192.168.1.102:6380 192.168.1.102:6381 192.168.1.102:6389 192.168.1.102:6390 192.168.1.102:6391

这里要使用实际的ip地址,实际使用中,实在不同的机器,这里用一台机器模拟

登入集群

[root@hadoop102 src]# redis-cli -c -p 6379

127.0.0.1:6379> cluster nodes查看集群信息

redis cluster如何分配这六个节点

一个集群至少要有三个主节点

选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。

分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上。

slot

集群中录入值

•在redis-cli每次录入、查询键值,redis都会计算出该key应该送往的插槽,如果不是该客户端对应服务器的插槽,redis会报错,并告知应前往的redis实例地址和端口。

•redis-cli客户端提供了 –c 参数实现自动重定向。

如 redis-cli -c –p 6379 登入后,再录入、查询键值对可以自动重定向。

•不在一个slot下的键值,是不能使用mget,mset等多键操作。

•可以通过{}来定义组的概念,从而使key中{}内相同内容的键值对放到一个slot中去。

查询集群中的值

•CLUSTER KEYSLOT 计算键 key 应该被放置在哪个槽上。

•CLUSTER COUNTKEYSINSLOT 返回槽 slot 目前包含的键值对数量。

•CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。

故障处理

主机挂了,从机变成主机

主机恢复后,变成从机

参数 cluster-require-full-coverage 为yes 某一结点主机和从机都挂掉,集群挂掉。

集群的优缺点

Redis 集群提供了以下好处:

•实现扩容

•分摊压力

•无中心配置相对简单

Redis 集群的不足:

•多键操作是不被支持的

•多键的Redis事务是不被支持的。lua脚本不被支持。

•由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至redis cluster,需要整体迁移而不是逐步过渡,复杂度较大。

集群jedis

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class RedisClusterDemo {
    public static void main(String[] args) {
        //创建对象
        HostAndPort hostAndPort = new HostAndPort("hadoop102", 6379);
        JedisCluster jedisCluster = new JedisCluster(hostAndPort);

        //进行操作
        jedisCluster.set("b1","value1");
        String value = jedisCluster.get("b1");
        System.out.println("b1"+":"+value);
        jedisCluster.close();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值