Redis-10大数据类型理解与测试
Redis10大数据类型
注:参考阳哥redis笔记,仅做学习提升之用
我要打10个
1.redis字符串(String)
-
string是redis最基本的类型,一个key对应一个value。
-
string类型是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象 。
-
string类型是Redis最基本的数据类型,一个redis中字符串value最多可以是512M
2.redis列表(List)
-
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
-
它的底层实际是个双端链表,最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
3.redis哈希表(Hash)
-
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
-
Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)
4.redis集合(Set)
-
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,集合对象的编码可以是 intset 或者 hashtable。
-
Redis 中Set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
-
集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)
5.redis有序集合(ZSet)
-
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
-
不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。
-
zset的成员是唯一的,但分数(score)却可以重复。
-
zset集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 2^32 - 1
6.redis地理空间(GEO)
Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,包括:
添加地理位置的坐标。
获取地理位置的坐标。
计算两个位置之间的距离。
根据用户给定的经纬度坐标来获取指定范围内的地理位置集合
7.redis基数统计(HyperLogLog)
- HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且是很小的。
- 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
- 但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
8.redis位图(bitmap)
由0和1状态表现的二进制位的bit数组
9.redis位域(bitfield)
- 通过bitfield命令可以一次性操作多个比特位域(指的是连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果。
- 说白了就是通过bitfield命令我们可以一次性对多个比特位域进行操作。
10.redis流(Stream)
- Redis Stream 是 Redis 5.0 版本新增加的数据结构。
- Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
- 简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。
- 而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失
官网地址
Redis 键(key)
常用
案例
keys *
查看当前库所有的keyexists key
判断某个key是否存在type key
查看你的key是什么类型del key
删除指定的key数据unlink key
非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的删除会在后续异步中操作。ttl key
查看还有多少秒过期,-1表示永不过期,-2表示已过期expire key
秒钟 为给定的key设置过期时间move key dbindex【0-15】
将当前数据库的 key移动到给定的数据库 db 当中select dbindex
切换数据库【0-15】,默认为0dbsize
查看当前数据库key的数量flushdb
清空当前库flushall
通杀全部库
数据类型命令及落地使用
帮助命令
1.Redis字符串(String)
单值单value
1)set 、get 、ttl、keepttl
2)mset、mget、msetnx
mset:同时设置一个或多个 key-value 对。
mget:获取所有(一个或多个)给定 key 的值。
msetnx:同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
127.0.0.1:6379> del lbj kd curry
(integer) 3
127.0.0.1:6379> msetnx lbj 1 kd 2 curry 3
(integer) 1
127.0.0.1:6379> msetnx lbj 1 kd 2 curry 3
(integer) 0
3)getrange
getrange:获取指定区间范围内的值,类似between…and的关系
从零到负一表示全部
setrange设置指定区间范围内的值,格式是setrange key值 具体值
127.0.0.1:6379> set key 123456
OK
127.0.0.1:6379> getrange key 0 -1
"123456"
127.0.0.1:6379> getrange key 0 2
"123"
4)INCR 、INCRBY 、DECR 、DECRBY
一定要是数字才能进行加减
递增数字:INCR key
增加指定的整数:INCRBY key increment
递减数值:DECR key
减少指定的整数:DECRBY key decrement
5)strlen、append
获取字符串长度和内容追加
127.0.0.1:6379> strlen curry
(integer) 1
127.0.0.1:6379> append curry 91
(integer) 3
127.0.0.1:6379> strlen curry
(integer) 3
127.0.0.1:6379> get curry
"391"
127.0.0.1:6379>
127.0.0.1:6379> set lock pay ex 10 nx
OK
127.0.0.1:6379> get lock
"pay"
127.0.0.1:6379> set lock order ex 10 nx
OK
127.0.0.1:6379> set lock pay ex 10 nx
(nil)
127.0.0.1:6379> set lock pay ex 10 nx
OK
127.0.0.1:6379> get lock
"pay"
127.0.0.1:6379> get lbj
"1"
127.0.0.1:6379> getset lbj 23
"1"
127.0.0.1:6379> get lbj
"23"
2.Redis列表(List)
单key多value
1)lpush/rpush/lrange
127.0.0.1:6379> lpush list 1
(integer) 1
127.0.0.1:6379> rpush list 23
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "23"
2)lindex、llen
lindex:按照索引下标获得元素(从上到下)
llen:获取列表中元素的个数
127.0.0.1:6379> lindex list 1
"23"
127.0.0.1:6379> llen list
(integer) 2
3)lrem key 数字N 给定值v1 ,删除N个值等于v1的元素
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "23"
127.0.0.1:6379> lrem list 1 1
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "23"
3)Itrim
Itrim: key 开始index 结束index,截取指定范围的值后再赋值给key
127.0.0.1:6379> lrange list 0 -1
1) "1"
2) "23"
127.0.0.1:6379> ltrim list 1 1
OK
127.0.0.1:6379> lrange list 0 -1
1) "23"
4)rpoplpush
rpoplpush 源列表 目的列表
移除列表的最后一个元素,并将该元素添加到另一个列表并返回
127.0.0.1:6379> lpush list1 1 2 3
(integer) 3
127.0.0.1:6379> lpush list2 11 12 13
(integer) 3
127.0.0.1:6379> rpoplpush list1 list2
"1"
127.0.0.1:6379> lrange list1 0 -1
1) "3"
2) "2"
127.0.0.1:6379> lrange list2 0 -1
1) "1"
2) "13"
3) "12"
4) "11"
5)lset
lset key index value
替换指定index的位置的元素
127.0.0.1:6379> lrange list2 0 -1
1) "1"
2) "13"
3) "12"
4) "11"
127.0.0.1:6379> lset list2 2 lbj
OK
127.0.0.1:6379> lrange list2 0 -1
1) "1"
2) "13"
3) "lbj"
4) "11"
127.0.0.1:6379>
6)linsert
linsert key before/after 已有值 插入的新值
在list某个已有值的前后再添加具体值
127.0.0.1:6379> lpush list3 1 2 3 a b c l j
(integer) 8
127.0.0.1:6379> lrange list3 0 -1
1) "j"
2) "l"
3) "c"
4) "b"
5) "a"
6) "3"
7) "2"
8) "1"
127.0.0.1:6379> linsert list3 after 3 lbj
(integer) 9
127.0.0.1:6379> lrange list3 0 -1
1) "j"
2) "l"
3) "c"
4) "b"
5) "a"
6) "3"
7) "lbj"
8) "2"
9) "1"
127.0.0.1:6379> linsert list3 before 3 kd
(integer) 10
127.0.0.1:6379> lrange list3 0 -1
1) "j"
2) "l"
3) "c"
4) "b"
5) "a"
6) "kd"
7) "3"
8) "lbj"
9) "2"
10) "1"
127.0.0.1:6379>
7)应用场景
微信公众号订阅的信息
大V作者李永乐老师和CSDN发布了文章分别是 11 和 22
阳哥关注了他们两个,只要他们发布了新文章,就会安装进我的List
lpush likearticle:阳哥id 11 22
查看阳哥自己的号订阅的全部文章,类似分页,下面0~10就是一次显示10条
lrange likearticle:阳哥id 0 9
3.Redis哈希(Hash)
KV模式不变,但V是一个键值对Map<String,Map<Object,object>>
1)hset/hget/hmset/hmget/hgetall/hdel
127.0.0.1:6379> hset hash1 k1 v1
(integer) 1
127.0.0.1:6379> hget hash1 k1
"v1"
127.0.0.1:6379> hmset hash2 id 23 name LBJ age 39
OK
127.0.0.1:6379> hmget hash2 id name age
1) "23"
2) "LBJ"
3) "39"
127.0.0.1:6379> hgetall hash1
1) "k1"
2) "v1"
127.0.0.1:6379> hgetall hash2
1) "id"
2) "23"
3) "name"
4) "LBJ"
5) "age"
6) "39"
127.0.0.1:6379>
127.0.0.1:6379> hdel hash1
(error) ERR wrong number of arguments for 'hdel' command
127.0.0.1:6379> hdel hash1 k1
(integer) 1
127.0.0.1:6379> hget hash1
(error) ERR wrong number of arguments for 'hget' command
127.0.0.1:6379> hgetall hash1
(empty array)
2)hlen
获取某个key内的全部数量
127.0.0.1:6379> hlen hash2
(integer) 3
127.0.0.1:6379>
3)hexists key
在key里面的某个值的key
127.0.0.1:6379> hexists hash2 id
(integer) 1
127.0.0.1:6379>
4)hkeys/hvals
127.0.0.1:6379> hset hash1 lbj 23
(integer) 1
127.0.0.1:6379> hgetall hash1
1) "lbj"
2) "23"
127.0.0.1:6379> hkeys hash1
1) "lbj"
127.0.0.1:6379> hvals hash1
1) "23"
5)hincrby/hincrbyfloat
127.0.0.1:6379> hset hash1 lbj 23
(integer) 1
127.0.0.1:6379> hgetall hash1
1) "lbj"
2) "23"
127.0.0.1:6379> hkeys hash1
1) "lbj"
127.0.0.1:6379> hvals hash1
1) "23"
127.0.0.1:6379> hget hash1 lbj
"23"
127.0.0.1:6379> hincrby hash1 lbj 16
(integer) 39
127.0.0.1:6379> hincrbyfloat hash1 lbj 0.7
"39.7"
#只对数字有效
127.0.0.1:6379> hset hash1 kd a
(integer) 1
127.0.0.1:6379> hincrby hash1 kd 11
(error) ERR hash value is not an integer
6)hsetnx
不存在赋值,存在了无效。
127.0.0.1:6379> hsetnx hash1 curry 30
(integer) 1
127.0.0.1:6379> hsetnx hash1 curry 11
(integer) 0
127.0.0.1:6379> hget hash1 curry
"30"
应用场景:JD购物车早期 设计目前不再采用,当前小中厂可用
4.Redis集合(set集合)
1)SADD、SMEMBERS、SISMEMBER、SREM、scard
SADD key member [member ...]
:添加元素
SMEMBERS key
:遍历集合中的所有元素
SISMEMBER key member
:判断元素是否在集合中
SREM key member[memberscard,……]
:删除元素
scard
:获取集合里面的元素个数
127.0.0.1:6379> sadd set1 lbj kd curry
(integer) 3
127.0.0.1:6379> smembers set1
1) "curry"
2) "lbj"
3) "kd"
127.0.0.1:6379> sismember set1 lbj
(integer) 1
127.0.0.1:6379> srem set1 curry
(integer) 1
127.0.0.1:6379> smembers set1
1) "lbj"
2) "kd"
127.0.0.1:6379> scard set1
(integer) 2
127.0.0.1:6379>
2)SRANDMEMBER key
从集合中随机展现设置的数字个数元素,元素不删除
- 从set集合里面随机取出2个
- 如果超过最大数量就全部取出,
- 如果写的值是负数,比如-3 ,表示需要取出3个,但是可能会有重复值。
127.0.0.1:6379> smembers set1
1) "kb"
2) "curry"
3) "lbj"
4) "kd"
5) "zimu"
127.0.0.1:6379> srandmember set1 2
1) "kd"
2) "kb"
127.0.0.1:6379> srandmember set1 2
1) "zimu"
2) "lbj"
127.0.0.1:6379> srandmember set1 2
1) "zimu"
2) "lbj"
127.0.0.1:6379> srandmember set1 6
1) "kb"
2) "curry"
3) "lbj"
4) "kd"
5) "zimu"
127.0.0.1:6379> srandmember set1 -3
1) "kb"#重复
2) "lbj"
3) "kb"#重复
127.0.0.1:6379>
3)SPOP key [数字]
从集合中随机弹出一个元素,出一个删一个
127.0.0.1:6379> smembers set1
1) "kd"
2) "zimu"
3) "lbj"
4) "curry"
5) "kb"
127.0.0.1:6379> spop set1 1
1) "kd"
127.0.0.1:6379> spop set1 1
1) "curry"
127.0.0.1:6379> spop set1 1
1) "lbj"
127.0.0.1:6379> smembers set1
1) "zimu"
2) "kb"
4)smove key1 key2
在key1里已存在的某个值,将key1里已存在的某个值赋给key2
127.0.0.1:6379> sadd set2 1 2 3
(integer) 3
127.0.0.1:6379> smembers set1
1) "zimu"
2) "kb"
127.0.0.1:6379> smove set2 set1 2
(integer) 1
127.0.0.1:6379> smembers set1
1) "2"
2) "zimu"
3) "kb"
5)集合运算
127.0.0.1:6379> sadd array1 1 2 3 a b c
(integer) 6
127.0.0.1:6379> sadd array2 b c 1
(integer) 3
127.0.0.1:6379> sdiff array1 array2
1) "2"
2) "3"
3) "a"
127.0.0.1:6379> sunion array1 array2
1) "1"
2) "b"
3) "2"
4) "c"
5) "a"
6) "3"
127.0.0.1:6379> sinter array1 array2
1) "1"
2) "b"
3) "c"
6)应用场景
- 微信抽奖小程序
- 微信朋友圈点赞查看同赞朋友
- QQ内推可能认识的人
5.Redis有序集合Zset(sorted set)
在set基础上,每个val值前加一个score分数值。之前set是k1 v1 V2 v3,现在zset是k1 score1 v1 score2 v2
1)常用
2)zadd、zrange、withscores
ZADD key score member [score member ...]
:添加元素
ZRANGE key start stop [WITHSCORES]
:按照元素分数从小到大的顺序、返回索引从start到stop之间的所有元素
zrevrange
:顾名思义,翻转的ZRANGE
127.0.0.1:6379> zadd zset1 10 v1 20 v2 30 v3
(integer) 3
127.0.0.1:6379> zadd zset1 10 v1 20 v2 30 v3
(integer) 0
127.0.0.1:6379> zrange zset1 0 -1
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> zrange zset1 0 -1 withscores
1) "v1"
2) "10"
3) "v2"
4) "20"
5) "v3"
6) "30"
127.0.0.1:6379>
3)ZRANGEBYSCORE
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
:获取指定分数范围的元素、(不包含、
limit 作用是返回限制、limit 开始下标步 多少步
4)zscore、zcard、zcount、zrank
zscore
:按照值获得对应的分数
zcard
:获取集合中元素个数
zcount
:获取分数区间内元素个数,zcount key 开始分数区间 结束分数区间
zrank/zrevrank
: 获取value在zset中的下标位置,正序/逆序
5)zrem
- 删除元素,格式:zrem zset的key 项的值,项的值可以是多个
- zrem key score某个对应值,可以是多个值
6)ZINCRBY
ZINCRBY key increment member
:增加某个元素的分数
7)zmpop
从键名列表中的第一个非空排序集
中弹出一个或多个元素,它们是成员分数对
8)应用场景
思路:定义商品销售排行榜(sorted set集合),key为 goods:sellsort,分数为 商品销售数量。
商品编号1001的销量是9,商品编号1002的销量是15 | zadd goods:sellsort 9 1001 15 1002 |
---|---|
有一个客户又买了2件商品1001,商品编号1001销量加2 | zincrby goods:sellsort 2 1001 |
求商品销量前10名 | ZRANGE goods:sellsort 0 9 withscores |
6.Redis位图(bitmap)
由0和1状态表现的二进制位的bit数组
1)需求
- 用户是否登陆过Y、N,比如京东每日签到送京豆
- 电影、广告是否被点击播放过
- 钉钉打卡上下班,签到统计
2)是什么
说明:用String类型作为底层数据结构实现的一种统计二值状态的数据类型
位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(我们称之为一个索引)。
Bitmap支持的最大位数是232位,它可以极大的节约存储空间,使用512M内存就可以存储多达42.9亿的字节信息(232 = 4294967296)
3)能干嘛
用于状态统计Y、N,类似AtomicBoolean
4)基本命令
5)setbit
-
setbit key offset value
-
setbit 键 偏移位 只能零或者1
-
Bitmap的偏移量是从零开始算的
6)getbit
getbit key offset
7)strlen
统计字节数占用多少
不是字符串长度而是占据几个字节,超过8位后自己按照8位一组一byte再扩容
8)bitcount
全部键里面含有1的有多少个?
9)bitop
举例:
连续2天都签到的用户
加入某个网站或者系统,它的用户有1000W,做个用户id和位置的映射
比如0号位对应用户id:uid-092iok-lkj
比如1号位对应用户id:uid-7388c-xxx
。。。。。。
10)setbit和getbit案例说明:按照天
11)应用场景
-
一年365天,全年天天登陆占用多少字节
-
按照年
- 按年去存储一个用户的签到情况,365 天只需要 365 / 8 ≈ 46 Byte,1000W 用户量一年也只需要 44 MB 就足够了。
- 假如是亿级的系统,每天使用1个1亿位的Bitmap约占12MB的内存(10^8/8/1024/1024),10天的Bitmap的内存开销约为120MB,内存压力不算太高。
- 此外,在实际使用时,最好对Bitmap设置过期时间,让Redis自动删除不再需要的签到记录以节省内存开销。
7.Redis基数统计(HyperLogLog)
HyperLogLog 是一种概率数据结构,用于估计集合的基数。作为一种概率数据结构,HyperLogLog以完美的精度换取了高效的空间利用率。
Redis HyperLogLog 实现最多使用 12 KB,并提供 0.81% 的标准误差。
1)看需求
- 统计某个网站的UV、统计某个文章的UV
- 什么是UV
- Unique Visitor,独立访客,一般理解为客户端IP
- 需要去重考虑
- 用户搜索网站关键词的数量
- 统计用户每天搜索不同词条个数
2)是什么
-
去重复统计功能的基数估计算法-就是HyperLogLog
-
基数
-
是一种数据集,去重复后的真实个数
-
案例Case
-
-
基数统计
- 用于统计一个集合中不重复的元素个数,就是对集合去重复后剩余元素的计算
-
一句话
- 去重后的真实数据
3)基本命令
pfadd
:添加对应key的元素pfcount
:去重后统计key的元素个数pfmerge
:生成合并两个key去重后的key
应用场景-编码实战案例见高级篇------>天猫网站首页亿级uv的Redis统计方案
8.Redis地理空间(GEO)
1)简介
移动互联网时代LBS应用越来越多,交友软件中附近的小姐姐、外卖软件中附近的美食店铺、高德地图附近的核酸检查点等等,那这种附近各种形形色色的XXX地址位置选择是如何实现的?
地球上的地理位置是使用二维的经纬度表示,经度范围 (-180, 180],纬度范围 (-90, 90],只要我们确定一个点的经纬度就可以名取得他在地球的位置。
例如:滴滴打车,最直观的操作就是实时记录更新各个车的位置,
然后当我们要找车时,在数据库中查找距离我们(坐标x0,y0)附近r公里范围内部的车辆
使用如下SQL即可:
select taxi from position where x0-r < x < x0 + r and y0-r < y < y0+r
1.查询性能问题,如果并发高,数据量大这种查询是要搞垮数据库的
2.这个查询的是一个矩形访问,而不是以我为中心r公里为半径的圆形访问。
3.精准度的问题,我们知道地球不是平面坐标系,而是一个圆球,这种矩形计算在长距离计算时会有很大误差
2)原理
Redis在3.2版本以后增加了地理位置的处理
3)命令
GEOADD
:多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中GEOPOS
:从键里面返回所有给定位置元素的位置(经度和纬度)GEODIST
: 返回两个给定位置之间的距离。GEORADIUS
:以给定的经纬度为中心,返回与中心的距离不超过给定最大距离的所有位置元素。GEORADIUSBYMEMBER
:跟GEORADIUS类似GEOHASH
:返回一个或多个位置元素的 Geohash 表示
4)GEOADD、GEOPOS、geohash、GEODIST、GEORADIUS、GEORADIUSbymember
-
如何获得某个地址的经纬度
- http://api.map.baidu.com/lbsapi/getpoint/
-
GEOADD
:添加经纬度坐标
GEOADD city 116.403963 39.915119 "天安门" 116.403414 39.924091 "故宫" 116.024067 40.362639 "长城"
-
中文乱码如何处理
-
GEOPOS
:返回经纬度
GEOPOS city 天安门 故宫 长城
-
GEOHASH
:返回坐标的geohash表示-
geohash算法生成的base32编码值
-
3维变2维变1维:主要分为三步。将三维的地球变为二维的坐标在将二维的坐标转换为一维的点块最后将一维的点块转换为二进制再通过base32编码
-
geohash city 天安门 故宫 长城
GEODIST
: 两个位置之间距离
GEODIST city 天安门 故宫 km
后面参数是距离单位:m 米、km 千米、ft 英尺、mi 英里
GEORADIUS
: 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUS city 116.418017 39.914402 10 km withdist withcoord count 10 withhash desc
GEORADIUS city 116.418017 39.914402 10 km withdist withcoord withhash count 10 desc
WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
WITHCOORD: 将位置元素的经度和维度也一并返回。
WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大
COUNT 限定返回的记录数。
当前位置(116.418017 39.914402),阳哥在北京王府井
GEORADIUSBYMEMBER
:找出位于指定范围内的元素,中心点是由给定的位置元素决定
GEORADIUSbymember city 天安门 10 km withdist withcoord count 10 withhash
应用场景
- 美团地图位置附近的酒店推送
- 高德地图附近的核酸检查点
9.Redis流(Stream)-专人专事,还是用MQ吧
10.Redis位域(bitfield)-了解即可
原文地址:https://blog.csdn.net/kdzandlbj/article/details/140628168
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!