Redis

下载安装启动

  1. cd 到Redis解压路径。
  2. 输入:redis-server.exe redis.windows.conf。
  3. 再打开一个cmd命令窗口,切入到Redis包下面,输入命令:
    redis-server --service-install redis.windows-service.conf --loglevel verbose
  4. redis-cli (启动本地)。

https://blog.csdn.net/qq_44664329/article/details/112993835

数据类型、特点、应用

string(字符串)

String数据结构是简单的key-value类型。

set user:id:1:email 3333@222.com;
set user:id:2:email 444@222.com;

//批量设置
mset key value [key value...]
mget key [key ...]

应用:
数据模型: 在这里插入图片描述

  1. 存储 MySQL 中某个字段的值
    把 key 设计为 表名:主键名:主键值:字段名 eg.
  2. 存储对象
    string 类型⽀持任何格式的字符串,应⽤最多的就是存储 json 或其他对象格式化的字符串。 ( 这种场景下推荐使⽤ hash 数据类型 )
set user:id:1 '[{"id":1,"name":"zj","email":"10000@qq.com"},]'
  1. ⽣成⾃增 id
    当 redis 的 string 类型的值为整数形式时, redis 可以把它当做是整数⼀样进行自增( incr )自减( decr) 操作。由于 redis 所有的操作都是原⼦性的,所以 不必担⼼多客户端连接时可能出现的事务 问题。 incr 对值进⾏加 1 操作,如果不是整数,返回错误,如果不存在按照从 0 开始 decr 同 incr ,但是是减 1 操作 incrby,decrby ,增加减去指定的数。⽐如视频播放次数,点赞次数。

  2. 共享 session
    数据共享的功能, redis 作为单独的应用软件用来存储⼀些共享数据供多个实例访问。

  3. ⾃动定时过期

set key value [ex seconds] [px millseconds] [nx|xx]
ex seconds: 键过期时间
px milliseconds: 为键设置毫秒级过期时间
nx: 键必须不存在才可以设置成功,⽤于添加
xx: 键必须存在,才可以设置成功,⽤于更新
  1. 日活统计:setBit

bitMap原理https://blog.csdn.net/weixin_37281289/article/details/106834014

在这里插入图片描述
在这里插入图片描述
https://blog.csdn.net/jack1liu/article/details/107128744

list(双向链表)

常见操作时用 lpush 命令在 list 头部插⼊元素, 用 rpop 命令在 list 尾取出数据。

hexists key field //判断filed是否存在
hkeys key //获取所有的field
hvals key //获取所有的value
hgetall key //获取所有的field-value ,如果元素数较多会存在阻塞redis的可能
hincreby key filed
rpush key value [value...] //从右插⼊元素
lpush key value [value...] //从左边插⼊元素
lrange key start end //获取指定范围的元素列表
lindex key index //获取列表指定索引下标的元素
llen key //获取列表的⻓度
lpop key // 从列表左侧弹出元素
rpop key // 从列表右侧弹出元素
lrem key count value //从列表中找到等于value的元素,并进⾏删除,根据count的不同有不同的情况
lset key index newValue //修改指定索引下标的元素
blpop key timeout //阻塞式左弹出key
brpop key timeout //阻塞式右弹出key,因为 list 结构的数据查询两端附近的数据性能⾮常好,所以适合⼀些需要获取最新数据的场景,⽐如新闻类应⽤的 “最近新闻”。
LTRIM key start stop //对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

应用:

1.消息队列。 redis 的 list 数据类型对于⼤部分使⽤者来说,是实现队列服务的最经济,最简单的方式。很多公司使用 redis 做消息队列, lpush + brpop 或 rpop 命令,实现先进先出,如果消费失败客户端把 key 再放回去,消费成功 就 remove 掉。

常用组合:
lpush + lpop = 栈
lpush + rpop = 队列
lpush + ltrim = 有限集合
lpush + brpop = 消息队列

https://www.cnblogs.com/knowledgesea/p/4972771.html

消息队列系统
使用list可以构建队列系统,使用zset(sorted set)甚至可以构建有优先级的队列系统。
比如:将Redis用作日志收集器
实际上还是一个队列,多个端点将日志信息写入Redis,然后一个worker统一将所有日志写到磁盘。

hash(散列,无序)

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象

应用:
⼀些关系型数据库中不是特别复杂的表,也无需复杂的关系查询,可以使⽤ Redis 的 Hash 来存储,也可以⽤ Hash 做表数据缓存。
数据模型:
在这里插入图片描述

hmset user:1 name zj email 123456@163.com
hset key field value
hsetnx key field value //与setnx命令⼀样,不存在则设置值,⽤于添加,作⽤在field上⾯
hget key field //获取值
hdel key field // 删除值
hlen key //字段field的个数
hmset key field value [filed value] //批量设置field-value
hexists key field //判断filed是否存在
hkeys key //获取所有的field
hvals key //获取所有的value
hgetall key //获取所有的field-value ,如果元素数较多会存在阻塞redis的可能
hincreby key filed

set (集合,无序不重复)

set就是一个集合,不重复值的组合。利用Redis提供的set数据结构,可以存储一些集合性的数据。set中的元素是没有顺序的。
往set中添加数据,返回值为当前集合个数。

sadd key value [value...] //添加元素
srem key value [value...] //删除元素
scard key //计算元素的个数
sismember key value //判断元素是否在集合中
srandmember key [count] //随机从集合中返回指定个数的元素,不写默认为1
spop key //从集合随机取出元素
smembers key //获取集合内的所有元素
sinter key1 key2 //求集合的交集
sunion key1 key2 //求集合的并集
sdiff key1 key2 //求集合的差集

应用:

  1. 共同好友列表
    社交类应用中,获取两个⼈或多个⼈的共同好友,两个⼈或多个⼈共同关注的微博这样类似的功 能,⽤ MySQL 的话操作很复杂,可以把每个人的好友 id 存到集合中,获取共同好友的操作就可以简单 到⼀个取交集的命令就搞定。
// 这⾥为了⽅便阅读,把 id 替换成姓名
sadd user:wade james melo paul kobe
sadd user:james wade melo paul kobe
sadd user:paul wade james melo kobe
sadd user:melo wade james paul kobe
// 获取 wade 和 james 的共同好友
sinter user:wade user:james
/* 输出:
2. 1) "kobe"
3. 2) "paul"
4. 3) "melo"
*/
// 获取⾹蕉四兄弟的共同好友
sinter user:wade user:james user:paul user:melo
/* 输出:
5. 1) "kobe"
*/
  1. 唯⼀ ip
    跟踪⼀些具有唯⼀性的⼀些数据,比如访问某⼀博客的唯⼀ ip 地址的信息,我们仅需要在每次访问的时候,将 ip 存入 redis 中。利用服务器端聚合操作⽅便⾼效的特性,维护数据对象之间的关联关系。

sorted set(有序不重复集合)

和set相比,zset(sorted set)增加了一个权重参数score,使得集合中的元素能够按score进行有序排列,比如一个存储全班同学成绩的zset,其集合value可以是同学的学号,而score就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。可以用sorted set来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

zadd key score member //score是可以重复的,添加key的时候指定分数
zcard key //计算成员个数
zscore key member //计算某个成员的分数
zrank key member //计算成员排名,从低到⾼
zrevrank key member //计算成员排名,从⾼到低
zrem key member [member...] //删除成员
zincrby key increnment member //增加成员的分数
zrange key start end [withscores] //从低到⾼返回指定排名的分数
zrevrange key start end [withscores] //从⾼到低返回
zrangebyscore key min max [withscores] [limit offset count] //按照分数从低到⾼返回
zrevrange score key min max [withscores] [limit offset count] //按照分数从⾼到低返回成员

应用:

  1. 根据好友的 “ 亲密度 ” 排序显示好友列表。
// ⽤元素的分数(score)表示与好友的亲密度
zadd user:kobe 80 james 90 wade 85 melo 90 paul
// 根据“亲密度”给好友排序
zrevrange user:kobe 0 -1
/**
2. 输出:
3. 1) "wade"
4. 2) "paul"
5. 3) "melo"
6. 4) "james"
*/
// 增加好友的亲密度
zincrby user:kobe 15 james
// 再次根据“亲密度”给好友排序
zrevrange user:kobe 0 -1
/**
7. 输出:
8. 1) "james"
9. 2) "wade"
10. 3) "paul"
11. 2) "melo"
*/
  1. 排 行 榜

实效性划分:
从排行榜的实效性上划分,主要分为:
实时榜: 基于当前⼀段时间内数据的实时更新,进⾏排行。例如:当前一小时内游戏热度实时 榜,当前一小时内明星送花实时榜等
历史榜: 基于历史⼀段周期内的数据,进行排行。例如:日榜(今天看昨天的),周榜(上⼀周的),月榜(上个月的),年榜(上⼀年的)

业务数据类型划分:
从需要排⾏的数据类型上划分,主要分为:
单类型数据排⾏榜: 是指需要排行的主体不需要区分类型,例如,所有⽤户积分排⾏,所有公贡献值排⾏,所有游戏热度排⾏等
多类型(复合类型)数据排行榜: 是指需要排行的主体在排行中要求有类型上的区分,例如:竞技类游戏热度排⾏、体育类游戏热度排⾏、MOBA类游戏操作性排⾏、⻆⾊/ 回合 / 卡牌三类游戏热度排⾏等

展示唯度划分:
从榜单的最终展示唯度上划分,主要分为:
单唯度: 是指选择展示的排行榜就是基于⼀个唯度下的排行,例如前面提到的游戏操作性排行榜,就仅展示所有MOBA 类游戏按操作性的评分排行
多唯度:是指选择展示的排行榜还有多种唯度供⽤户选择,仍然以前面的 游戏排行为例,唯度除了操作性,还有音效评分排行,难易度评分排行,画面评分排行等。

展示数据量划分:
从需要展示的数据量上划分,主要分为:
topN 数据:只要求展示 topN 条排行纪录,例如:最火 游戏 top20
全量数据:要求展示所有数

HyperLogLog

使用 Redis 统计集合的基数一般有三种方法,分别是使用 Redis 的 HashMap,BitMap 和 HyperLogLog。前两个数据结构在集合的数量级增长时,所消耗的内存会大大增加,但是 HyperLogLog 则不会。

常用命令

连接redis常用命令
菜鸟教程

Redis在项目中的地位及使用场景剖析

https://blog.csdn.net/ABCDABCD321123/article/details/111029159

Redis为什么这么快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

持久化

rdb方式(存储的是快照数据,适合做冷备,恢复数据更快)

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。

在这里插入图片描述
触发rdb方式:
(1)save: 同步保存,阻塞式保存,将当前 Redis的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘。
(2)bgsave: 异步保存,开启新的线程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。
(3)自动触发: save m n,#表示m 秒内如果至少有 n个 key 的值变化,则保存save
(4)其他方式:
除了save m n以外,还有一些其他情况会触发bgsave:
  在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行 bgsave 命令,并将rdb文件发送给从节点;
  执行shutdown命令时,自动执行rdb持久化,

RDB 的优势和劣势

①、优势

(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。

(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

②、劣势
在快照持久化期间修改的数据不会被保存,可能丢失数据。

AOF方式(更好的保证数据不丢失)

AOF 其实就是将客户端每一次操作记录追加到指定的aof(日志)文件中。
重写(bgrewriteaof命令) :为了解决AOF文件体积膨胀的问题,Redis使用子进程进行AOF重写功能(根据数据库状态对aof文件进行精简),子进程子进程与线程的区别,这里主要是因为可以在不用锁的情况下也能实现数据安全性) 在进行AOF重写期间,服务器主进程还可以继续处理新的命令请求,一方面继续将新的命令操作追加到旧的aof文件,另一方面会将新的命令放入重写缓存区,等到子进程将aof重写完成后,再将重写缓存区的aof进行叠加,最后替换旧的aof文件。
在这里插入图片描述
触发aof方式:

(1)每修改同步always:同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好。
(2)每秒同步everysec:异步操作,每秒记录,如果一秒内宕机,有数据丢失。
(3)不同no:从不同步

aof 的优势和劣势

①、优势
(1)AOF可以更好的保证数据的完整性,最多丢失1s的数据。
(2)AOF非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据 。

②、劣势
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大。
(2)AOF运行效率比rdb低。
在这里插入图片描述

aof数据恢复实例

Redis事务

Redis 事务的执行并不是原子性的。

**Redis事务的三个阶段:**开始事务、命令入队、执行事务

为什么Redis不支持回滚:
失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
Redis主要认为失败都是使用者造成的所以就没有回滚操作,为了保持内部可以保持简单且快速,就不支持回滚。

在Redis中除了没有原子性外,Redis对事务也没有隔离级别的概念,所以就不会产生我们使用关系型数据库需要关注的脏读,幻读,重复读的问题。

Redis的watch机制实现乐观锁
虽说 Redis不支持直接回滚,但我们可以通过 Redis提供的监控命令(watch)来实现回滚。
**watch:**乐观锁,如果监控的值发生变化,则提交事务时会失败。

redis集群

主从架构

特点:
(1)主节点Master可读、可写。
(2)从节点Slave只读。(read-only)

主从同步原理分析

Redis的主从结构可以采用一主多从结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。
全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:

  • 从服务器连接主服务器,发送SYNC命令;
  • 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
  • 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
  • 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
  • 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
  • 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令。

增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
在这里插入图片描述
过程原理

  1. 当从库和主库建立MS关系后,会向主数据库发送SYNC命令
  2. 主库接收到SYNC命令后会开始在后台保存快照(RDB持久化过程),并将期间接收到的写命令缓存起来
  3. 当快照完成后,主Redis会将快照文件和所有缓存的写命令发送给从Redis
  4. 从Redis接收到后,会载入快照文件并且执行收到的缓存的命令

之后,主Redis每当接收到写命令时就会将命令发送从Redis,从而保证数据的一致

https://www.cnblogs.com/krock/p/14283469.html
https://www.cnblogs.com/javazhiyin/p/13839357.html

配置

https://www.cnblogs.com/vieta/p/11192137.html

Sentinel哨兵模式

主从模式的缺陷: 当主节点宕机了,整个集群就没有可写的节点了。
哨兵的任务:

  • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API
    向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作,
    它会进行选举,将其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

哨兵工作原理分析

在这里插入图片描述
(1)Sentinel可以监控任意多个Master和该Master下的Slaves。(即多个主从模式)

(2)同一个哨兵下的、不同主从模型,彼此之间相互独立。

(3)Sentinel会不断检查Master和Slaves是否正常。

1):每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。

2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值(这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒), 则这个实例会被 Sentinel 标记为主观下线。

3):如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。

4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 。

5):在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令 。

6):当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 。

7):若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
8): 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

配置

https://www.cnblogs.com/vieta/p/11192137.html
在这里插入图片描述

哨兵(至少3个)为什么是奇数?
防止哨兵投票选举master出现票数相同的情况。

雪崩、穿透、击穿

https://www.zhihu.com/question/421946305/answer/1482420252.
雪崩是大面积的key缓存失效;
解决方案
(1)随机设置key失效时间。
(2)不设置过期时间
(3)跑定时任务,在缓存失效前刷进新的缓存
(4)也是像解决缓存击穿一样加锁排队

穿透是redis里不存在这个缓存key。
解决方案
(1)对不存在的数据缓存到redis中,设置key,value值为null。
(2)拉黑该IP地址。
(3)对参数进行校验,不合法参数进行拦截。
(4)布隆过滤器

击穿是redis某一个热点key突然失效,最终的受害者都是数据库。
解决方案:
1、使用锁,单机用synchronized,lock等,分布式用分布式锁(在第一个查询数据的请求上使用一个互斥锁来锁住它 其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后将数据放到redis缓存起来。后面的线程进来发现已经有缓存了,就直接走缓存 。.)
2、缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存
3、在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作

未雨绸缪:将redis、MySQL等搭建成高可用的集群,防止单点(主从同步、哨兵模式)、消息中间件方式。
亡羊补牢:服务中进行限流 + 降级,防止MySQL被打崩溃。
重振旗鼓:Redis 持久化 RDB+AOF,宕机重启,自动从磁盘上加载数据,快速恢复缓存数据。

redis内存淘汰机制

定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。

惰性过期: 只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。

定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)
https://www.cnblogs.com/javazhiyin/p/13839357.html
LRU算法
https://www.cnblogs.com/heyanan/p/12574894.html

redis和数据库一致性问题

不同的业务场景(并发量、一致性要求都不是很高的情况、最终一致性、强一致性)选取不同的一致性策略。
单库、多库(分库分表)、多库读写分离(数据库集群、需考虑DB主从一致性)、数据库+缓存
https://blog.kido.site/2018/11/24/db-and-cache-preface/

分布式环境下(单机就不用说了)非常容易出现缓存和数据库间的数据一致性问题,如果你的项目对缓存的要求是强一致性的,那么请不要使用缓存。我们只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括 合适的缓存更新策略,更新数据库后要及时更新缓存、缓存失败时增加重试机制例如MQ模式的消息队列

常用方案:

1、延时双删
缓存超时设置,这样最差的情况就是在超时时间内数据存在不一致。
延时:为了保证将缓存的旧数据删除。
https://www.freebytes.net/it/java/redis-db-same.html
@Transactional
public void update(){
deleteCache();//删除缓存
updateDb();//更新数据库
//下面的代码最好使用异步执行
Thread.sleep(1000);//等待1秒
deleteCache();//删除缓存
}

2、异步更新缓存(基于订阅binlog的同步机制、canal框架)
https://zhuanlan.zhihu.com/p/158383468
技术整体思路:
MySQL binlog增量订阅消费+消息队列+增量数据更新到redis

读Redis:热数据基本都在Redis
写MySQL:增删改都是操作MySQL
更新Redis数据:MySQ的数据操作binlog,来更新到Redis

3、串行化(强一致性)

redis分布式锁(底层:setnx+expire)

Redis 锁的实质便是让并行的多个线程在Redis 内部以串行的方式执行。
实现:使setnx 和 expire两条命令同时成功,利用事物实现这两条命令的原子性。
Redisson(封装了setnx+expire)实现redis分布式锁:获得锁的线程可以开启一个定时任务,当前线程如果还没有执行完业务逻辑,则令其超时时间延长,如果线程执行完业务逻辑后,则锁会被那个线程释放。
在这里插入图片描述

redis分布式锁参考1
redis分布式锁参考2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值