Redis 入门详解

redis 是分布式的内存数据库
redis 是单进程处理客服端的请求
redis 是通过 epoll 包装(epoll 是以 linux 为内核) 在处理大量文件下的多路 IO 复用
redis 默认装 16 个库
redis 索引从 0 开始
redis 端口 6379
redis 中 1 表示成功,存在 0 表示失败,不存在
dd 删除文件中行



redis 常用命令

vim fileName 修改文件 i 插入 按(esc) 保存并退出,
    输入(:)
        再输入 wq(write quit) 保存退出
        正常退出(q)
        ! 强制退出

clear 清除当前界面
ls -li 显示当前文件夹
ps -ef|grep redis(lsof -i :6379) 查看 redis 是否启动
ping 当 redis 连接成功时, 输入该命令返回 pong 说明连接正常
set key value 存储数据
get key 获取值
select number 切换数据库 (Set the number of databases. The default database is DB 0, you can select a different one on a per-connection basis using SELECT <dbid> where dbid is a number between 0 and 'databases'-1)
dbsize 查看当前数据库的 key 的数量
keys * 查看所有 key
keys k? 带占位符的查找
flushdb 清除当前库的 key
flushall 清除所有库的 key
redis-cli -p 6379 shutdown 停止 redis 服务
config get requirepass 查看密码
config get dir 当前启动 redis 的路径(可变的)
auth password 登录密码
rm -f fileName 删除文件




redis 数据类型

redis 的五大数据类型
    redis key 键值
        exists key 判断数据库中是否有该 key
        move key db 移动某个 key 到指定的库
        expire key 秒 为给定的 key 设定过期时间
        ttl key 查看 key 还有多久过期 -1 表示永不过期, -2 表示已经过期
        type key 查看 key 的类型
        del key 删除 key
    String (字符串)单 key 单 value 是二进制安全的, 可以包含任何数据
        append key value 给该 key 拼接 value
        strlen key 获取 key 对应的 value 的长度
        incr key 对是数字的 value 的 key 加 1
        decr key 对是数字的 value 的 key 减 1
        incrby key number 对是数字的 value 的 key 加 number
        decrby key number 对是数字的 value 的 key 减 number
        getrange 截取 number1 到 number2 的值(包含 number2) number2 为 -1 时 表示截取 number1 到所有
        setrange key number 设置从 number 开始的值
        setex key 秒 value 设置 key 可以存活的时间
        setnx key value 当 key 不存在就保存到数据库中
        mset/mget m 表示 more 同时 设置/获取 多个 key
        msetnx 当多个都不存在时,set 多个 key
    Hash (哈希, 类似 java 的 Map)是一个键值对集合, 特别适合用于存储对象(类似 Map<String, Object>)
        kv 模式不变, v 是一个键值对 (c存值 hset key key value) map(mao)
        hset/hget/hmset/hmget/hgetall/hdel 存/取/存多个/取多个/取所有/删除
        hlen key 获取长度
        hexists key1 key2 判断 key1 里面是否包含 key2
        hkeys/hvals key 获取 key 的 key 的集合, 获取 key 的 value 集合
        hincrby key1 key2 number 对 Hash 里面, key 的 value 的数字的进行加
        hincrbyfloat key1 key2 number 对 Hash 里面, key 的 value 的小数的进行加
        hsetnx key1 key2 if not 不存在就 保存进去
    List (列表) 是简单的字符串列表, 底层实际是链表, 单值多value
        lpush key 存 list 类型的 key, 从左边开始存 , 取得时候是正这进反着出
        rpush key 存 list 类型的 key, 从右边开始存 , 取得时候是怎么进就怎么出
        lrange key 0 -1 截取 list 中的值
        lpop/rpop 弹出 key 中值, lpop 后进先出, rpop 先进先出
        lindex 按索引取值
        llen 获取 list 的长度
        lrem key 删除 N 个 value
        ltrim key 截取从 index 开始到 index 结束范围的值之后再赋值给 key
        rpoplpush key1 key2 将 key1 最下面的值放在 key2 的最上面
        lset key index value 替换指定下标的值
        linsert key befor/after 值1 值2 在指定的值 before/after 添加值
    Set (集合) 是 String 类型的无序集合, 他是通过 HashTable 实现的, 无序无重复, 单值多value
        sadd/smembers/sismember key 添加/获取/是否包含某个值
        scard 获取集合元素的个数
        srem key value 删除集合中的值
        srandmembers key number 在集合中随机去 number 个值
        spop key 随机去栈一个
        smove key1 key2 value 将key1 中 value 移除到 key2 中
        数学集合类
        差集 sdiff key1 key2 取 key1 与 key2 中的差集,只去 key1 中
        交集 sinter key1 key2 取 key1 与 key2 中都有的值
        并集 sunion key1 key2 取 key1 与 key2 中去掉重复的所有的值
    Zset (sorted set: 有序集合) 也是String 类型元素的集合, 不允许重复, 不同的是每个元素都会关联一个 double 类型的分数
        sorted set 和 set 的区别, 在 set 的基础上, 加一个 score 值
        之前的 Set 是 key1 v1 v2 v3
        现在的 zset 是 k1 score1 v1 score2 v2
        zadd key score1 value1 score2 value2 score3 value3
        zrange key 0 -1 获取全部 value
        zrange key 0 -1 withscore 获取  value score
        zrangebyscore key 开始score1 结束 score2 获取在多少分数之间的 value score1<= <=scroe2
        zrangebyscore key 开始score 结束 (score  ( 不包含,小于 score1<= <scroe2
        zrangebyscore key 开始(score 结束 (score score1< <scroe2
        zrangebyscore key 开始score1 结束 score2 limit 2 2 从第二个截取两个
        zrem key value 移除指定的 score 下对应的 value,作用是删除元素
        zcard key 元素个数
        zcount key score1 score2 区间的个数(包含score1 score2)
        zscore key value 获取对应 value 的 score
        zrevrank key value 作用是倒序下取得下标值
        zrevrange key 0 -1 倒序获取所有 value
        zrevrangebyscore key 结束分数 开始分数


redis 配置文件 redis.conf 参数说明

redis.conf 配置项说明如下:
1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
  daemonize no
2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
  pidfile /var/run/redis.pid
3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
  port 6379
4. 绑定的主机地址
  bind 127.0.0.1
5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
  timeout 300
6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
  loglevel verbose
7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
  logfile stdout
8. 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
  databases 16
9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
  save <seconds> <changes>
  Redis默认配置文件中提供了三个条件:
  save 900 1
  save 300 10
  save 60 10000
  分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
 
10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
  rdbcompression yes
11. 指定本地数据库文件名,默认值为dump.rdb
  dbfilename dump.rdb
12. 指定本地数据库存放目录
  dir ./
13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
  slaveof <masterip> <masterport>
14. 当master服务设置了密码保护时,slav服务连接master的密码
  masterauth <master-password>
15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
  requirepass foobared
16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
  maxclients 128
17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
  maxmemory <bytes>
18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
  appendonly no
19. 指定更新日志文件名,默认为appendonly.aof
   appendfilename appendonly.aof
20. 指定更新日志条件,共有3个可选值:
  no:表示等操作系统进行数据缓存同步到磁盘(快)
  always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
  everysec:表示每秒同步一次(折衷,默认值)
  appendfsync everysec
 
21. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
   vm-enabled no
22. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
   vm-swap-file /tmp/redis.swap
23. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
   vm-max-memory 0
24. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
   vm-page-size 32
25. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
   vm-pages 134217728
26. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
   vm-max-threads 4
27. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
  glueoutputbuf yes
28. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
  hash-max-zipmap-entries 64
  hash-max-zipmap-value 512
29. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
  activerehashing yes
30. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
  include /path/to/local.conf
    util 单位
        配置大小单位, 开头定义了一些基本的度量单位, 只支持 bytes, 不支持 bit
        对大小写不敏感
    include 包含
        和我们的 Struts2 配置文件类似, 可以通过 includes 包含, redis.conf 可以作为总闸, 包含其他
        include /path/to/local/local.conf
    general 通用
        tcp-backlog 默认是 511, 是一个连接队列的连接池
            s设置 tcp 的 backlog, backlog 其实就是一个连接队列,
            backlog 队列总和 = 未完成三次握手队列 + 已完成三尺握手队列.
            在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题. 注意 Linux 内核会将这个值减小到/proc/sys/net/core/somaxconn 的值
            所以需要确认增大 somaxconn 和 tcp_max_syn_backlog 两个值来表达到想要的结果
    limits 限制
        Maxmemory-pollcy 缓存过期清洁策略, 当 redis maxmemory 达到的时候 (五种)
            volatile-lru: (lru 最进最少使用) 使用lru 算法移除 key, 只对设置了过期时间的 key
            allkeys-lru 使用 lru 算法移除 key
            volatile-random (random 随机) 在过期集合中移除随机的 key, 只对设置了过期时间的 key
            allkeys-random 移除随机的 key
            volatile-ttl(ttl 有限时间内) 移除哪些 ttl 值最小的 key , 即那些最近要过期的 key
            noeviction: 永不过期, 不进行移除, 针对写操作, 只是返回报错信息

redis 持久化

    RDB(Redis Database): 在指定的时间间隔内将内存中的数据集快照写入磁盘
                 也就是讲的 Snapshot 快照, 它恢复时是将快照文件直接读到内存里
        Redis 会单独创建 (fork) 一个子进程来进行持久化, 会先将数据写入到一个临时文件中,
        待持久化过程都结束了, 再用这个临时文件替换上次持久化好的文件.整个过程中
        主进程不会进行任何 io 操作, 这就确保了极高的性能, 如果需要进行大规模数据的恢复
        ,且对数据恢复的完整性不是非常敏感, 那么 RDB 方式要比 AOF 方式更加的高效
        RDB 的缺点是最后一次持久化后的数据可能丢失
        Fork: Fork 的作用是复制一个与当前进程一样的进程, 新进程的所有数据(变量, 环境变量, 程序计数器等)
        数值都是和原进程一致, 但是是一个全新的进程, 并作为原进程的子进程
        Rdb 保存的是 dump.rdb 文件
        触发 Rdb 的三个条件 redis.conf 配置文件默认设置,命令: save <seconds> <changes> 禁用 save ""
            900 s 内有一个 key 修改(新增,删除,修改)了一次内
            300 s 内有一个 key 修改了十次内
            60 s 内有一个 key 修改了一万次内
            redis 不会马上生成 dump.rdb 文件, 而是超过这个时间后才会生成, 或者是对 key 的改变超出了设定的范围会立即生成
            RDB 是整个内存的压缩过得 Snopshot, RDB 的数据结构, 可以配置复合的快照触发条件
            默认:
                1分钟内改了1万次
                5分钟改了10万次
                15分钟改了1次
            如何触发 RDB 快照:
                RDB 迅速备份: 在进行了数据操作后需要立即备份数据生成 dump.rdb 文件,执行 save bgsave flushall命令
                    配置文件中默认的快照配置, 冷拷贝后重新使用, 多台机器
                    save: 只管保存其他不管, 全部阻塞
                    bgsave: Redis 会在后台异步进行快照操作
                    快照同时还可以响应客户端请求, 可以通过 lastsave 命令来获取最后一次成功执行快照的时间
                    flushall 也会生成 dump.rdb 文件, 但是是空的, 无意义
                    Stop-write-on-bgsave-error 默认配置 yes: 后天保存数据出错就停止写入
                                        no: 表示不在乎数据一致性或者有其他的手段发现和控制
                    rdbcompression 默认 yes: 对于存储到磁盘中的快照, 可以设置是否进行压缩存储.如果是, redis 会采用
                        LZF 算法进行压缩, 如果不想消耗 CPU 来进行压缩的话, 可以设置为 no 关闭此功能
                    rdbchecksum: 在存储快照后, 还可以让 redis 使用 CRC64 算法来进行校验, 但是这样会增加大约 10% 的性能消耗,
                        如果希望获取到最大的性能提升, 可以关闭
                    dbfilename dump.rdb 指定本地数据库的文件名
                    dir 获取 redis 运行的路径
                如何恢复: 将备份文件(dump.rdb) 移动到 redis 安装目录并启动服务即可, 它会自动将备份文件加载到内存中
        优势: 适合大规模的数据恢复, 对数据完整性和一致性要求不高
        劣势: 在一定间隔时间做一次备份, 如果 redis 意外 down 掉的话, 就会丢失最后一次快照后的所有修改
              fork 的时候, 内存中的数据被克隆了一份, 大致2倍的膨胀性需要考虑
        如何停止: 动态所有停止 rdb 保存规则的方法: redis-cli config set save ""



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

        在统一路径下, 当同时存在 .rdb 和 .aof 文件时, 会先加载 .aof 文件, 当 .rdb/.aof 文件损坏时
        redis-check-aof --fix .aof/.rdb 文件, 可以修复文件

        appendfsync
            Always: 同步持久化, 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
            Everysec: 出厂默认推荐, 一步操作, 每秒记录 如果一秒内宕机(死机),有数据丢失
            No
        Rewrite(重写)AOF 采用文件追加方式, 文件会越来越大为避免出现此种情况, 新增了重写
            机制, 当 AOF 文件的大小超过设定的大小时, Redis 会启动 AOF 文件的内容压缩,
            只保留可以恢复数据的最小指令集, 可以是用命令 bgrewriteaof

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

            触发机制: Redis 会记录上次重写时 aof 文件的大小, 默认配置是当 aof 文件大小是
            上次 rewrite 后大小的一倍且文件大于 64M 时触发
            
            No-appendfsync-on-rewrites: 重写时是否可以运用 Appendfsync, 用默认 no 即可, 保证数据安全性
            Auto-aof-rewrite-min-size: 设置重写的基准值
            Auto-aof-rewrite-percentage: 设置重写的基准值
        
        优势:
            每秒同步: appendfsync always 同步持久化, 每次发生数据变更会被记录到磁盘, 性能较差但数据完整性比较好
            每修改同步: appendfsync everysec 一步操作, 每秒记录, 如果一秒宕机,有数据丢失
            不同步: appendfsync no 从不同步

        劣势:
            相同数据集的数据而言 aof 文件远大于 rdb 文件, 恢复速度慢于 rdb
            Aof 运行效率要慢于 rdb, 每秒同步策略效率较好, 不同步效率和 rdb 相同
        

Redis 事物

        可以一次执行多个命令, 本质是一组命令的集合. 一个事物中的所有命令都会序列化,按顺序的串行化执行而不会被其他命令插入, 不许加塞. 一个队列中, 一次性, 顺序性, 排他性的执行一系列命令


        常用命令
        multi 开启事物, 返回 ok
        exec 执行事物, 返回结果
        discard 放弃事物
        全体连坐表示提交事物的时候有一个错了其他的也不会执行(在执行时就报错没有加入 queued 队列中)
        冤头债主错了报错, 没错的继续执行(执行时并没有报错并加入到 queued 队列中)
        watch 监控(类似乐观锁): 监视一个或多个 key 如果在事物提交之前 这个或多个 key 被其他命令所修改, 那么事物将被打断
            悲观锁: 就是很悲观, 每次去拿数据的时候都会认为别人会修改, 所以每次在拿数据的时候都会上锁
                这样别人想拿这个数据就会 block 知道他拿锁.传统的关系型数据库里边就用到了很多这种
                锁机制.比如: 行锁, 表锁等, 读锁, 解锁等, 都是在操作之前先上锁(数据库备份的时候可用合适)
            乐观锁: 就是很乐观, 每次去拿数据都认为别人不会修改, 所以不上锁, 但是在跟新的时候会判断一下在此
                期间别人有没有去更新这个数据, 可以使用版本号等机制. 乐观锁多用于读的应用类型, 这样可以
                提高吞吐量
                乐观锁策略: 提交版本必须大于记录当前版本才能执行更新
            cas(check and set):  先检查再 set

            1. 初始化信用卡可用余额和欠额
               无加塞篡改, 先监控再开启 multi(就是自己在操作的时候之前没有其他人对其操作)
               保证两笔金额变动在同一个事物内
            2. 有加塞篡改, 就是在自己操作数据之前, 别人在自己之前进行了操作, 当自己 exec
                提交事物的时候不能成功, 需要重新获取别人修改后的数据重新操作

        unwatch(对所有 key 取消监视): 就是在 watch 的时候知道自己 watch 的 key 被修改了, 那么执行 unwatch 放弃监视
             重新在缓存中获取最初的数据重新 watch, 再对其重新 watch, 直到对其操作的时候
             没人对其修改再执行 exec
        一旦执行了 exec 之前对 key 加的监控锁都会被取消

        redis 事物三阶段
            开启: 以 multi 开启一个事物
            入队: 将多个命令入队到事物中, 接到这些命令
                  并不会立即执行, 而是放到等待执行的事物
                  队列里面
            执行: 由 exec 命令触发事物
        redis 事物三特性:
            单独的隔离操作: 事物中的所有命令都会序列化 按顺序执行, 事物在执行的过程中, 不会被其他的客户端发送多来
                命令请求打断
            没有隔离级别的概念: 队列中的命令没有提交之前都不会实际的执行, 因为事物提交之前任何指令都不会被实际执行
                也就不存在"事物内的查询要看到事物里的更新, 再事物外查询不能看到" 这个让人万分头痛的问题
                不保证原子性: redis 同一个事物中如果有一条命令执行失败, 气候的命令仍然会被执行, 没有回滚

redis 的发布订阅: 进程间的一种消息模式: 发送者(pub)发送消息, 订阅者(sub)接收消息.
          订阅/发布消息图
          命令:
            subscribe 消息1 消息2 .. 订阅
            publish 消息1 内容 发布消息
            pubscribe new* 使用通配符 订阅
        表锁: 并发性极差, 一致性很好

redis 主从复制

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

    
        读写分离, 容灾恢复
        1. 配从(库)不配主(库)
        2. 从库配置: slaveof 主库 IP 主库端口: 每次与 master断开之后, 都需要重新连接, 除非你配置进 redis.conf配置文件中
        
        一主二从:
            info replication
            slaveof ip port 从机配置到主机
        薪火相传: 上一个 Slaver 可以是下一个 slaver 的 master, slave 同样可以接收其他
              slaves 的连接和同步骑牛, 那么该 slave 作为了链条中下一个 master,
              可以有效减轻 master 的写力
              中途变更转向会清楚之前的数据, 重新拷贝最新的
            
        反客为主: 使当前数据库停止与其他数据库的同步, 转成主数据库
            手动命令从机转变为主机 slaveof no one

        复制的原理: slave 启动成功连接到 master 后会发送一个 sync 命令
                master 街道命令启动后台的存盘进程, 同时手机所有接收到的用于修改数据集命令
                在后台进程执行完毕之后, master 将传送整个数据文件到 slave, 以完成一次同步
                全量复制: 第一次 slave 会接收主数据库的所有数据,将其存盘并加载到内存中
                增量复制: 每次 master 将新数据一次传给 slave 完成同步
                但是只要是重新连接 master, 一次完成同步(全量复制)将被自动执行
        哨兵模式(sentinel): 反可为主的自动版, 能够后台监视主机是否故障, 如果故障了根据
                    根据投票数自动将从库转为主库
            使用步骤: 在 redis 目录下 创建 sentinel.conf 文件 touch sentinel.conf
                  在 sentinel.conf 文件中添加 sentinel monitor host6379(被监控数据库名字) 127.0.0.1 6379 1
                  1 表示, 主机挂掉后 slave 投票看让谁接替成为主机,得到票数多成为主机
                  启动哨兵: redis-sentinel /myredis/sentinel.conf

            




redis 获取常见数据类型操作命令: http://redisdoc.com/



























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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值