四阶段--day13--Redis缓存入门/Redis常用数据类型

目录

一 Redis简介

1 背景描述

2 Redis 概述

3 版本及参考说明

二 Redis初始操作

1 启动redis服务

​   1.1 docker 中查看redis 服务

 1.2 查看启动的redis进程信息

 2 进入redis容器

3 登陆redis服务

3.1 登陆本地redis

3.2  登陆远程redis

4 查看redis信息

5 清空redis屏幕

6  退出redis服务

7  关闭redis服务

8  系统帮助

三 Redis数据存储操作

1 简易数据存取

1.1 基于查看redis中的key

1.2  基于key/value形式存储数据

1.3  基于key获取redis中存储的数据

1.4  清除redis中的数据

2  Key有效时间设计

2.1  Expire (设置生效时长-单位秒)

2.2  Persist (取消时长设置)

2.3  pexpire (单位毫秒)

四 Redis常用数据类型

1 简介

1.1 概述

1.2  常用数据类型

2 String类型操作实践

2.1 incr/incrby

2.2  decr/decrby

2.3  append

2.4  strlen

2.5  mset/mget 同时设置/获取多个键值

2.6  小节面试分析

3  Hash类型应用实践

3.1 hset/hget

3.2 hincrby--自增  hdecrby--自减 可指定自减自增的系数

3.3 hmset/hmget

3.4   hexists   属性字段是否存在

3.5  hdel

3.6 hkeys/hvals  只获取字段名HKEYS或字段值HVALS

3.7 小节面试分析

4 List类型应用实践

4.1 lpush

4.2 rpush

4.3 del

4.4  linsert

4.5 lset

4.6 lrem

4.7 ltrim

4.8 lpop

4.9  rpop

4.10 llen

4.11   lindex

4.12  rpoplpush

4.13  小节面试分析

5 Set类型应用实践

5.1  sadd

5.2 smembers

5.3 spop

5.4  scard

5.5  smove

5.6  sunion

5.7  小节面试分析


一 Redis简介

本章节主要是讲解了一下redis的一些入门操作,主要是一些需要记住的一些指令,强化练习即可

1 背景描述

我们现在的项目架构中,基本上是Web服务器(Tomcat)和数据库独立部署,独占服务器资源,随着用户数的增长,并发读写数据库,会加大数据库访问压力,导致性能的下降,严重时直接导致系统宕机,例如:

在这里插入图片描述

此时,我们可以在Tomcat同服务器上中增加本地缓存,并在外部增加分布式缓存,缓存热门数据。也就是通过缓存能把绝大多数请求在读写数据库前拦截掉,大大降低数据库压力。例如:

在这里插入图片描述

 基于这样的一种架构设计,于是类似redis的一些分布式数据库就诞生了。

2 Redis 概述

Redis是一个key-value存储系统(官网:http://redis.io),是一个分布式缓存数据库。在DB-Engines.com的数据库排行中, Redis上升排行第七.

在这里插入图片描述

 redis是内存数据库,断点可能会失去数据

3 版本及参考说明

Redis的次版本号(第一个小数点后的数字)为偶数的版本是稳定版本(2.4、2.6等),奇数为非稳定版本(2.5、2.7),一般推荐在生产环境使用稳定版本。最新版本6.2.2,新增了stream的处理方式,性能更高。Redis官方是不支持windows平台的,windows版本是由微软自己建立的分支,基于官方的Redis源码上进行编译、发布、维护的,所以windows平台的Redis版本要略低于官方版本。
Redis 相关参考网址如下所示:

Bootnb 相关:https://www.runoob.com/redis/redis-tutorial.html
Redis 官网:https://redis.io/
源码地址:https://github.com/redis/redis
Redis 在线测试:http://try.redis.io/
Redis 命令参考:http://doc.redisfans.com/

二 Redis初始操作

1 启动redis服务

Docker 环境下的启动(docker环境启动多个需要运行多个容器):

docker start redis #底层也是通过redis-server启动,start单词后的redis为容器名

设置开机自启:

  

 1.1 docker 中查看redis 服务

docker ps

 1.2 查看启动的redis进程信息

ps -ef | grep redis
root      3511     1  0 16:29 ?   00:00:01 redis-server *:6379
root      3515     1  0 16:29 ?   00:00:01 redis-server 127.0.0.1:6380

 2 进入redis容器

docker exec -it redis01 bash #redis01 为容器名

3 登陆redis服务

3.1 登陆本地redis

redis-cli
或者
redis-cli -p 6379
或者
redis-cli -p 6379 -a  password #-a后面为password,此操作需要开启redis.conf文件中的 requirepass选项

3.2  登陆远程redis

redis-cli  -h ip  -p 6379  -a  password

4 查看redis信息

首先登陆redis,然后输入info指令,例如

127.0.0.1:6379> info		#查看当前redis节点的详细配置信息

5 清空redis屏幕

清除redis屏幕内容,不会把redis数据库内容清除

127.0.0.1:6379> clear

6  退出redis服务

退出redis服务,例如

127.0.0.1:6379> exit

7  关闭redis服务

127.0.0.1:6379> shutdown

保护模式的关闭,会保存redis内容

8  系统帮助

可以基于hep指令查看相关指令帮助,例如

127.0.0.1:6379> help
redis-cli 2.8.19
Type: "help @<group>" to get a list of commands in <group>
      "help <command>" for help on <command>
      "help <tab>" to get a list of possible help topics
      "quit" to exit
127.0.0.1:6379> help type

  TYPE key
  summary: Determine the type stored at key
  since: 1.0.0
  group: generic

三 Redis数据存储操作

1 简易数据存取

1.1 基于查看redis中的key

127.0.0.1:6379> keys *
(empty list or set)

1.2  基于key/value形式存储数据

127.0.0.1:6379> set test1 123
OK
127.0.0.1:6379> set test2 ab
OK
127.0.0.1:6379> keys *
1) "test1"
2) "test2"

1.3  基于key获取redis中存储的数据

127.0.0.1:6379> get test1
"123"
127.0.0.1:6379> get test2
"ab"
127.0.0.1:6379> get test3
(nil)
127.0.0.1:6379>

1.4  清除redis中的数据

1)  清除当前数据库数据

127.0.0.1:6379> flushdb
OK

2)  清除所有数据库数据

127.0.0.1:6379> flushall
OK

2  Key有效时间设计

实际工作中我们经常要控制redis中key的有效时长,例如秒杀操作的计时,缓存数据的有效时长等。

2.1  Expire (设置生效时长-单位秒)

语法:EXPIRE key seconds


127.0.0.1:6379> set bomb tnt
OK
127.0.0.1:6379> expire bomb 10
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) 5
127.0.0.1:6379> ttl bomb
(integer) 3
127.0.0.1:6379> ttl bomb
(integer) 3
127.0.0.1:6379> ttl bomb
(integer) 2
127.0.0.1:6379> ttl bomb
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) -2
127.0.0.1:6379> ttl bomb
(integer) -2
127.0.0.1:6379>

其中,TTL查看key的剩余时间,当返回值为-2时,表示键被删除。
当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。

2.2  Persist (取消时长设置)

通过persist让对特定key设置的生效时长失效。

语法:PERSIST key

127.0.0.1:6379> set bomb tnt
OK
127.0.0.1:6379> expire bomb 60
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) 49
127.0.0.1:6379> persist bomb
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) -1
127.0.0.1:6379>

其中,设置新的数据时需要重新设置该key的生存时间,重新设置值也会清除生存时间。

2.3  pexpire (单位毫秒)

pexpire 让key的生效时长以毫秒作为计量单位,这样可以做到更精确的时间控制。例如,可应用于秒杀场景。

语法:PEXPIRE key milliseconds

127.0.0.1:6379> set bomb tnt
OK
127.0.0.1:6379> pexpire bomb 10000
(integer) 1
127.0.0.1:6379> ttl bomb
(integer) 6
127.0.0.1:6379> ttl bomb
(integer) 3
127.0.0.1:6379> ttl bomb
(integer) -2
127.0.0.1:6379>

四 Redis常用数据类型

本章节主要是对redis中的常用数据类型存储结构,基本操作进行了分析和实践,结合指令特性理解其应用场景

1 简介

1.1 概述

Redis作为一种key/value结构的数据存储系统,为了便于对数据进行进行管理,提供了多种数据类型。然后,基于指定类型存储我们项目中产生的数据,例如用户的登陆信息,购物车信息,商品详情信息等等。

1.2  常用数据类型

Reids中基础数据结构包含字符串、散列,列表,集合,有序集合。工作中具体使用哪种类型要结合具体场景。

2 String类型操作实践

字符串类型是redis中最简单的数据类型,它存储的值可以是字符串,其最大字符串长度支持到512M。基于此类型,可以实现博客的字数统计,将日志不断追加到指定key,实现一个分布式自增iid,实现一个博客的的点赞操作等..

2.1 incr/incrby

当存储的字符串是整数时,redis提供了一个实用的命令INCR,其作用是让当前键值递增,并返回递增后的值。
语法:INCR key

127.0.0.1:6379> set num 1
(integer) 1
127.0.0.1:6379> incr num #默认递增1
(integer) 2
127.0.0.1:6379> keys *
1) "num"	
127.0.0.1:6379> incr num
127.0.0.1:6379>

说明,如果num不存在,则自动会创建,如果存在自动+1

指定增长系数:
语法:INCRBY key increment

127.0.0.1:6379> incrby num 2  #每次递减2
(integer) 5
127.0.0.1:6379> incrby num 2
(integer) 7
127.0.0.1:6379> incrby num 2
(integer) 9
127.0.0.1:6379>

2.2  decr/decrby

减少指定的整数
DECR key 按照默认步长(默认为1)进行递减
DECRBY key decrement 按照指定步长进行递减

127.0.0.1:6379> incr num    #递增1
(integer) 10
127.0.0.1:6379> decr num   #递减1
(integer) 9
127.0.0.1:6379> decrby num 3  #每次递减3

2.3  append

向尾部追加值。如果键不存在则创建该键,其值为写的value,即相当于SET key value。返回值是追加后字符串的总长度。
语法:APPEND key value

127.0.0.1:6379> keys *
1) "num"
2) "test1"
3) "test"
127.0.0.1:6379> get test
"123"
127.0.0.1:6379> append test "abc"
(integer) 6
127.0.0.1:6379> get test
"123abc"
127.0.0.1:6379>

2.4  strlen

字符串长度,返回数据的长度,如果键不存在则返回0。注意,如果键值为空串,返回也是0。
语法:STRLEN key

127.0.0.1:6379> get test
"123abc"
127.0.0.1:6379> strlen test
(integer) 6
127.0.0.1:6379> strlen tnt
(integer) 0
127.0.0.1:6379> set tnt ""
OK
127.0.0.1:6379> strlen tnt
(integer) 0
127.0.0.1:6379> exists tnt
(integer) 1
127.0.0.1:6379>

2.5  mset/mget 同时设置/获取多个键值


语法:MSET key value [key value …]
MGET key [key …]

127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> mset a 1 b 2 c 3
OK
127.0.0.1:6379> mget a b c
1) "1"
2) "2"
3) "3"
127.0.0.1:6379>

2.6  小节面试分析

  • 博客的字数统计如何实现?(strlen)
  • 如何将审计日志不断追加到指定key?(append)
  • 你如何实现一个分布式自增id?(incr-雪花算法)
  • 如何实现一个博客的的点赞操作?(incr,decr)

3  Hash类型应用实践

Redis散列类型相当于Java中的HashMap,实现原理跟HashMap一致,一般用于存储对象信息,存储了字段(field)和字段值的映射,一个散列类型可以包含最多2的32次方-1个字段。

3.1 hset/hget

语法结构

HSET key field value
HGET key field
HMSET key field value [field value…] #中括号内容可要可不要
HMGET key field [field]  #hmget  获取全部字段的值
HGETALL key

HSET和HGET赋值和取值

127.0.0.1:6379> hset user username chenchen
(integer) 1
127.0.0.1:6379> hget user username
"chenchen"
127.0.0.1:6379> hset user username chen
(integer) 0
127.0.0.1:6379> keys user
1) "user"
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379> 
127.0.0.1:6379> hset user age 18
(integer) 1
127.0.0.1:6379> hset user address "xi'an"
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
3) "age"
4) "18"
3) "address"
4) "xi'an"
127.0.0.1:6379>

HSET命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0。

3.2 hincrby--自增  hdecrby--自减 可指定自减自增的系数

127.0.0.1:6379> hdecrby article total 1		#执行会出错
127.0.0.1:6379> hincrby article total -1		#没有hdecrby自减命令
(integer) 1
127.0.0.1:6379> hget article total			#获取值

3.3 hmset/hmget

HMSET和HMGET设置和获取对象属性

127.0.0.1:6379> hmset person username tony age 18
OK
127.0.0.1:6379> hmget person age username
1) "18"
2) "tony"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>

注意:上面HMGET字段顺序可以自行定义

3.4   hexists   属性字段是否存在

属性是否存在
127.0.0.1:6379> hexists killer
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379> hexists killer a
(integer) 0
127.0.0.1:6379> hexists user username
(integer) 1
127.0.0.1:6379> hexists person age
(integer) 1
127.0.0.1:6379>

3.5  hdel

删除属性

127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>

3.6 hkeys/hvals  只获取字段名HKEYS或字段值HVALS

127.0.0.1:6379> hkeys person
1) "username"
2) "age"
127.0.0.1:6379> hvals person
1) "tony"
2) "18"
2.3.8	hlen
元素个数
127.0.0.1:6379> hlen user
(integer) 1
127.0.0.1:6379> hlen person
(integer) 2
127.0.0.1:6379>

  

3.7 小节面试分析

  • 发布一篇博客需要写内存吗?(需要,hmset)
  • 浏览博客内容会怎么做?(hmget)
  • 如何判定一篇博客是否存在?(hexists)
  • 删除一篇博客如何实现?(hdel)
  • 分布式系统中你登录成功以后是如何存储用户信息的?(hmset)

4 List类型应用实践

Redis的list类型相当于java中的LinkedList,其原理就就是一个双向链表。支持正向、反向查找和遍历等操作,插入删除速度比较快。经常用于实现热销榜,最新评论等的设计。

4.1 lpush

在key对应list的头部添加字符串元素

redis 127.0.0.1:6379> lpush mylist "world"
(integer) 1
redis 127.0.0.1:6379> lpush mylist "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>

其中,Redis Lrange 返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推

4.2 rpush

在key对应list的尾部添加字符串元素

redis 127.0.0.1:6379> rpush mylist2 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist2 "world"
(integer) 2
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>

4.3 del

redis 127.0.0.1:6379> del mylist

4.4  linsert

在key对应list的特定位置之前或之后添加字符串元素

redis 127.0.0.1:6379> rpush mylist3 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist3 "world"
(integer) 2
redis 127.0.0.1:6379> linsert mylist3 before "world" "there"
(integer) 3
redis 127.0.0.1:6379> lrange mylist3 0 -1
1) "hello"
2) "there"
3) "world"
redis 127.0.0.1:6379>

4.5 lset

设置list中指定下标的元素值(一般用于修改操作)

redis 127.0.0.1:6379> rpush mylist4 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist4 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist4 "three"
(integer) 3
redis 127.0.0.1:6379> lset mylist4 0 "four"
OK
redis 127.0.0.1:6379> lset mylist4 -2 "five"
OK
redis 127.0.0.1:6379> lrange mylist4 0 -1
1) "four"
2) "five"
3) "three"
redis 127.0.0.1:6379>

4.6 lrem

从key对应list中删除count个和value相同的元素,count>0时,按从头到尾的顺序删除

redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist5 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist5 2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "foo"
2) "hello"
redis 127.0.0.1:6379>
count<0时,按从尾到头的顺序删除
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist6 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist6 -2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "foo"
redis 127.0.0.1:6379>
count=0时,删除全部
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist7 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist7 0 "hello"
(integer) 3
redis 127.0.0.1:6379> lrange mylist7 0 -1
1) "foo"
redis 127.0.0.1:6379>

4.7 ltrim

保留指定key 的值范围内的数据

redis 127.0.0.1:6379> rpush mylist8 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist8 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist8 "three"
(integer) 3
redis 127.0.0.1:6379> rpush mylist8 "four"
(integer) 4
redis 127.0.0.1:6379> ltrim mylist8 1 -1
OK
redis 127.0.0.1:6379> lrange mylist8 0 -1
1) "two"
2) "three"
3) "four"
redis 127.0.0.1:6379>

4.8 lpop

从list的头部删除元素,并返回删除元素

redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> lpop mylist
"hello"
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "world"
redis 127.0.0.1:6379>

4.9  rpop

从list的尾部删除元素,并返回删除元素

redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> rpop mylist2
"world"
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
redis 127.0.0.1:6379>

4.10 llen

返回key对应list的长度:

redis 127.0.0.1:6379> llen mylist5
(integer) 2
redis 127.0.0.1:6379>

4.11   lindex

返回名称为key的list中index下标位置的元素:

redis 127.0.0.1:6379> lrange mylist5 0 -1  #lrange 返回列表指定区间元素
1) "three"
2) "foo"
redis 127.0.0.1:6379> lindex mylist5 0
"three"
redis 127.0.0.1:6379> lindex mylist5 1
"foo"
redis 127.0.0.1:6379>

4.12  rpoplpush

从第一个list的尾部移除元素并添加到第二个list的头部,最后返回被移除的元素值,整个操作是原子的.如果第一个list是空或者不存在返回nil:

rpoplpush lst1 lst1
rpoplpush lst1 lst2

4.13  小节面试分析

  1. 如何基于redis实现一个队列结构?(lpush/rpop)
  2. 如何基于redis实现一个栈结构?(lpush/lpop)
  3. 如何基于redis实现一个阻塞式队列?(lpush/brpop)
  4. 如何实现秒杀活动的公平性?(先进先出-FIFO)
  5. 通过list结构实现一个消息队列(顺序)吗?(可以,FIFO->lpush,rpop)
  6. 用户注册时的邮件发送功能如何提高其效率?(邮件发送是要调用三方服务,底层通过队列优化其效率,队列一般是list结构)
  7. 如何动态更新商品的销量列表?(卖的好的排名靠前一些,linsert)
  8. 商家的粉丝列表使用什么结构实现呢?(list结构)
     

5 Set类型应用实践

Redis的Set类似Java中的HashSet,是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。Redis中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

HashSet的值底层存到了map集合的key值中.

5.1  sadd 添加元素,重复元素添加失败,返回0

127.0.0.1:6379> sadd name tony
(integer) 1
127.0.0.1:6379> sadd name hellen
(integer) 1
127.0.0.1:6379> sadd name rose
(integer) 1
127.0.0.1:6379> sadd name rose
(integer) 0

5.2 smembers  获取内容

127.0.0.1:6379> smembers name

“hellen”
“rose”
“tony”

5.3 spop  移除并返回集合中的一个随机元素

127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
3) "rabbitmq"
4) "nginx"
127.0.0.1:6379> spop internet
"rabbitmq"
127.0.0.1:6379> spop internet
"nginx"
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"

5.4  scard  获取成员个数

127.0.0.1:6379> scard name
(integer) 3

5.5  smove   移动一个元素到另外一个集合

127.0.0.1:6379> sadd internet amoeba nginx redis
(integer) 3
127.0.0.1:6379> sadd bigdata hadopp spark rabbitmq
(integer) 3
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
3) "nginx"
127.0.0.1:6379> smembers bigdata
1) "hadopp"
2) "spark"
3) "rabbitmq"
127.0.0.1:6379> smove bigdata internet rabbitmq
(integer) 1
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
3) "rabbitmq"
4) "nginx"
127.0.0.1:6379> smembers bigdata
1) "hadopp"
2) "spark"
127.0.0.1:6379>

5.6  sunion  并集

127.0.0.1:6379> sunion internet bigdata
1) "redis"
2) "nginx"
3) "rabbitmq"
4) "amoeba"
5) "hadopp"
6) "spark"

5.7  小节面试分析

  • 朋友圈的点赞功能你如何实现?(sadd,srem,smembers,scard)
  • 如何实现一个网站投票统计程序?
  • 你知道微博中的关注如何实现吗?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值