Redis学习总结

什么是Redis

Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如下:
- 字符串类型
- 散列类型
- 列表类型
- 集合类型
- 有序集合类型

Redis的应用场景

  • 缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)
  • 分布式集群架构中的session分离。
  • 聊天室的在线好友列表。
  • 任务队列。(秒杀、抢购、12306等等)
  • 应用排行榜。
  • 网站访问统计。
  • 数据过期处理(可以精确到毫秒)

Redis的安装和配置

关于Redis的安装和配置可查看Linux下的服务搭建https://blog.csdn.net/ititii/article/details/80172225,在这篇文章对Redis的持久化方案和Redis的服务搭建、主从复制以及Redis的集群模拟搭建做出了简要的介绍。

Redis数据类型

  • string类型
  • 赋值
 语法:set key
 eg:127.0.0.1:6379> set s1 111
 OK
  • 取值
语法:get key
eg:127.0.0.1:6379> get s1
"111"
  • 设置多个值
语法:mset key value [key value ...]
eg:127.0.0.1:6379> mset s2 222 s3 333
OK
  • 获取多个值
语法:mget key [key ...]
eg:127.0.0.1:6379> mget s1 s2 s3
1) "111"
2) "222"
3) "333"
  • 取值并赋值
    取值并赋值的意思:先取出 原来的值,并对原来的值进行从新赋值。
语法:getset key value
eg:127.0.0.1:6379> getset s1 1111
"111"
  • 删除
语法:del key
eg:127.0.0.1:6379> del s3
(integer) 1
  • 数值增减
    当存储的字符串是整数时,Redis提供了一个实用的命令INCR,其作用是让当前键值递增,并返回递增后的值。
    递增:
语法:incr key
eg:127.0.0.1:6379> incr num
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> incr num
(integer) 3
增加指定的整数
语法:incrby key increment
eg:127.0.0.1:6379> incrby num 2
(integer) 5
127.0.0.1:6379> incrby num 2
(integer) 7
127.0.0.1:6379> incrby num 2
(integer) 9

递减:

语法:decr key
eg:127.0.0.1:6379> decr num
(integer) 8
127.0.0.1:6379> decr num
(integer) 7
127.0.0.1:63
递减指定的整数
语法:decrby key increment
eg:127.0.0.1:6379> decrby num 2
(integer) 4
127.0.0.1:6379> decrby num 2
(integer) 2
127.0.0.1:6379> decrby num 2
(integer) 0
  • 向尾部追加值
    append的作用是向键值的末尾追加value。如果键不存在则将该键的值设置为value,即相当于 set key value。返回值是追加后字符串的总长度。
语法:append key value
eg:127.0.0.1:6379> set s3 hell
OK
127.0.0.1:6379> append s3 o
(integer) 5
127.0.0.1:6379> get s3
"hello"
  • 获取字符串长度
语法:strlen key
eg:127.0.0.1:6379> strlen s3
(integer) 5

应用:商品可以采用字符的数字递增的形式来作为商品的主键生成策略(这样就可以避免多个数据库中的商品信息主键重复)
string类型的问题:
假设一个pojo类型的对象以Json序列化的形式存储到Redis中,如果要修改pojo类型的对象的属性的值,如果采用string类型传输就会变得比较麻烦已经浪费资源,毕竟有时只需要修改其中某个属性,采用string类型就需要对其中的数据进行全部传输和修改。


  • hash类型
  • hash类型介绍
    hash叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。
    这里写图片描述
  • 赋值
    hset命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0。
语法:hset key field value
eg:127.0.0.1:6379> hset user username zhangsan
(integer) 1
127.0.0.1:6379> hset user username lisi
(integer) 0
  • 插入多个值
语法:hmset key field value [field value ....]
eg:127.0.0.1:6379> hmset user age 13 telephone 13333333
OK
  • 取值
语法:hget key field
eg:127.0.0.1:6379> hget user username
"lisi"
  • 取多个值
语法:hmget key field [field...]
eg:127.0.0.1:6379> hmget user username age telephone
1) "lisi"
2) "13"
3) "13333333"
  • 获取所有字段值
语法:hgetall key
eg:127.0.0.1:6379> hgetall user
1) "username"
2) "lisi"
3) "age"
4) "13"
5) "telephone"
6) "13333333"
  • 删除字段
    可以删除一个或多个字段,返回值是被删除的字段个数
语法:hdel key field [field ...]
eg:127.0.0.1:6379> hdel user age telephone
(integer) 2
  • 增加数字
语法:hincrby key field increment
eg:127.0.0.1:6379> hincrby user age 2
(integer) 2
127.0.0.1:6379> hincrby user age 2
(integer) 4
  • 判断字段是否存在
语法:hexists key field
eg:127.0.0.1:6379> hexists user age
(integer) 1(存在为1)
127.0.0.1:6379> hexists user ae
(integer) 0(不存在为0)
  • 只获取字段名或字段值
语法:hkeys key
      hvals key
eg:127.0.0.1:6379> hkeys user
1) "username"
2) "age"
127.0.0.1:6379> hvals user
1) "lisi"
2) "4"
  • 获取字段数量
语法:hlen key
eg:127.0.0.1:6379> hlen user
(integer) 2

应用:存储商品信息;


  • List类型
  • ArrayList 和LinkedList区别:
    ArrayList使用数组方式存储数据,所以根据索引查询数据速度快,而新增或者删除元素时需要设计到位移操作,所以比较慢。
    LinkedList使用双向链表方式存储数据,每个元素都记录前后元素的指针,所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快。然后通过下标查询元素时需要从头开始索引,所以比较慢,但是如果查询前几个元素或后几个元素速度比较快。
  • redis的list介绍
    列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段。
    列表类型内部是使用双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度为0(1),获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的。
  • 向列表两端增加元素
    • 向列表左边增加元素:
    • 向列表右边增加元素
左边:
语法:lpush key value [value]
eg:127.0.0.1:6379> lpush list 1 2 3
(integer) 3
右边:
语法:rpush key value [value ...]
eg:127.0.0.1:6379> rpush list a b c
(integer) 6
  • 查看列表
    lrange命令是列表类型最常用的命令之一,获取列表中的某一片段,将返回start、stop之间的所有元素(包含两端的元素),索引从0开始。索引可以是负数,如:“-1”代表最后边的一个元素。
语法:lrange key start stop
eg:127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
4) "a"
5) "b"
6) "c"
  • 从列表两端弹出元素
    lpop命令从列表左边弹出一个元素,会分两步完成:
    第一步是将列表左边的元素从列表中移除
    第二步是返回被移除的元素值
语法:lpop key
rpop key
eg:127.0.0.1:6379> lpop list
"3"
127.0.0.1:6379> rpop list
"c"
  • 获取列表中元素的个数
语法:llen key
eg:127.0.0.1:6379> llen list
(integer) 4
  • 删除列表中指定的值
    lrem命令会删除列表中前count个值为value的元素,返回实际删除的元素个数。根据count值的不同,该命令的执行方式会有所不同:
    当count>0时, LREM会从列表左边开始删除。
    当count<0时, LREM会从列表后边开始删除。
    当count=0时, LREM删除所有值为value的元素。
语法: lrem key count value
eg:127.0.0.1:6379> lrem list 2 2
(integer) 2
  • 获得/设置指定索引的元素值
获取指定索引的值:
语法:lindex key index
eg:127.0.0.1:6379> lindex list 3
"1"
设置指定索引的值:
语法:lset list index value
eg:127.0.0.1:6379> lset list 3 3
OK
  • 只保留列表指定片段
语法:ltrim key start stop
eg:127.0.0.1:6379> ltrim list 0 5
OK
  • 向列表中插入元素
    该命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数是before还是after来决定将value插入到该元素的前面还是后面。
语法:linsert key before|after pivot value
eg:127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> linsert list after 3 4
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "4"
3) "2"
4) "1"
  • 将元素从一个列表转移到另一个列表中
语法:rpoplpush source destination
eg:127.0.0.1:6379> rpoplpush list newlist 
"1"
127.0.0.1:6379> lrange newlist 0 -1
1) "1"
127.0.0.1:6379> lrange list 0 -1
1) "3"
2) "4"
3) "2"

应用:商品列表的评论;


  • Set类型
  • redis set介绍
    集合中的数据是不重复且没有顺序。集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型的Redis内部是使用值为空的散列表实现,所有这些操作的时间复杂度都为0(1)。
    Redis还提供了多个集合之间的交集、并集、差集的运算。
  • 增加/删除元素
增加元素:
语法:sadd key number [number]
eg:127.0.0.1:6379> sadd set a b c
(integer) 3
127.0.0.1:6379> sadd set a
(integer) 0
删除元素:
语法:srem key number [number]
eg:127.0.0.1:6379> srem set c d
(integer) 1
  • 获得集合中的所有元素
语法:smembers key
eg:127.0.0.1:6379> smembers set
1) "b"
2) "a”
  • 判断元素是否在集合中
语法:sismember key member
eg:127.0.0.1:6379> sismember set a
(integer) 1
127.0.0.1:6379> sismember set h
(integer) 0
  • 集合的差集运算A-B
语法:sdiff key key
eg:127.0.0.1:6379> sadd setA 1 2 3
(integer) 3
127.0.0.1:6379> sadd setB 2 3 4
(integer) 3
127.0.0.1:6379> sdiff setA setB 
1) "1"
127.0.0.1:6379> sdiff setB setA 
1) "4"
  • 集合的交集运算 A ∩ B
语法:sinter key key
eg:127.0.0.1:6379> sinter setA setB 
1) "2"
2) "3"
  • 集合的并集运算 A ∪ B
语法:sunion key key
eg:127.0.0.1:6379> sunion setA setB
1) "1"
2) "2"
3) "3"
4) "4"
  • 获得集合中元素的个数
语法:scard key
eg:127.0.0.1:6379> smembers setA 
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> scard setA 
(integer) 3
  • 从集合中弹出一个元素
    注意:由于集合是无序的,所有SPOP命令会从集合中随机选择一个元素弹出
语法:spop key
eg:127.0.0.1:6379> spop setA 
"1“

  • SortedSet类型zset
  • 4.5.1redis sorted set介绍
    在集合类型的基础上,有序集合类型为集合中的每个元素都关联一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在在集合中,还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素等与分数有关的操作。

在某些方面有序集合和列表类型有些相似。
- 1、二者都是有序的。
- 2、二者都可以获得某一范围的元素。
但是,二者有着很大区别:
- 1、列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会变慢。
- 2、有序集合类型使用散列表实现,所有即使读取位于中间部分的数据也很快。
- 3、列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)
- 4、有序集合要比列表类型更耗内存。

- 增加元素
向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。

语法:zadd key score member [score member ...]
eg:127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu 
(integer) 3
127.0.0.1:6379> zadd scoreboard 97 lisi 
(integer) 0
  • 获取元素的分数
语法:zscore key member
eg:127.0.0.1:6379> zscore scoreboard lisi 
"97"
  • 删除元素
    移除有序集key中的一个或多个成员,不存在的成员将被忽略。
    当key存在但不是有序集类型时,返回一个错误。
语法:zrem key member [member...]
eg:127.0.0.1:6379> zrem scoreboard lisi
(integer) 1
  • 获得排名在某个范围的元素列表
    获得排名在某个范围的元素列表
    按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素)
语法:zrange key start stop 
eg:127.0.0.1:6379> zrange scoreboard 0 2
1) "zhangsan"
2) "wangwu"
3) "lisi“

按照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

语法:zrevrange key start stop
eg:127.0.0.1:6379> zrevrange scoreboard 0 2
1) " lisi "
2) "wangwu"
3) " zhangsan “

如果需要获得元素的分数的可以在命令尾部加上WITHSCORES参数

eg:127.0.0.1:6379> zrange scoreboard 0 1 WITHSCORES
1) "zhangsan"
2) "80"
3) "wangwu"
4) "94"
  • 获得指定分数范围的元素
语法:zrangebyscore key min max [WITHSCORES] [LIMIT offset count]
eg:127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES
1) "wangwu"
2) "94"
3) "lisi"
4) "97"
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2
1) "wangwu"
2) "lisi"
  • 增加某个元素的分数
语法:zincrby key increment member
eg:127.0.0.1:6379> ZINCRBY scoreboard 4 lisi 
"101“
  • 获得集合中元素的数量
语法:zcard key
eg:127.0.0.1:6379> ZCARD scoreboard
(integer) 3
  • 获得指定分数范围内的元素个数
语法 :zcount key min max
eg:127.0.0.1:6379> ZCOUNT scoreboard 80 90
(integer) 1
  • 按照排名范围删除元素
语法: zremrangebyrank key start stop
eg:
127.0.0.1:6379> ZREMRANGEBYRANK scoreboard 0 1
(integer) 2 
127.0.0.1:6379> ZRANGE scoreboard 0 -1
1) "lisi"
  • 按照分数范围删除元素
语法:zremrangebyscore key min max
eg:127.0.0.1:6379> zadd scoreboard 84 zhangsan  
(integer) 1
127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100
(integer) 1
  • 获取元素的排名
从小到大:
语法:zrank key member
eg:127.0.0.1:6379> ZRANK scoreboard lisi 
(integer) 0
从大到小:
语法:zrevrank key member
eg:127.0.0.1:6379> ZREVRANK scoreboard zhangsan 
(integer) 1

应用:商品销售排名;


  • keys命令
  • 设置key的生存时间
    Redis在实际使用过程中更多的用作缓存,然而缓存的数据一般都是需要设置生存时间的,即:到期后数据销毁。
EXPIRE key seconds           设置key的生存时间(单位:秒)key在多少秒后会自动删除
TTL key                     查看key生于的生存时间
PERSIST key             清除生存时间 
PEXPIRE key milliseconds    生存时间设置单位为:毫秒

eg:

192.168.101.3:7002> set test 1      设置test的值为1
OK
192.168.101.3:7002> get test            获取test的值
"1"
192.168.101.3:7002> EXPIRE test 5   设置test的生存时间为5秒
(integer) 1
192.168.101.3:7002> TTL test            查看test的生于生成时间还有1秒删除
(integer) 1
192.168.101.3:7002> TTL test
(integer) -2
192.168.101.3:7002> get test            获取test的值,已经删除
(nil)

Jedis客户端

  • java进行单实例连接:
public class JedisClient {

    @Test
    public void testJedis() {
        // 创建一个Jedis的连接
        Jedis jedis = new Jedis("192.168.211.128", 6379);
        // 执行redis命令
        jedis.hset("user1", "age", "18");
        // 从redis中取值
        String result = jedis.hget("user1", "age");
        // 打印结果
        System.out.println(result);
        // 关闭连接
        jedis.close();
    }
}
  • Java进行连接池连接:
@Test
    public void testJedisPool() {
        //创建一连接池对象
        JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
        //从连接池中获得连接
        Jedis jedis = jedisPool.getResource();
        String result = jedis.get("mytest");
        System.out.println(result);
        //关闭连接
        jedis.close();

        //关闭连接池
        jedisPool.close();
    }
  • spring整合jedis
    spring配置文件application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd 
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!-- 连接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大连接数 -->
        <property name="maxTotal" value="30" />
        <!-- 最大空闲连接数 -->
        <property name="maxIdle" value="10" />
        <!-- 每次释放连接的最大数目 -->
        <property name="numTestsPerEvictionRun" value="1024" />
        <!-- 释放连接的扫描间隔(毫秒) -->
        <property name="timeBetweenEvictionRunsMillis" value="30000" />
        <!-- 连接最小空闲时间 -->
        <property name="minEvictableIdleTimeMillis" value="1800000" />
        <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
        <property name="softMinEvictableIdleTimeMillis" value="10000" />
        <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
        <property name="maxWaitMillis" value="1500" />
        <!-- 在获取连接的时候检查有效性, 默认false -->
        <property name="testOnBorrow" value="false" />
        <!-- 在空闲时检查有效性, 默认false -->
        <property name="testWhileIdle" value="true" />
        <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
        <property name="blockWhenExhausted" value="false" />
    </bean>

    <!-- redis单机 通过连接池 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool"
        destroy-method="close">
        <constructor-arg name="poolConfig" ref="jedisPoolConfig" />
        <constructor-arg name="host" value="192.168.242.130" />
        <constructor-arg name="port" value="6379" />
    </bean>
</beans>

测试代码:

@Test
    public void testJedisPool() {
        JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool");
        Jedis jedis = null;
        try {
            jedis = pool.getResource();

            jedis.set("name", "lisi");
            String name = jedis.get("name");
            System.out.println(name);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (jedis != null) {
                // 关闭连接
                jedis.close();
            }
        }
    }

  • JedisCluster连接Redis集群
@Test
public void testJedisCluster() throws Exception {
    //创建一连接,JedisCluster对象,在系统中是单例存在
    Set<HostAndPort> nodes = new HashSet<>();
    nodes.add(new HostAndPort("192.168.211.128", 7001));
    nodes.add(new HostAndPort("192.168.211.128", 7002));
    nodes.add(new HostAndPort("192.168.211.128", 7003));
    nodes.add(new HostAndPort("192.168.211.128", 7004));
    nodes.add(new HostAndPort("192.168.211.128", 7005));
    nodes.add(new HostAndPort("192.168.211.128", 7006));
    JedisCluster cluster = new JedisCluster(nodes);
    //执行JedisCluster对象中的方法,方法和redis一一对应。
    cluster.set("cluster-test", "my jedis cluster test");
    String result = cluster.get("cluster-test");
    System.out.println(result);
    //程序结束时需要关闭JedisCluster对象
    cluster.close();
}
  • spring 整合JedisCluster
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!-- 最大连接数 -->
    <property name="maxTotal" value="30" />
    <!-- 最大空闲连接数 -->
    <property name="maxIdle" value="10" />
    <!-- 每次释放连接的最大数目 -->
    <property name="numTestsPerEvictionRun" value="1024" />
    <!-- 释放连接的扫描间隔(毫秒) -->
    <property name="timeBetweenEvictionRunsMillis" value="30000" />
    <!-- 连接最小空闲时间 -->
    <property name="minEvictableIdleTimeMillis" value="1800000" />
    <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
    <property name="softMinEvictableIdleTimeMillis" value="10000" />
    <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
    <property name="maxWaitMillis" value="1500" />
    <!-- 在获取连接的时候检查有效性, 默认false -->
    <property name="testOnBorrow" value="true" />
    <!-- 在空闲时检查有效性, 默认false -->
    <property name="testWhileIdle" value="true" />
    <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
    <property name="blockWhenExhausted" value="false" />
</bean>
<!-- redis集群 -->
<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
    <constructor-arg index="0">
        <set>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="192.168.211.128"></constructor-arg>
                <constructor-arg index="1" value="7001"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="192.168.211.128"></constructor-arg>
                <constructor-arg index="1" value="7002"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="192.168.211.128"></constructor-arg>
                <constructor-arg index="1" value="7003"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="192.168.211.128"></constructor-arg>
                <constructor-arg index="1" value="7004"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="192.168.211.128"></constructor-arg>
                <constructor-arg index="1" value="7005"></constructor-arg>
            </bean>
            <bean class="redis.clients.jedis.HostAndPort">
                <constructor-arg index="0" value="192.168.211.128"></constructor-arg>
                <constructor-arg index="1" value="7006"></constructor-arg>
            </bean>
        </set>
    </constructor-arg>
    <constructor-arg index="1" ref="jedisPoolConfig"></constructor-arg>
</bean>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值