redis安装和使用

redis安装

wget http://download.redis.io/redis-stable.tar.gz
tar zxvf redis-stable.tar.gz
cd redis-stable.tar.gz
make
make install

  

redis启动

redis-server
redis关闭
 
redis-cli shutdown

配置

方法一

redis-server /path/to/redis.conf
redis-server /path/to/redis.conf --loglevel warning //设置日志级别

  

方法二

redis-cli
redis > CONFIG SET loglevel warning

  

多数据库的选择

默认情况下,客户端自动选择0号数据库。
可以使用select命令来选择其他数据库。
> select 1

  

redis不可以设置数据库的名称,数据库是通过编号来使用的。
redis只有一个全局的密码,不存在访问某个数据库的密码。

数据库基本操作

(1)添加数据和查找数据,通过set/get命令添加和获取数据

127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> set bar 1
OK
127.0.0.1:6379[1]> get bar
"1"
127.0.0.1:6379[1]> get aaa
(nil)

  

(2)判断一个键是否存在,exists命令可以判断key是否存在,存在返回1,不存在返回0

127.0.0.1:6379[1]> exists bar
(integer) 1
127.0.0.1:6379[1]> exists aaa
(integer) 0

  

(3)删除数据,del命令删除key,返回值为成功删除key的个数

127.0.0.1:6379[1]> del aaa
(integer) 0
127.0.0.1:6379[1]> del bar
(integer) 1

  

(4)获取value的类型

127.0.0.1:6379[1]> set bar 1
OK
127.0.0.1:6379[1]> type bar
string

  

(5)自增和自减,incr 、decr以及incrby和decrby实现整数的加减

127.0.0.1:6379[1]> INCR ab
(integer) 1
127.0.0.1:6379[1]> INCR ab
(integer) 2
127.0.0.1:6379[1]> INCRBY ab 2
(integer) 4
127.0.0.1:6379[1]> DECR ab
(integer) 3
127.0.0.1:6379[1]> DECRBY ab 2
(integer) 1

  

(6)增加指定浮点数,incrbyfloat可以指定自增的浮点数

127.0.0.1:6379[1]> INCRBYFLOAT ab 1.1
"2.1"

  

(7)向尾部追加,append命令可以向字符尾部追加内容

127.0.0.1:6379[1]> set key hello
OK
127.0.0.1:6379[1]> append key world
(integer) 10
127.0.0.1:6379[1]> get key
"helloworld"

  

(8)获取字符串长度,strlen获取value的长度

127.0.0.1:6379[1]> STRLEN key
(integer) 10

  

(9)批量设置和获取,通过mset和mget命令可以批量执行设置和获取

127.0.0.1:6379[1]> mset key1 va1 key2 va2
OK
127.0.0.1:6379[1]> mget key1 key2
1) "va1"
2) "va2"

  

(10)位操作

getbit key offset
setbit key offset
bitcount key [start] [end]
bitop operation destkey key [key ...]

  

散列类型

其实这里的散列类型就是类似于非结构化数据,json数据一样。
 
{
"id":1,
"name":"test"
}

  

基本操作

(1)存储方法,可以通过hset和hget来设置和获取数据

127.0.0.1:6379[1]> hset user id 1
(integer) 1
127.0.0.1:6379[1]> hset user name test
(integer) 1
127.0.0.1:6379[1]> hget user id
"1"
127.0.0.1:6379[1]> hget user name
"test"

  

(2)判断字段是否存在,hexists命令,返回1存在,返回0不存在

127.0.0.1:6379[1]> hexists user id
(integer) 1
127.0.0.1:6379[1]> hexists user age
(integer) 0

  

(3)使用hsetnx(hset if not exists)如果不存在赋值

127.0.0.1:6379[1]> hsetnx user age 111
(integer) 1
127.0.0.1:6379[1]> hget user age
"111"

  

(4)增加数字

127.0.0.1:6379[1]> hincrby user score 60
(integer) 60
127.0.0.1:6379[1]> hget user score
"60"

  

(5)删除字段

127.0.0.1:6379[1]> hdel user score
(integer) 1
127.0.0.1:6379[1]> hget user score
(nil)

  

如何存储数据?

(1)使用散列类型存储数据,散列数据包括三部分(键、字段、字段值)
键           字段     字段值
post:id field value
127.0.0.1:6379[1]> incr userid
(integer) 1
127.0.0.1:6379[1]> hset user:1 name test
(integer) 1
127.0.0.1:6379[1]> hset user:1 score 90
(integer) 1
127.0.0.1:6379[1]> incr userid
(integer) 2
127.0.0.1:6379[1]> hset user:2 name test2
(integer) 1
127.0.0.1:6379[1]> hset user:2 score 99
(integer) 1

  

添加了两条数据,id为1的名字为test分数为90,而id为2的名字为test2分数为90.

(2)获取多个字段的数据,需要使用hmget命令,并制定字段名称
127.0.0.1:6379[1]> hmget user:1 name score
1) "test"
2) "90"
(3)获取一行数据,不需要指定字段名称,只需要指出键名
127.0.0.1:6379[1]> hgetall user:2
1) "name"
2) "test2"
3) "score"
4) "99"
(4)只获取字段名或字段值
127.0.0.1:6379[1]> hkeys user:1
1) "name"
2) "score"
127.0.0.1:6379[1]> hvals user:1
1) "test"
2) "90"

  

(5)获取字段数量
127.0.0.1:6379[1]> hlen user:1
(integer) 2

  

需要注意的是,散列类型无法获取所有存在的键值,也就是id,如果删除了中间某个id的话,只可以使用exist命令来判断key是否存在。

列表类型

类表类型解决了上述的问题。
类表类型是有序的,值是可以重复的。
列表类型是通过双向链表实现的,向列表两端添加元素的时间复杂度为O(1),获取两端元素的速度也是最快。

基本操作

列表的基本操作命令都是以l开头的。

(1)添加和弹出元素使用lpush和rpush以及lpop和rpop分别从列表的左侧和右侧添加和删除元素。
127.0.0.1:6379> lpush user test
(integer) 1
127.0.0.1:6379> rpush user test1
(integer) 2
127.0.0.1:6379> lpop user
"test"
127.0.0.1:6379> rpop user
"test1"
127.0.0.1:6379>
(2)llen查看元素个数
127.0.0.1:6379> llen user
(integer) 0
127.0.0.1:6379> lpush user test
(integer) 1
127.0.0.1:6379> llen user
(integer) 1
(3)获取列表片段
127.0.0.1:6379> lrange user 0 3
1) "test"
2) "test1"
3) "test2"
4) "test3"
127.0.0.1:6379> lrange user 0 2
1) "test"
2) "test1"
3) "test2"

  

(4)从列表中删除元素
lrem     key     count     value
@count 为删除个数,大于0的话从左边开始,小于0的话从右边开始
@value 要删除的值
 我们可以把数据的id存储在列表中,当某一行数据被删除时候,只需要删除为该value为key即可,而查询数据的时候,需要先从列表中读取所有的id,再从散列表中读取数据。
(5)获取和设置索引元素值
 
(6)向列表中插入元素 
127.0.0.1:6379> lrange user 0 -1
1) "test"
2) "test1"
3) "test2"
4) "test3"
127.0.0.1:6379> linsert user before test1 test0
(integer) 5
127.0.0.1:6379> linsert user after test1 test1.5
(integer) 6
127.0.0.1:6379> lrange user 0 -1
1) "test"
2) "test0"
3) "test1"
4) "test1.5"
5) "test2"
6) "test3"

  

(7)将元素从一个列表转移到另外一个列表
rdroplpush     source     destination
从source列表的右侧弹出一个数据,添加到destination列表的左侧

集合类型

集合中不允许重复数据的出现,数据是唯一的,无序的。
空的散列表的HASH TABLE实现,因此操作时间复杂度为O(1)。
(1)增加sadd和删除srem、获取所有元素smembers,返回值标识成功添加元素的数量:
127.0.0.1:6379> sadd key 1
(integer) 1
127.0.0.1:6379> sadd key 2
(integer) 1
127.0.0.1:6379> sadd key 2
(integer) 0
127.0.0.1:6379> smembers key
1) "1"
2) "2"
127.0.0.1:6379> srem key 2
(integer) 1
127.0.0.1:6379> smembers key
1) "1"

  

(2)判断元素是否在集合中可以使用sismember命令。
127.0.0.1:6379> sismember key 1
(integer) 1
127.0.0.1:6379> sismember key 3
(integer) 0

  

(3)集合运算
sdiff      key     [key...]
sinter key [key...]
sunion key [key...]

  

(4)获取元素个数
127.0.0.1:6379> scard key
(integer) 1

  

(5)集合运算并保存结果
sdiffstore       destination     key [key...]
sinterstore destination key[key...]
sunionstore destination key[key...]

  

(6)随机获取集合的元素
srandmember key [count]
127.0.0.1:6379> srandmember key 3
1) "4"
2) "2"
3) "3"

  

需要注意,srandmember取到的随机元素在集合比较小的情况下并不是完全随机的,由于redis的存储方法是利用哈希桶+数据链的存储方式,当桶和每个桶内元素的个数都非常小时就会造成取到相同数据的情况。

有序集合类型 sorted set

与普通的集合类型相比,有序集合为集合中的每一个元素都关联了一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在等集合的基本操作,还能够得到分数最高(或最低)的前n个元素、获得指定分数范围内的元素等与分有关的操作,虽然集合中的元素必须是不同的,但是其分数是可以相同的。
 
有序结合和列表的使用区别:
(1)列表类型是通过链来实现的,获取靠近两端数据的速度极快,而当元素增多后,访问中间元素的数据就会变慢,所以她更适合实现如“新鲜事”或“日志”这样少访问中间元素的应用。
(2)有序集合类型是使用散列和跳跃表实现的,所以即使读取位于中间部分数据的速度也很快(时间复杂度为O(log(n)))。
(3)列表中不能简单地调整某个元素的位置,但有序集合可以通过调整分数来实现位置的调整。
(4)有序集合更加消耗内存。

基本操作

(1)zadd添加元素,并设置分数score

127.0.0.1:6379> zadd students 60 xiaoming
(integer) 1
127.0.0.1:6379> zadd students 80 daxiong
(integer) 1
(2)zscore获取元素分数
127.0.0.1:6379> zscore students xiaoming
"60"
(3)获取排名在某个范围的列表,元素是从0开始的
127.0.0.1:6379> zrange students 0 1
1) "xiaoming"
2) "daxiong"
(4)获取指定分数范围的元素,用于筛选数据
127.0.0.1:6379> zrangebyscore students 0 70
1) "xiaoming"
127.0.0.1:6379> zrangebyscore students 0 100
1) "xiaoming"
2) "daxiong"
limit命令可以实现sql语句中的Limit效果
获取从0开始的前2个数据
127.0.0.1:6379> zrangebyscore students 0 100 limit 0 2
1) "xiaoming"
2) "daxiong"
获取从1开始的前2个数据
127.0.0.1:6379> zrangebyscore students 0 100 limit 1 2
1) "daxiong"
(5)增加和减少某个元素的分数
127.0.0.1:6379> zincrby students 5 xiaoming
"65"
127.0.0.1:6379> zincrby students -5 xiaoming
"60"
(6)获取集合中元素个数
127.0.0.1:6379> zcard students
(integer) 2
(7)获取指定分数范围内的元素个数
zcount     key     min     max

127.0.0.1:6379> zcount students 0 70
(integer) 1
127.0.0.1:6379> zcount students 0 90
(integer) 2

  

(8)删除一个或多个元素
zrem     key     [key...]
(9)按照排名范围来删除元素
zremrangebyrank     key     start     stop
(10)按照分数范围来删除元素
zremrangebyscore     key     min     max
(11)获取元素的排名,注意元素从0开始排序
127.0.0.1:6379> zrank students xiaoming
(integer) 0

事务

redis的事务是一组命令的集合。事务同命令一样都是redis的最小执行单元,一个事务中的命令要么执行要么都不执行。

首先需要multi命令来开始事务,用exec命令来执行事务。

127.0.0.1:6379> multi
OK
127.0.0.1:6379> hset user:1 name xiaoming
QUEUED
127.0.0.1:6379> hset user:1 name daxiong
QUEUED
127.0.0.1:6379> exec
1) (integer) 0
2) (integer) 0
127.0.0.1:6379> hgetall user:1
1) "name"
2) "daxiong"
3) "score"
4) "61"

  

multi代表事务的开始,返回ok表示成功;
 
exec代表事务的执行,返回各个命令的执行结果;
 
在multi和exec中间添加需要执行的命令。
 
在multi开始后,所有命令都不会执行,而是全部暂时保存起来,在执行exec命令后会按照命令保存的顺序依次执行各个命令。
 
如果事务执行过程中存在失败的情况下(某一个命令执行失败后其他命令会继续执行),需要开发人员自行处理后果。
 
注意:redis不支持回滚操作,导致redis的错误异常需要开发人员处理。

watch

watch命令可以监控一个或多个键值的变化,一旦其中一个键被改变,之后的事务就不会执行,而且监控会一直持续到exec命令。
127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> set key 2
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 3
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get key
"2"

  

生存时间

(1)设置key的超时时间,超时后redis会自动删除给key值,类似于memcache中的超时时间。
 
expire     key     seconds
//设置成功返回1,失败返回0
127.0.0.1:6379> set session:aabb uid1122
OK
127.0.0.1:6379> expire session:aabb 300
(integer) 1
127.0.0.1:6379> del session:aabb
(integer) 1
127.0.0.1:6379> expire session:aabb 300
(integer) 0 127.0.0.1:6379> expire session:aabb 300
(integer) 1
127.0.0.1:6379> ttl session:aabb
(integer) 290

  

(2)查询剩余超时时间
ttl     key
127.0.0.1:6379> expire session:aabb 300
(integer) 1
127.0.0.1:6379> ttl session:aabb
(integer) 290

  

(3)取消超时时间
127.0.0.1:6379> get session:aabb
"300"
127.0.0.1:6379> ttl session:aabb
(integer) 280
127.0.0.1:6379> persist session:aabb
(integer) 1
127.0.0.1:6379> ttl session:aabb
(integer) -1

  

(4)如果使用设置相关的命令,会取消该键的超时间

缓存数据

在某些情况下,需要缓存一部分网站数据,而网站数据由需要持续的更新(假如需要两个小时更新一次),那么可以采用redis进行缓存这部分数据,设置数据的超时时间为2小时,每当有请求访问的时候首先到redis中查找该数据是否存在,如果存在直接读取,如果不存在的话重新从数据库中读取该数据加载到redis中。
 
在缓存数据的时候需要考虑到被缓存数据的大小,如果缓存数据较大,会占用过多的内存资源,有必要在配置文件中限制内存的使用大小(maxmemory)。
 
当超过maxmemory的限制后,redis会根据maxmemory-policy参数指定的策略(包括LRU等算法)来删除不需要的键。

排序

sort命令支持对集合类型、类表类型、有序集合类型进行排序。
127.0.0.1:6379> lpush list 1 2 6 3 4 9 8
(integer) 7
127.0.0.1:6379> sort list
1) "1"
2) "2"
3) "3"
4) "4"
5) "6"
6) "8"
7) "9"

  

可以对有序集合的值进行排序:
127.0.0.1:6379> zadd set 50 2 40 3 20 1 60 5
(integer) 4
127.0.0.1:6379> sort set
1) "1"
2) "2"
3) "3"
4) "5"

  

sort命令可以添加desc来实现倒序排序
127.0.0.1:6379> sort set desc
1) "5"
2) "3"
3) "2"
4) "1"

  

BY参数

很多时候我们需要根据ID对应的对象的某一个属性进行排序,那么如何才能把多个不同的数据进行关联查询呢?
(1)首先,向userids中添加三个用户id
127.0.0.1:6379> lpush userids 1 2 3
(integer) 3
(2)其次,分别对三个用户添加分数
127.0.0.1:6379> set user_score_1 50
OK
127.0.0.1:6379> set user_score_2 30
OK
127.0.0.1:6379> set user_score_3 70
OK
(3)最后,使用sort、by命令来对对用户按照默认情况以及分数的递增和递减进行排序。
127.0.0.1:6379> sort userids
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sort userids by user_score_*
1) "2"
2) "1"
3) "3"
127.0.0.1:6379> sort userids by user_score_* desc
1) "3"
2) "1"
3) "2"

GET参数

get参数并不影响排序,它的作用是使sort命令返回的结果不再是元素自身的值,而是get参数中指定的键值,同by参数一样,支持字符串类型和散列类型的键。
127.0.0.1:6379> sort userids by user_score_* get user_name_*
1) "xiaoming"
2) "daxiong"
3) "xiaohong"
127.0.0.1:6379> sort userids by user_score_* desc get user_name_*
1) "xiaohong"
2) "daxiong"
3) "xiaoming"

  

STORE参数

store参数用于结果保存。
 
sort命令是redis的复杂命令之一,使用不好会造成性能的瓶颈。
 
sort命令的时间复杂度是O(n+mlog(m)),其中n是排序列表(集合和有序集合)中元素的个数,m是返回元素的个数。Redis在排序前会建立一个长度为n的的容器来存储待排序元素,虽然是一个临时的过程,但是多个较大数据的排序操作则会严重影响系统的性能。
 
因此,在开发中需要注意:
(1)尽可能减少排序键中的元素个数,降低n
(2)使用Limit参数只获取需要的数据,降低n
(3)如果要排序的数据量较大,尽可能使用store名来缓存结果。

任务队列

任务队列一般适用于生产者和消费者之间通信的,那么在redis中很容易想到使用列表类型来实现任务队列,具体方法是创建一个任务队列,生产者主动lpush数据,而消费者去rpop数据,保持一个先进先出的循序。
但是这样存在一个问题,消费者需要主动去请求数据,周期性的请求会造成资源的浪费,因此,redis提供了一个brpop的命令来解决这个问题。
BRPOP     key     timeout
brpop命令接收两个参数,第一个参数key为键值,第二个参数timeout为超时时间。BRPOP命令取数据时候,如果暂时不存在数据,该命令会一直阻塞直到达到超时时间。如果timeout设置为0,那么就会无限等待下去。

优先级队列

基于任务队列,如何实现优先级队列呢?
 
那么可以选择多个任务队列,而每个任务队列的任务优先级是不同的。
 
redis提供了下面的命令,会从左边第一个key开始读下去知道返回一个数据。
brpop key [key...] timetout

发布/订阅模式

redis提供了rabitmq类似的发布订阅模式,通过生产者使用下面的命令来发布消息,
PUBLISH     CHANNEL     MESSAGE
消费者通过下面的消息来订阅消息,
SUBSCRIBE     CHANNEL     MESSAGE
生产者:
#向channel.test发布消息
127.0.0.1:6379> publish channel.test hello
(integer) 0 #返回0表明订阅者为0,没有发布消息
127.0.0.1:6379> publish channel.test hello
(integer) 1 #返回n表明订阅者为n,成功发布给1个消费者
消费者:
#订阅channel.test消息
127.0.0.1:6379> subscribe channel.test
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel.test"
3) (integer) 1
#接收到来自channel.test的消息
1) "message"
2) "channel.test"
3) "hello"

管道

redis的底层通信协议对管道提供了支持。通过管道可以一次性发送多条命令并在执行完后一次性将结果返回,当一组命令中每条命令都不依赖之前命令的执行结果时就可以将这组命令一起通过管道发出。管道通过减少客户端与redis的通信次数来实现降低往返实验累计值的目的。

节省空间

(1)精简键名和键值
(2)redis为每种数据类型提供了两种内部编码。例如散列类型的存储是通过散列表来实现的,redis会根据数据的多少来选择编码类型,当数据较少的时候会采用紧凑但性能稍差的内部编码方式,而数据变多时会把编码方式改为散列表。
 
转载自:cococo点点 http://www.cnblogs.com/coder2012

Redis高级命令操作大全--推荐的更多相关文章

  1. SQLite3命令操作大全

    SQLite3命令操作大全 SQLite库包含一个名字叫做sqlite3的命令行,它可以让用户手工输入并执行面向SQLite数据库的SQL命令.本文档提供一个样使用sqlite3的简要说明. 一.ql ...

  2. Redis高级命令及特性(安全性)

    高级命令 ​ keys * : 返回满足的所有键 ,可以模糊匹配 ​ exists :是否存在指定的key,存在返回1,不存在返回0 ​ exprie:设置某个key的过期时间 ​ ttl:查看剩余时 ...

  3. redis 简单命令操作

    一.概述: 在该系列的前几篇博客中,主要讲述的是与Redis数据类型相关的命令,如String.List.Set.Hashes和Sorted-Set.这些命令都具有一个共同点,即所有的操作都是针对与K ...

  4. redis常用命令手册大全

    一.五种数据类型1.Redis字符串StringString 是最简单的类型,你可以理解成与 Memcached 是一模一样的类型,一个 key 对应一个value,其上支持的操作与 Memcache ...

  5. AMH面板命令操作大全

    LNMP面板 - AMH 命令使用nginx篇 » SSH Nginx1) 有步骤提示操作: ssh执行命令: amh nginx然后选择对应选项进行操作. 2) 或直接操作: 启动Nginx: am ...

  6. Redis常用命令操作

    字符串类型: * 存储:set key value * 获取:get key * 无值返回nil * 删除:del key 哈希类型 hash: * 存储:hset key field value * ...

  7. 《Linux 操作系统》Linux的常用命令操作大全

    前言 在学习命令之前先学习我们该如何去学习linux 命令. 几乎每一个命令都有参数,每个参数的含义是什么,我们一般也不是全部都能记住,所以我们必须有一个可以知道每一个命令下各个参数的含义的方法. 命 ...

  8. Redis - 常用命令操作

    常用命令keys:        keys *        查看符合条件的所有key exists:        exists key    查看key是否存在 del:        del k ...

  9. redis高级命令4 持久化机制 、事务

    redis的事务是支持很简单,基本没有啥用我们来看下面的列子 我们开启一个事务,在事务中执行了age 加1,set a4 ,还有对一个字符串进行加一,对字符串加1导致了事务失败,按道理incr age ...

随机推荐

  1. 删除Excel中的复选框等控件

  2. ora-00600错误解决一枚

    今天网友遇到ora-600错误,这里把这个ora-600错误的解决方法详细记录一下. 最初报错信息如下: ora-600-图1 ora-600-图2 图3 这里我们可以看到报错控制文件版本不一致,要求 ...

  3. PHP搭建(windows64+apache2.4.7+mysql-5.6+php5.5+phpMyAdmin)和Discuz安装

    以下文章参考的3个来源,在加上本人搭建过程中遇到的问题的修复完善笔记: <PHP环境的搭建和Discuz!安装> http://www.myxzy.com/post-386.html ht ...

  4. 欧盟GDPR通用数据保护条例-原文

    GDPR英文原文 https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=uriserv:OJ.L_.2016.119.01.0001.01.ENG&a ...

  5. android 本地通知

    NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); Notificat ...

  6. Struts,Spring,Hibernate优缺点

    Struts跟Tomcat.Turbine等诸 多Apache项目一样,是开源软件,这是它的一大优点.使开发者能更深入的了解其内部实现机制. Struts开放源码框架的创建是为了使开发者在构建基于Ja ...

  7. PhotoSwipe中文API(一)

    入门 您应知道之前先做起事情: 1. PhotoSwipe不是一个简单的jQuery插件,至少基本的JavaScript知识才能安装. 2. PhotoSwipe需要预定义的图像尺寸(更多关于这一点) ...

  8. 特定于类的内存管理---《C++必知必会》 条款36

    我们可以量身定制 operator new 和 operator delete 用于某个类类型,而不是必须使用标准版的 operator new 和 operator delete. 注意:我们不可以 ...

  9. cocos代码研究(13)Widget子类EditBox学习笔记

    理论基础 一个用来输入文本的类,继承自 Widget , 以及 IMEDelegate. 代码部分 Public枚举类型 enum KeyboardReturnType键盘的返回键类型. enum I ...

  10. cocos进阶教程(3)Lua加密技术

    如果开发者不想让游戏中的资源或脚本文件轻易的暴露给其他人,一般会采用对文件进行加密的方式来保护文件或资源被盗用.Quick-Cocos2d-x 为开发者提供了xxtea加密算法,用来对脚本文件及资源进 ...