redis文档api以及SpringBoot集成操作

redis

redis中的key设计
  1. 唯一性
  2. 可读性
  3. 灵活性
  4. 时效性
redis有无事务

看个人认知情况,因为redis单操作时有原子性,多个线程操作时redis无原子性,redis进行事务时,一旦其中一个redis操作出现异常,那么之前操作的redis也不会进行回滚

所以在这就出现了分歧

redis优势:

性能极高:redis能支持超过10w每秒读写的频率

优点:

​ 对数据高并发读写(直接是内存中进行读写的)
​ 对海量数据的高效率存储和访问
​ 对数据的可拓展性和高可用性.
​ 单线程操作,每个操作都是原子操作,没有并发相关问题(redis 6)

缺点:

​ redis(ACID处理非常简单)
​ 无法做太复杂的关系数据库模型

如果确定使用redis, 此时需要考虑使用哪个数据类型
1>如果要排序选用zset
2>如果数据是多个且允许重复选用list
3>如果数据是多个且不允许重复选用set
4>剩下的使用string
5>如果是对象类型也可使用hash
/* 有些公司约定: 所有的redis的key跟value都使用字符串(排除使用zset场景)【偏redis String类型json结构】
    1>如果要排序选用zset
    2>剩下的使用string
*/
redis安全性:

因为redis读写速度非常快,一秒之内可以进行密码破解15w次,所以需要一个设定强大的密码来解决外界的破解

String类型

包含多种类型的特殊类型,并且是二进制安全的.比如序列化的对象进行存储,比如一张图片进行二进制存储.,

set key value:设置key值下的value值
set age 2
get key: 获取key值下的value值
get age
incr key:把key下面的value值加一(只能进行数字类型)
incr age
decr key:把key下面的value值减一(只能进行数据类型)
decr age
del key:删除存在的key值
del age
setex key timeout value:存入键值对,timeout表示失效的时间,单位s
setex age 20 3
ttl key:查询当前的key还能存活多长的时间
ttl age
setnx key value:如果当前存在key的键值对则不进行添加,不存在key的键值对则直接添加
setnx name xiaosuda
hash类型

一个对象存储在hash类型要比存储在String类型占用的内存空间较少

hset key hashkey hashvalue -> 存入一个hash对象
hset user name xiaosuda
hget key hashkey -> 根据hash对象键取去值
hget user name
hexists key hashkey -> 判断hash对象是含有某个键
hexists user name
hdel key hashkey -> 根据hashkey删除hash对象键值对
hdel user name

了解部分

hincrby key field increment递增值 -> 递增field 对应的increment值
hincrby user id 2
hlen key -> 获取hash对象键的数量
hlen user
hkeys key -> 获取hash对象的所有键
hkeys * (拿到所有key键值对)
hvals key -> 获取hash对象的所有值
hvals user
hgetall key -> 获取hash对象的所有数据
hgetall *
List类型

类似一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,list的设计非常简单精巧,即可以作为栈,又可以作为队列.满足绝大多数需求

rpush key value -> 往列表右边添加数据
rpush name xiaoze
lpush key value -> 往列表左边添加数据
lpush name xiaotian
lrange key start end -> 范围显示列表数据,全显示则设置0 -1
lrange name 0 2
lpop key -> 弹出列表最左边的数据
lpop name
rpop key -> 弹出列表最右边的数据
rpop name
llen key -> 获取列表长度
llen name

了解部分

linsert key before/after refVal newVal -> 参考值之前/后插入数据
linsert name before b a //在b之前插入a
linsert name after b a  //在b之后插入a
lset key index value -> 根据索引修改数据
lset name 2 xiaomeng
lrem key count value -> 在列表中按照个数删除数据
lrem score 1 10 //从表头开始到表尾删除1个10
ltrim key start end -> 范围截取列表
ltrim name 1 20
lindex key index -> 根据索引取列表中数据
lindex name 10
Set类型

集合是string类型的无序集合,set是通过hashtable实现的,对集合我们可以取交集,并集,差集.

sadd key value -> 往set集合中添加元素
sadd name xiaotian
smembers key -> 列出set集合中的元素
smembers name
srem key value -> 删除set集合中的元素
srem name xiaotian
spop key count -> 随机弹出集合中的元素
spop name 1 //随便弹出集合中count个元素
sdiff key1 key2 -> 返回key1中特有元素(差集)

set1 : a b c

set2:b c f e

sdiff set1 set2 //a f c
sinter key1 key2 -> 返回两个set集合的交集
sinter set1 set2 //b c
sunion key1 key2 -> 返回两个set集合的并集
sunion set1 set2 a b c f e
scard key -> 返回set集合中元素个数
scard set1

了解

sdiffstore var key1 key2 -> 返回key1中特有元素存入另一个set集合
sdiffstore var set1 set2
sinterstore var key1 key2 -> 返回两个set集合的交集存入另一个set集合
sinterstore var set1 set2
sunionstore var key1 key2 -> 返回两个set集合的并集存入另一个set集合
sunionstore var set1 set2
smove key1 key2 value -> 把key1中的某元素移入key2中
smove set1 set2
sismember key value -> 判断集合是否包含某个值
sismember set a
srandmember key count -> 随机获取set集合中元素
srandmember set 2 //随机取count个元素
sorted_set类型
zadd key score column -> 存入分数和名称
zadd players 300 a
zadd players 300 b
zadd players 300 c
zincrby key score column -> 偏移名称对应的分数
zincrby players 12 a
zrange key start end -> 按照分数升序输出名称
zrange players 0 500
zrevrange key start end -> 按照分数降序输出名称
zrevrange players 0 500
zrank key name -> 升序返回排名
zrank players b
zrevrank key name -> 降序返回排名
zrevrank players b
zcard key -> 返回元素个数
zcard players
Stringboot集成reids的操作
private StringRedisTemplate template;
redisTemplate.opsForValue();操作字符串
//设置值
template.opsForValue().set(String key,String value);
//获取key下的value值
template.opsForValue().get(String value);
//自增
template.opsForValue().increment(String key);
//自减
template.opsForValue().decrement(String key);
//在原有的值基础上新增字符串到末尾。
template.opsForValue().append(String key,String value);
//在原有的值基础上新增字符串到末尾。
template.opsForValue().get(String key, long start, long end);
//获取原来key键对应的值并重新赋新值。
template.opsForValue().getAndSet(String key, String value);
//key键对应的值value对应的ascii码,在offset的位置(从左向右数)变为value。
template.opsForValue().setBit(String key,Long offset,boolean value);
//如果键不存在则新增,存在则不改变已经有的值。
template.opsForValue().selfAbsent(String key,String value);
//设置存活时间
template.opsForValue().set(String key, String value, long timeout, TimeUnit unit);
redisTemplate.opsForHash();操作hash
//添加hash对象
template.opsForHash().put(String key,String value);
//设置map集合到redis。
template.opsForHash().multiSet(Map<? extends K,? extends V> map)
//根据集合取出对应的value值。
template.opsForHash().multiGet(Collection<K> keys)
//获取指定变量中的hashMap值。
template.opsForHash().value(String key);
//获取变量中的键值对。
template.opsForHash().entries(String key)
//get(H key, Object hashKey)
template.opsForHash().get(String key, Object hashKey)
//根据hash对象对应的key键值对下的value值进行增加count值
template.opsForHash().increment(String key,String value,Time tiem);
//删除hash对象
template.opsForHash().delete(String key,String ...hashkey);
//打印hash对象的key下的value值
template.opsForHash().get(String key,String hashkey);
//获取hash对象的key下的value值
template.opsForHash().lengthOfValue(String key,String hashkey);
//获取变量中的键。
template.opsForHash().keys(String key);
// 判断变量中是否有指定的map键。
template.opsForHash().hasKey(String key, Object hashKey)
//遍历hash数组
for (Object obj : template.opsForHash().values(String key)) {
    System.out.println(obj);
}
//如果变量值存在,在变量中可以添加不存在的的键值对,如果变量不存在,则新增一个变量,同时将键值对添加到该变量。
template.opsForHash().putIfAbsent(String key, String hashKey, String value)
//匹配获取键值对,ScanOptions.NONE为获取全部键对,ScanOptions.scanOptions().match("map1").build()     匹配获取键位map1的键值对,不能模糊匹配。
template.opsForHash().scan(String key, ScanOptions options)
redisTemplate.opsForList();操作list
//从左边添加元素
template.opsForList().leftPush(String key,String pivot, String value);
//从右边添加元素
template.opsForList().rightPush(String key,String pivot, String value);
//从右边弹出一个元素
template.opsForList().rightPop(String key);
//从左边弹出一个元素
template.opsForList().leftPop(String key);
//根据范围打印list集合里面元素
template.opsForList().range(String key,long start,long end);
//返回元素个数
template.opsForList().size(String key);
//获取集合指定位置的值。
template.opsForList().index(String key, long index)
//向左边批量添加参数元素。
template.opsForList().leftPushAll(String key, String... values)
//如果存在集合则添加元素。
template.opsForList().leftPushIfPresent(String key, String value)
//向集合中第一次出现第二个参数变量元素的右边添加第三个参数变量的元素值。
template.opsForList().rightPush(K key, V pivot, V value)
//在集合的指定位置插入元素,如果指定位置已有元素,则覆盖,没有则新增,超过集合下标+n则会报错。
template.opsForList().set(String key, long index, String value)
redisTemplate.opsForSet();操作set
1add(K key, V... values)
    向变量中批量添加值。
    redisTemplate.opsForSet().add("setValue","A","B","C","B","D","E","F");  


2members(K key)
    获取变量中的值。
    Set set = redisTemplate.opsForSet().members("setValue");  
System.out.println("通过members(K key)方法获取变量中的元素值:" + set);  


3size(K key)
    获取变量中值的长度。
    long setLength = redisTemplate.opsForSet().size("setValue");  
System.out.println("通过size(K key)方法获取变量中元素值的长度:" + setLength);  


4randomMember(K key)
    随机获取变量中的元素。
    Object randomMember = redisTemplate.opsForSet().randomMember("setValue");  
System.out.println("通过randomMember(K key)方法随机获取变量中的元素:" + randomMember);  


5randomMembers(K key, long count)
    随机获取变量中指定个数的元素。
    List randomMembers = redisTemplate.opsForSet().randomMembers("setValue",2);  
System.out.println("通过randomMembers(K key, long count)方法随机获取变量中指定个数的元素:" + randomMembers);  


6isMember(K key, Object o)
    检查给定的元素是否在变量中。
    boolean isMember = redisTemplate.opsForSet().isMember("setValue","A");  
System.out.println("通过isMember(K key, Object o)方法检查给定的元素是否在变量中:" + isMember);  


7move(K key, V value, K destKey)
    转移变量的元素值到目的变量。
    boolean isMove = redisTemplate.opsForSet().move("setValue","A","destSetValue");  
if(isMove){  
    set = redisTemplate.opsForSet().members("setValue");  
    System.out.print("通过move(K key, V value, K destKey)方法转移变量的元素值到目的变量后的剩余元素:" + set);  
    set = redisTemplate.opsForSet().members("destSetValue");  
    System.out.println(",目的变量中的元素值:" + set);  
}  


8pop(K key)
    弹出变量中的元素。
    Object popValue = redisTemplate.opsForSet().pop("setValue");  
System.out.print("通过pop(K key)方法弹出变量中的元素:" + popValue);  
set = redisTemplate.opsForSet().members("setValue");  
System.out.println(",剩余元素:" + set)  


    9remove(K key, Object... values)
    批量移除变量中的元素。
    long removeCount = redisTemplate.opsForSet().remove("setValue","E","F","G");  
System.out.print("通过remove(K key, Object... values)方法移除变量中的元素个数:" + removeCount);  
set = redisTemplate.opsForSet().members("setValue");  
System.out.println(",剩余元素:" + set);


10scan(K key, ScanOptions options)
    匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match("C").build()匹配获取键位map1的键值对,不能模糊匹配。
    //Cursor<Object> cursor = redisTemplate.opsForSet().scan("setValue", ScanOptions.NONE);  
    Cursor<Object> cursor = redisTemplate.opsForSet().scan("setValue", ScanOptions.scanOptions().match("C").build());  
while (cursor.hasNext()){  
    Object object = cursor.next();  
    System.out.println("通过scan(K key, ScanOptions options)方法获取匹配的值:" + object);  
}  


11difference(K key, Collection<K> otherKeys)
    通过集合求差值。
    List list = new ArrayList();  
list.add("destSetValue");  
Set differenceSet = redisTemplate.opsForSet().difference("setValue",list);  
System.out.println("通过difference(K key, Collection<K> otherKeys)方法获取变量中与给定集合中变量不一样的值:" + differenceSet);  


12difference(K key, K otherKey)
    通过给定的key求2个set变量的差值。
    differenceSet = redisTemplate.opsForSet().difference("setValue","destSetValue");  
System.out.println("通过difference(K key, Collection<K> otherKeys)方法获取变量中与给定变量不一样的值:" + differenceSet);  


13differenceAndStore(K key, K otherKey, K destKey)
    将求出来的差值元素保存。
    redisTemplate.opsForSet().differenceAndStore("setValue","destSetValue","storeSetValue");  
set = redisTemplate.opsForSet().members("storeSetValue");  
System.out.println("通过differenceAndStore(K key, K otherKey, K destKey)方法将求出来的差值元素保存:" + set); 


14differenceAndStore(K key, Collection<K> otherKeys, K destKey)
    将求出来的差值元素保存。
    redisTemplate.opsForSet().differenceAndStore("setValue",list,"storeSetValue");  
set = redisTemplate.opsForSet().members("storeSetValue");  
System.out.println("通过differenceAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的差值元素保存:" + set); 


15distinctRandomMembers(K key, long count)
    获取去重的随机元素。
    set = redisTemplate.opsForSet().distinctRandomMembers("setValue",2);  
System.out.println("通过distinctRandomMembers(K key, long count)方法获取去重的随机元素:" + set);  


16intersect(K key, K otherKey)
    获取2个变量中的交集。
    set = redisTemplate.opsForSet().intersect("setValue","destSetValue");  
System.out.println("通过intersect(K key, K otherKey)方法获取交集元素:" + set); 


17intersect(K key, Collection<K> otherKeys) 
    获取多个变量之间的交集。
    set = redisTemplate.opsForSet().intersect("setValue",list);  
System.out.println("通过intersect(K key, Collection<K> otherKeys)方法获取交集元素:" + set); 


18intersectAndStore(K key, K otherKey, K destKey)
    获取2个变量交集后保存到最后一个参数上。
    redisTemplate.opsForSet().intersectAndStore("setValue","destSetValue","intersectValue");  
set = redisTemplate.opsForSet().members("intersectValue");  
System.out.println("通过intersectAndStore(K key, K otherKey, K destKey)方法将求出来的交集元素保存:" + set);  


19intersectAndStore(K key, Collection<K> otherKeys, K destKey)  
    获取多个变量的交集并保存到最后一个参数上。
    redisTemplate.opsForSet().intersectAndStore("setValue",list,"intersectListValue");  
set = redisTemplate.opsForSet().members("intersectListValue");  
System.out.println("通过intersectAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的交集元素保存:" + set); 


20union(K key, K otherKey)
    获取2个变量的合集。
    set = redisTemplate.opsForSet().union("setValue","destSetValue");  
System.out.println("通过union(K key, K otherKey)方法获取2个变量的合集元素:" + set);


21union(K key, Collection<K> otherKeys)
    获取多个变量的合集。
    set = redisTemplate.opsForSet().union("setValue",list);  
System.out.println("通过union(K key, Collection<K> otherKeys)方法获取多个变量的合集元素:" + set);  


22unionAndStore(K key, K otherKey, K destKey)
    获取2个变量合集后保存到最后一个参数上。
    redisTemplate.opsForSet().unionAndStore("setValue","destSetValue","unionValue");  
set = redisTemplate.opsForSet().members("unionValue");  
System.out.println("通过unionAndStore(K key, K otherKey, K destKey)方法将求出来的交集元素保存:" + set);


23unionAndStore(K key, Collection<K> otherKeys, K destKey)     
    获取多个变量的合集并保存到最后一个参数上。
    redisTemplate.opsForSet().unionAndStore("setValue",list,"unionListValue");  
set = redisTemplate.opsForSet().members("unionListValue");  
System.out.println("通过unionAndStore(K key, Collection<K> otherKeys, K destKey)方法将求出来的交集元素保存:" + set);

redisTemplate.opsForZSet();操作有序set
//存入分数和名称
template.opsForZSet().add(String key,String value,double scorce);
//返回元素个数
System.out.println(template.opsForZSet().zCard(String key));
//偏移名称对应的分数
template.opsForZSet().incrementScore(String key,String value,double delta);
//打印
template.opsForZSet().rangeWithScores(String key,long start,long end).forEach(x-> System.out.println(x.getValue()+"=="+x.getScore()));
//获取ZSetOperations类型的数组
for (ZSetOperations.TypedTuple<String> hui : template.opsForZSet().rangeWithScores(String key,long start,long end)) {
    System.out.println(hui.getValue() + "==" + hui.getScore());
}
//升序排序
System.out.println(template.opsForZSet().range(String key,long start,long end));
//降序排序
System.out.println(template.opsForZSet().reverseRange(String key,long start,long end));
//统计元素个数
System.out.println(template.opsForZSet().size(String key));
//升序返回排名
System.out.println(template.opsForZSet().rank(String key,String value));
//降序返回排名
System.out.println(template.opsForZSet().reverseRank(String key,String value));
//从集合中删除指定元素
template.opsForZSet().remove(String key,...String values);

清空redis数据

flushdb 清空当前数据库,flushall清空所有数据库

返回满足的所有键

    keys * (可以模糊查询)
    exists 是否存在指定key
    expire 设置某个key的过期时间.使用ttl查看剩余时间
    persist 取消过期时间

数据库
select 选择数据库 数据库为015(一共16个数据库) 默认进入的是0数据库
move [key] [数据库下标] 讲当前数据中的key转移到其他数据库中
randomkey 随机返回数据库里的一个key
rename重命名key
echo 打印名
dbsize 查看数据库的key数量
info 获取数据库信息
config get 实时传储收到的请求(返回相关的配置信息)
config get * 返回所有配置
密码设置
vi编辑redis.conf文件,找到下面进行保存修改
requirepass [密码]
重启服务器 pkill redis-server
再次进入127.0.01:6379>keys *
(error)NOAUTH Authentication required.
会发现没有权限进行查询auth [密码]
输入密码则成功进入
每次进入的时候都需要输入免密,还有种简单的方式:

redis-cli -a [密码]
常见的内存淘汰机制分为四大类:
   1. LRU:LRU是Least recently used,最近最少使用的意思,简单的理解就是从数据库中删除最近最少访问的数据,该算法认为,你长期不用的数据,那么被再次访问的概率也就很小了,淘汰的数据为最长时间没有被使用,仅与时间相关。
   2. LFU:LFU是Least Frequently Used,最不经常使用的意思,简单的理解就是淘汰一段时间内,使用次数最少的数据,这个与频次和时间相关。
   3. TTL:Redis中,有的数据是设置了过期时间的,而设置了过期时间的这部分数据,就是该算法要解决的对象。如果有些redis设置的key快要过期了那么提前让你结束掉。
   4. 随机淘汰:随机进行删除。
通过maxmemroy-policy可以配置具体的淘汰机制,看了网上很多文章说只有6种,其实有8种,可以看Redis5.0的配置文件

    1. volatile-lru -> 找出已经设置过期时间的数据集,将最近最少使用(被访问到)的数据干掉。
  2. volatile-ttl -> 找出已经设置过期时间的数据集,将即将过期的数据干掉。
  3. volatile-random -> 找出已经设置过期时间的数据集,进行无差别攻击,随机干掉数据。
  4. volatile-lfu -> 找出已经设置过期时间的数据集,将一段时间内,使用次数最少的数据干掉。
  5. allkeys-lru ->与第1个差不多,数据集从设置过期时间数据变为全体数据。
  6. allkeys-lfu -> 与第4个差不多,数据集从设置过期时间数据变为全体数据。
  7. allkeys-random -> 与第3个差不多,数据集从设置过期时间数据变为全体数据。
  8. no-enviction -> 什么都不干,报错,告诉你内存不足,这样的好处是可以保证数据不丢失,这也是系统默认的淘汰策略。

Redis过期Key清除策略

惰性删除:当访问key时,才去判断它是否过期了,如果过期了则直接干掉,这种方式很友好,但长时间不使用对于内存来说就是浪费

定时删除:设置key键值对的过期时间的同时设置一个定时器,当达到过期时间时进行key键值对清理

定期删除:自己定义一个时段去清理过期的key键值对,至于删除多少过期的key则看算法。

比如:如果进行一次删除时,过期的key还超过总体的25%那么会再次进行执行之前操作,直到不超过总体的25%为止

建议如下

Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,可以很好地在合理使用CPU和避免浪费内存之间取得平衡。
持久化机制两种机制

Redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中中的数据同步到硬盘来保证持久化.

  1. RBD

    RDB 详解:Redis 默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会将内存中的数据写入到磁盘中。即在指定目录下生成一个dump.rdb文件。Redis 重启会通过加载dump.rdb文件恢复数据

    RDB 的优缺点:

    优点:

    • 适合大规模的数据恢复。
    • 如果业务对数据完整性和一致性要求不高,RDB是很好的选择。

    缺点:

    • 数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。
    • 备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍哦),最后再将临时文件替换之前的备份文件。

    Snapshotting设置:

    save 900 1  #900秒内如果超过1个Key被修改则发起快照保存
    save 300 10 #300秒内如果超过10个key被修改,则发起快照保存
    save 60 10000
    
  2. AOF
    AOG详解:

    由于快照方式是在一定时间间隔做一次,所以可能发生reids意外down的情况就会丢失最后一次快照后的所有修改的数据.aof比快照方式有更好的持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到命令中,当redis重新启动时会重新执行文件中保存的写命令来在内存中重建这个数据库的内容.这个文件在bin目录下:appendonly.aof不是立即写到硬盘中,可以通过配置文件修改强制写到硬盘中
    

    AOG优缺点:

    • 优点:数据的完整性和一致性更高
    • 缺点:因为AOF记录的内容多,文件会越来越大,数据恢复也会越来越慢。

AOG设置:

appendonly yes //启动aof持久化方式有三种修改方式
#appendfsync always//收到命令就立即写到磁盘,效率最慢.但是能保证完全的持久化
#appendfsync everysec//每秒写入磁盘一次,在性能和持久化方面做了很好的折中
#appendfsync no //完全以依赖os 性能最好,持久化没保证
继承springboot
@Autowired
private StringRedisTemplate redisTemplate;

依赖

导入Jedis相关的依赖:
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
    <relativePath/>
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
导入Jedis相关的依赖:
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
在java的对应的方法
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值