redis数据类型及操作命令

数据类型

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型:

字符串 string
哈希 hash
列表 list
集合 set
有序集合 sorted set /zset

解释说明:

字符串(string):普通字符串,常用

哈希(hash):适合存储对象

列表(list):按照插入顺序排序,可以有重复元素

集合(set):无序集合,没有重复元素

有序集合(sorted set / zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素

Redis常用命令

更多命令可以参考Redis中文网:https://www.redis.net.cn

Redis数据类型_key键

image-20230722112045742

keys

查看当前库中所有的key 。
语法结构:

keys *
有3个通配符 *, ? ,[]
*: 通配任意多个字符
?: 通配单个字符
[]: 通配括号内的某1个字符

示例:keys *

注意:
生产已经禁止。因为长时间阻塞redis而导致其他客户端的命令请求一直处于阻塞状态。 更安全的
做法是采用scan。

新版本也进行了替代

root@6c068b3fbf29:/data# redis-cli --scan "u*"
"user1"
"user"

exists

判断某个key是否存在,返回1表示存在,0不存在。
语法结构:

exists key

示例:
#查看k1是否存在,如果存在返回1
exists k1
# 查看k1 k2 k3是否存在,如果k1 k2存在,k3不存在,则返回2
exists k1 k2 k3

注意:
可以设置多个key,只返回存在的个数,但不返回哪一个存在/不存在

type

查看当前key 所储存的值的类型。返回当前key所储存的值的类型,如string 、list等。

语法结构

type key

示例:
type k1

del

删除已存在的key,不存在的 key 会被忽略。

语法结构:

del key

示例
可以设置多个key,返回删除成功的个数;
# 删除k1,如果成功返回1,失败返回0
del k1
# 删除k1 k2 k3,如果k1 k2存在,k3不存在,则返回2
del k1 k2 k3

expire

给key设置time秒的过期时间。设置成功返回 1 。 当 key 不存在返回 0。

语法结构:

expire key time

示例:
# 给k1设置10秒后过期
expire k1 10

ttl

以秒为单位返回 key 的剩余过期时间。
语法结构:

ttk key

示例:
ttl  k1

注意:
当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间

persist

移除给定 key 的过期时间,使得 key 永不过期。

语法结构:

persist key

示例:
persist k1

注意:
当过期时间移除成功时,返回 1 。 如果 key 不存在或 key 没有设置过期时间,返回 0 

Redis数据类型_String

image-20230722113355064

String是Redis最基本的类型,一个key对应一个value。String是二进制安全的,意味着String可以包含
任何数据,比如序列化对象或者一张图片。String最多可以放512M的数据。

set

用于设置给定 key 的值。如果 key 已经存储其他值, set 就重写旧值,且无视类型。

语法格式:

set key value

示例:

127.0.0.1:6379> set k1 v1
OK

get

用于获取指定 key 的值。如果 key 不存在,返回 nil 。
语法格式:

get key

示例
127.0.0.1:6379> get k1
"v1"

append

将给定的value追加到key原值末尾

语法格式:

append key value

示例
127.0.0.1:6379> APPEND k1 k1
(integer) 4
127.0.0.1:6379> APPEND k1 k2
(integer) 6

注意:
如果 key 已经存在并且是一个字符串, append 命令将 value 追加到 key 原来的值的末尾。
如果 key 不存在, append 就简单地将给定 key 设为 value ,就像执行 set key value 一样。

strlen

获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。

语法格式

strlen key

示例
127.0.0.1:6379> strlen k1
(integer) 6

setex

给指定的 key 设置值及time 秒的过期时间。如果 key 已经存在, setex命令将会替换旧的值,并设置过期时间。

语法格式:

setex key time value

示例
#向Redis中设置一个k1的键值对并且10秒后过期
127.0.0.1:6379> setex k1 10 v1
OK

setnx

只有在key不存在时设置key的值

语法格式:
setnx key value

示例:
127.0.0.1:6379> setnx k1 v1
(integer) 0
127.0.0.1:6379> setnx k4 v4
(integer) 1

getrange

获取指定区间范围内的值,类似between........and 的关系

语法格式:

getrange key start end

示例:
127.0.0.1:6379> set k5 abcd123xxx
OK
127.0.0.1:6379> getrange k5 2 4
"cd1"

setrange

获取指定区间范围内的值,类似between........and 的关系

语法结构:

setrange key offset value

示例
127.0.0.1:6379> set k6 abcd1234
OK
127.0.0.1:6379> setrange k6 1 xxx
(integer) 8
127.0.0.1:6379> get k6
"axxx1234"

incr

将 key 中储存的数字值增一。

语法格式:

incr key

示例:
#因为Redis中不存在k1,所以先初始化为0,再递增,值为1
127.0.0.1:6379> incr k1
(integer) 1
# incr k1 存在k1,递增后k1的值为2
127.0.0.1:6379> incr k1
(integer) 2
# 如果value不是数字就会报错
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> INCR k2
(error) ERR value is not an integer or out of range

注意:
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 incr 操作。
如字符串类型的值不能表示为数字、或者是其他类型,那么返回一个错误

decr

将 key 中储存的数字值减一。

语法格式:

decr key

示例:
127.0.0.1:6379> decr k1
(integer) 1
127.0.0.1:6379> decr k1
(integer) 0
127.0.0.1:6379> decr k1
(integer) -1
127.0.0.1:6379> decr k1
(integer) -2
#如果
set k2 v2
decr k2 因为k2不为数值,Redis返回一个错误

注意:
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 decr 操作。
如字符串类型的值不能表示为数字、或者是其他类型,那么返回一个错误

incrby/decrby key step

将key存储的数字值按照step进行增减

127.0.0.1:6379> incrby k1 10
(integer) 20

注意:
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 incrby/decrby 命令
如字符串类型的值不能表示为数字、或者是其他类型,那么返回一个错误

mset

同时设置一个或多个 key-value

语法格式

mset key1 value1 key2 value2

示例
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK

mget

返回所有(一个或多个)给定 key 的值。

语法格式:

mget key1 key2

示例
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

注意:
如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 

getset

将给定key值设为value,并返回key的旧值(old value),简单一句话(先get然后立即set)。

语法格式

getset key value

示例
127.0.0.1:6379> getset k1 wcc
"v1"
127.0.0.1:6379> get k1
"wcc"

使用场景

value 除了是字符串以外还可以是数字。
    计数器
    统计多单位的数量
    粉丝数
    对象缓存存储
    分布式锁

Redis数据类型_List

List是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右
边)。底层是一个双向链表,对两段操作性能极高,通过索引操作中间的节点性能较差

一个List最多可以包含 $2^{32}-1$个元素 ( 每个列表超过40亿个元素)。

lpush/rpush

从左边(头部)/右边(尾部)插入一个或多个值。

语法结构:

lpush/rpush key1 value1 value2 value3

示例:
#从左边放入v1 v2 v3
127.0.0.1:6379> lpush k1 v1 v2 v3
(integer) 3

image-20230722141051695

#从右边放入v4 v5 v6
127.0.0.1:6379> rpush k1 v4 v5 v6
(integer) 6

image-20230722141114549

lrange

返回key列表中的start和end之间的元素(包含start和end)。 其中 0 表示列表的第一个元素,-1表示
最后一个元素。

语法结构:

lrange key start end

示例:
#取出列表里前3个值,结果为v3 v2 v1
127.0.0.1:6379> lrange k1 0 2
#取出列表里全部值,结果为v3 v2 v1 v4 v5 v6
127.0.0.1:6379> lrange k1 0 -1

lpop/rpop

移除并返回第一个值或最后一个值。

语法格式:

lpop/rpop key

示例
lpop k1 从列表中删除v3,并返回,当前列表全部值v2 v1 v4 v5 v6
rpop k1 从列表中删除v6,并返回,当前列表全部值v2 v1 v4 v5

注意:
值在键在,值光键亡

lindex

获取列表index位置的值(从左开始)。

语法结构:

lindex key index

示例:
lindex key index

llen

获取列表长度。

语法结构:

llen key

示例:
127.0.0.1:6379> llen k1
(integer) 6

lrem

从左边开始删除与value相同的count个元素。

语法结构:

lrem key count value

示例:
#从左边开始删除k1列表中2个v1元素
lrem k1 2 v1

linsert

在列表中value值的前边/后边插入一个new value值(从左开始)。

语法结构:

linsert key before/after value newvalue

示例:
linsert k1 before v1 v5 在v1前面插入一个v5

lset

将索引为index的值设置为value

语法结构:

lset key index value

示例:
lset key index value

使用场景

消息队列
排行榜
最新列表

Redis数据类型_Set

image-20230722141849235

与List类似是一个列表功能,但Set是自动排重的,当需要存储一个列表数据,又不希望出现重复数据
时,Set是一个很好的选择。
Set是String类型的无序集合,它底层其实是一个value为null的hash表,所以添加、删除、查找的时间
复杂度都是O(1)。

sadd

将一个或多个元素添加到集合key中,已经存在的元素将被忽略。

语法结构:

sadd key value1 value2.....

示例:
#向集合中添加值,最终只有v1 v2 v3 v4 v5 v6
127.0.0.1:6379> sadd k1 v1 v2 v2 v3 v4 v5 v6

smembers

取出该集合的所有元素。

语法结构:

smembers key

示例:
127.0.0.1:6379> smembers k1

sismember

判断集合key中是否含有value元素,如有返回1,否则返回0。

语法结构:

sismember key value

示例:
sismember k1 v1

scard

返回该集合的元素个数。

语法结构:

scard key

示例:
scard k1

srem

删除集合中的一个或多个成员元素,不存在的成员元素会被忽略。

语法结构

srem key value1 value2.

示例
# 删除v1 v2
srem k1 v1 v2

spop

随机删除集合中一个元素并返回该元素。

语法结构:

spop key

示例
spop k1 随机删除一个元素,并返回

srandmember

随机取出集合中count个元素,但不会删除。

语法结构:

srandmember key count

示例
#随机取出集合中的2个元素
srandmember k1 2

smove

将value元素从sourcekey集合移动到destinationkey集合中。

语法结构:

smove sourcekey destinationkey value

示例
smove k1 k2 v5 将元素v5从集合k1中移动到集合k2
注意:
如果 sourcekey集合不存在或不包含指定的 value元素,则 smove 命令不执行任何操作,仅返回0

sinter

返回两个集合的交集元素。

语法结构

sinter key1 key2

示例
sinter key1 key2

sunion

返回两个集合的并集元素。
语法结构

sunion key1 key2

示例
sunion k1 k2

sdiff

返回两个集合的差集元素(key1中的,不包含key2)
语法结构

sdiff key1 key2

示例
sdiff key1 key2

使用场景

黑白名单
随机展示
好友
关注人
粉丝
感兴趣的人集合

Redis数据类型_Hash

image-20230722143546484

Hash是一个键值对的集合。Hash 是一个 String 类型的 field(字段) 和 value(值) 的映射表,hash
特别适合用于存储对象。
Hash存储结构优化
如果field数量较少,存储结构优化为类数组结构
如果field数量较多,存储结构使用HashMap结构

hset

给key集合中的field赋值value。
语法结构

hset key field value

示例:
127.0.0.1:6379> hset user name baizhan
(integer) 1
127.0.0.1:6379> hset user age 3
(integer) 1

注意:
如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。
如果字段已经存在于哈希表中,旧值将被重写

hget

从key哈希中,取出field字段的值。

语法结构

hget key field

示例:
127.0.0.1:6379> hget user name
"baizhan"

hmset

批量设置哈希的字段及值。
语法结构

hmset key field1 value1 field2 value2...

示例
127.0.0.1:6379> hmset user1 name baizhan age 15
OK

hexists

判断指定key中是否存在field
语法结构

hexists key field

示例:
127.0.0.1:6379> hexists user1 name
(integer) 1
127.0.0.1:6379> hexists user1 xxx
(integer) 0

注意:
如果哈希表含有给定字段,返回 1 。 如果哈希表不含有给定字段,或 key 不存在,返回 0 

hkeys

获取该哈希中所有的field。
语法结构

hkeys key

示例:
127.0.0.1:6379> hkeys user1
1) "name"
2) "age"

hvals

获取该哈希中所有的value。
语法结构

hvals key

示例
127.0.0.1:6379> hvals user1
1) "baizhan"
2) "15"

hincrby

为哈希表key中的field字段的值加上增量increment。
语法结构

hincrby key field increment

示例
127.0.0.1:6379> hincrby user1 age 10
(integer) 25

注意
增量也可以为负数,相当于对指定字段进行减法操作。
如果哈希表的 key 不存在,一个新的哈希表被创建并执行 hincrby 命令。
如果指定的字段不存在,那么在执行命令前,字段的值被初始化为 0 。
对一个储存字符串值的字段执行 hincrby 命令将造成一个错误

hincrby user1 age 10 对user中的age字段做运算,增加10

hdel

删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。
语法结构

hdel key field1 field2..

示例:
127.0.0.1:6379> hdel user1 age
(integer) 1

hsetnx

给key哈希表中不存在的的字段赋值 。
语法结构

hsetnx key field value

示例
127.0.0.1:6379> hsetnx user1 age 10
(integer) 1

注意:
如果哈希表不存在,一个新的哈希表被创建并进行 hsetnx 操作。
如果字段已经存在于哈希表中,操作无效。
如果 key 不存在,一个新哈希表被创建并执行 hsetnx 命令

使用场景

购物车
存储对象

Redis数据类型_Zset

image-20230722144623239

Zset与Set非常相似,是一个没有重复元素的String集合。不同之处是Zset的每个元素都关联了一个分数
(score),这个分数被用来按照从低分到高分的方式排序集合中的元素。集合的元素是唯一的,但分数
可以重复

注意:
因为元素是有序的,所以可以根据分数(score)或者次序(position)来获取一个范围内的元素

zadd

将一个或多个元素(value)及分数(score)加入到有序集key中。
语法结构

zadd key score1 value1 score2 value2

示例
zadd k1 100 java 200 c++ 300 python 400 php

注意
如果某个元素已经是有序集的元素,那么更新这个元素的分数值,并通过重新插入这个元素,来保证该元素在正确的位置上。
分数值可以是整数值或双精度浮点数。
如果有序集合 key 不存在,则创建一个空的有序集并执行 zadd 操作

zrange

返回key集合中的索引start和索引end之间的元素(包含start和end)。
语法结构

zrange key start end [withscores]

示例
zrange k1 0 -1 返回集合中所有元素
zrange k1 0 -1 withscores 返回集合中所有元素,并携带元素分数

注意:
其中元素的位置按分数值递增(从小到大)来排序。 其中 0 表示列表的第一个元素,-1表示最后一个元素。
withscores是可选参数,是否返回分数

zrangebyscore

返回key集合中的分数minscore 和分数maxscore 之间的元素(包含minscore 和maxscore )。其中元素的位置按分数值递增(从小到大)来排序。
语法结构

zrangebyscore key minscore maxscore [withscores]

示例:
zrangebyscore k1 200 400 返回200-400分之间的元素递增排序

zincrby

为元素value的score加上increment的值

语法结构

zincrby key increment value

示例:
zincrby key increment value

zrem

删除该集合下value的元素

语法结构

zrem k1 php 删除php

zcount

统计该集合在minscore 到maxscore分数区间中元素的个数。
语法结构

zcount key minscore maxscore

示例
zcount k1 100 300 统计100分到300分中间元素的个数

zrank

返回value在集合中的排名,从0开始。
语法结构

zrank key value

示例
zrank k1 c++ 返回c++排名

使用场景

延时队列
排行榜
限流

Redis数据类型_Bitmaps

image-20230722145451592

在计算机中,用二进制(位)作为存储信息的基本单位,1个字节等于8位。
例如 "abc" 字符串是由 3 个字节组成,计算机存储时使用其二进制表示,"abc"分别对应的ASCII码是
97、98、99,对应的二进制是01100001、01100010、01100011,在内存中表示如下

image-20230722145519292

合理地使用位能够有效地提高内存使用率和开发效率。
Redis提供了Bitmaps这个 “数据结构” 可以实现对位的操作

image-20230722145535237

setbit

设置Bitmaps中某个偏移量的值。
语法结构

setbit key offset value

示例:
redis中bitmaps可以用来统计用户信息,eg:活跃天数、打卡天数、登录天数
bitmaps位图,都是操作二进制来进行记录,就只有0和1两个状态

127.0.0.1:6379> getbit sign 1 # 获取第一天的打卡状态
(integer) 1
127.0.0.1:6379> BITCOUNT sign # 统计所有打卡天数
(integer) 4127.0.0.1:6379> setbit zhangsan:3 1 1 # 往sign中添加数据,第1天打卡
(integer) 1
127.0.0.1:6379> setbit zhangsan:3 2 0 # 第2天未打卡
(integer) 0
127.0.0.1:6379> setbit zhangsan:3 3 1 # 第3天打卡
(integer) 0
127.0.0.1:6379> setbit zhangsan:3 4 0 # 第4天未打卡
(integer) 0
127.0.0.1:6379> setbit zhangsan:3 5 1 # 第5天打卡
(integer) 0
127.0.0.1:6379> setbit zhangsan:3 6 0 # 第6天未打卡
(integer) 0
127.0.0.1:6379> setbit zhangsan:3 7 1 # 第7天打卡
(integer) 0 127.0.0.1:6379> getbit sign 1 # 获取第一天的打卡状态
(integer) 1
127.0.0.1:6379> BITCOUNT sign # 统计所有打卡天数
(integer) 4
127.0.0.1:6379> getbit sign 1 # 获取第一天的打卡状态
(integer) 1
getbit key offset

image-20230722145706958

getbit

获取Bitmaps中某个偏移量的值。
语法结构

getbit key offset

示例

获取key的offset 的值
getbit sign 3 获取偏移量为1的值,结果为1

如果偏移量未设置值,则也返回0
getbit sign 99 获取偏移量为99的值,结果为0

bitcount

统计字符串被设置为1的bit数量。一般情况下,给定的整个字符串都会被进行统计,可以选择通过额外的start和end参数,指定字节组范围内进行统计(包括start和end),0表示第一个元素,-1表示最后一个元素。
语法结构:

bitcount key [start end]

示例
bitcount sign 获取整个字符串被设置为1的bit数量,结果为3

如:当前存在一个key为k1的bitmaps存储着[00000001,00000001,00000010,00000011],分别对应
[1,1,2,3]

setbit num 7 1
setbit num 15 1
setbit num 22 1
setbit num 30 1
setbit num 31 1
bitcount num 1 2 统计索引1、2两个字节组中bit=1的数量,即统计00000001,00000010中bit=1的数
量,结果为2
bitcount num 1 3 统计索引1、2、3三个字节组中bit=1的数量,即统计
00000001,00000010,00000011中bit=1的数量,结果为4
bitcount num 0 -1 统计所有的字节组中bit=1的数量,结果为5

setbit设置或获取的是bit(位)的位置,bitcount计算的是byte(字节)位置。

bitop

将多个bitmaps通过求交集/并集方式合并成一个新的bitmaps。
语法结构

bitop and/or destkey sourcekey1 sourcekey2

示例
bitop and k3 k1 k2 通过求交集将k1 k2合并成k3
bitop or k3 k1 k2 通过求并集将k1 k2合并成k3

image-20230722150053035

使用场景

活跃天数
打卡天数
登录天数
用户签到
统计活跃用户
统计用户是否在线
实现布隆过滤器

Redis数据类型_Geospatia

image-20230722150138359

GEO,Geographic,地理信息的缩写。该类型就是元素的二维坐标,在地图上就是经纬度。Redis基于该
类型,提供了经纬度设置、查询、范围查询、距离查询、经纬度Hash等常见操作

geoadd

用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。
语法结构

geoadd key longitude latitude member

示例:
# 将北京的经纬度和名称添加到china
geoadd china 116.405285 39.904989 beijing
# 将成都和上海的经纬度、名称添加到china
geoadd china 104.065735 30.659462 chengdu 121.472644 31.231706 shanghai

geopos

从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
语法结构

geopos key member [member ......]

示例
返回china中名称为shanghai和beijing的经纬度
geopos chinacity shanghai beijing

geodist

用于返回两个给定位置之间的距离。

image-20230722150438471

语法结构

geodist key member1 member2 [m|km|ft|mi]

参数说明:
m :米,默认单位。
km :千米。
mi :英里。
ft :英尺

示例
# 返回shanghai和beijing之间的距离,结果1067597.9668,单位米
geodist chinacity shanghai beijing
# 返回shanghai和chengdu之间的距离,结果1660.0198,单位是千米
geodist chinacity shanghai chengdu km

georadius

以给定的经纬度(longitude latitude)为中心, 返回键包含的位置元素当中, 与中心的距离不超过给
定最大距离(radius )的所有位置元素

image-20230722150627057

语法结构:

georadius key longitude latitude radius m|km|ft|mi

示例
#获取经纬度110 30为中心,在china内1200公里范围内的所有元素。
georadius china 110 30 1200 km

使用场景

附近的电影院
附近的好友
离最近的火锅店

Redis数据类型_Hyperloglog

image-20230722150806223

在我们做站点流量统计的时候一般会统计页面UV(独立访客:unique visitor)和PV(即页面浏览量:page
view)。redis HyperLogLog是用来做基数统计的算法,HyperLogLog的优点是:在输入元素的数量或者
体积非常非常大时,计算基数所需的空间总是固定的、并且使很小的

什么是基数

比如数据集{1,3,5,7,5,7,8},那么这个数据集的基数集为{1,3,5,7,8},基数(不重复元素)为5.基数估计就是在
误差可接受的范围内,快速计算基数

pfadd

将所有元素参数添加到 Hyperloglog 数据结构中。
语法结构

pfadd key element1 element2

示例
如果至少有个元素被添加返回 1, 否则返回 0
pfadd book1 uid1 uid2 uid3

注意:
添加元素到HyperLogLog中,如果内部有变动返回1,没有返回0

pfcount

计算Hyperloglog 近似基数,可以计算多个Hyperloglog ,统计基数总数。
语法结构

pfcount key1 key2

示例
pfcount book1 #计算book1的基数,结果为3
pfadd book2 uid3 uid4 #添加两个元素到book2中
pfcount book1 book2 #统计两个key的基数总数,结果为5

pfmerge

将一个或多个Hyperloglog(sourcekey1) 合并成一个Hyperloglog (destkey )。
语法结构

pfmerge destkey sourcekey1 sourcekey2

示例
比如每月活跃用户可用每天活跃用户合并后计算

#将book1和book2合并成book,结果为5
pfmerge book book1 book2

使用场景

基数不大,数据量不大就用不上,会有点大材小用浪费空间,有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么,和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmaps 方便很多,一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃

网站PV统计
网站UV统计
统计访问量(IP数)
统计在线用户数
统计每天搜索不同词条的个数
统计文章真实阅读数

通用命令

Redis中的通用命令,主要是针对key进行操作的相关命令:

  • KEYS pattern 查找所有符合给定模式( pattern)的 key
  • EXISTS key 检查给定 key 是否存在
  • TYPE key 返回 key 所储存的值的类型
  • TTL key 返回给定 key 的剩余生存时间(TTL, time to live),以秒为单位 -1为永不过期
  • DEL key 该命令用于在 key 存在是删除 key
posted @ 2023-07-22 15:16  YxinHaaa  阅读(8)  评论(0编辑  收藏  举报