Redis入门教程目录:【Redis入门教程目录】java
经过这部分让你们对Redis的五种数据结构有初步的认识,对于Redis来讲,每一种数据结构都有着本身的内部编码,并且是多种实现的,这样Redis会在合适的场景选择合适的内部编码,经过OBJECT ENCODING [key]
能够参看指定key
的内部编码。
这样作的好处:
a. 改进内部编码,对外的数据结构和命令没有影响,对用户提供黑箱模型。
b. 多种内部编码可在不一样场景下发挥各自的优点。如:ziplist
比较节约内存,可是元素比较多的时候,性能会有所降低,此时Redis会将编码自动转换为linkedlist
,性能会有所改善。 python
了解Redis的单线程架构,有助于你们对Redis的进一步学习和排解问题。
mysql
select
、
poll
、
epoll
能够
同时监听多个流的I/O(客户端到服务器的网络请求)事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或者多个流有
I/O
事件时,就从阻塞态中唤醒,
轮训一遍全部的流而且依次处理就绪的流。这样就算出现有的流的
I/O
由于网络缘由很慢,也不会影响别的流的
I/O
(非阻塞),由于是轮训全部的流的
I/O
。这里的“多路”指的是多个网络链接,“复用”指的是复用同一个线程。
Redis一些通用命令,好比删除一个键、计算数据库的大小、设置键的过时时间等,这些命令有不少,这里主要介绍7
个,完整的命令你们能够参考官方文档。c++
N
为数据库中Key
的数量。 这个命令因为时间复杂度为O(N)因此通常生产环境不使用,若是须要遍历所有数据,可使用Scan命令,时间复杂度为O(1)。pattern
的key
,好比说:KEYS *
匹配数据库中全部的key
。KEYS h?llo
匹配hello
、hallo
等key
。KEYS h*llo
匹配hllo
和haaaaaallo
等key
。KEYS h[abe]llo
匹配hallo
、hbllo
和hello
。key
列表。key
的数量。key
的数量。redis> DBSIZE
(integer) 5
redis> SET new_key "hello_moto" # 增长一个 key 试试
OK
redis> DBSIZE
(integer) 6
复制代码
EXISTS key
时间复杂度为O(1)。
检查给定key
是否存在。
返回值: 若key
存在,返回1
,不存在返回0
。web
DEL key [key ...]
时间复杂度为O(N),N
为被删除的key
的数量,其中删除单个字符串类型的key
,时间复杂度为O(1)
;删除单个列表、集合、有序集合或哈希表类型的key
,时间复杂度为O(M)
,M
为以上数据结构内的元素数量。
删除指定的一个或者多个key
,不存在的key
会被忽略。
返回值: 被删除的key
的数量。redis
EXPIRE key seconds
时间复杂度为O(1)。
为给定的key
设置生存时间,当key
过时时,它会被自动删除。
返回值: 设置成功返回1
,当key
不存在或者设置失败的时候返回0
。sql
PERSIST key
时间复杂度为O(1)。
移除给定key
的生存时间,将这个key
转换成持久的。
返回值: 当生存时间移除成功时,返回1
,若是key
不存在或者没有设置生存时间,返回0
。
代码演示:mongodb
redis> SET mykey "Hello"
OK
redis> EXPIRE mykey 10 # 为 key 设置生存时间
(integer) 1
redis> TTL mykey
(integer) 10
redis> PERSIST mykey # 移除 key 的生存时间
(integer) 1
redis> TTL mykey
(integer) -1
复制代码
key
的剩余生存时间(TTL,time to live)。key
不存在时,返回-2
,当key
存在可是没有设置生存时间时,返回-1
,不然返回key
的剩余生存时间。# 不存在的 key
redis> FLUSHDB
OK
redis> TTL key
(integer) -2
# key 存在,但没有设置剩余生存时间
redis> SET key value
OK
redis> TTL key
(integer) -1
# 有剩余生存时间的 key
redis> EXPIRE key 10086
(integer) 1
redis> TTL key
(integer) 10084
复制代码
这里介绍Redis的五种数据结构String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Zset(即Sorted Set有序集合)的结构和一些命令。数据库
字符串是Redis中最基础的数据结构。ruby
字符串的值虽然是字符串可是能够保存不少种类型的数据,如:简单的字符串、JSON、XML、数字、二进制等。须要注意一点的是,Redis中字符串类型的值最大能保存512MB。
value
关联到key
,若是key
已经持有其余值,SET
就覆写旧值,无视类型,当SET
命令对一个带有生存时间(TTL)的键进行设置以后,该键原有的TTL将被清除。EX seconds
:将键的过时时间设置为seconds
秒。 执行SET key value EX seconds
的效果等同于执行SETEX key seconds value
。PX milliseconds
:将键的过时时间设置为milliseconds
毫秒。执行SET key value PX milliseconds
的效果等同于执行PSETEX key milliseconds value
。NX
:只在键不存在时,才对键进行设置操做。执行SET key value NX
的效果等同于执行SETNX key value
。XX
:只在键已经存在时,才对键进行设置操做。由于
SET
命令能够经过参数来实现SETNX
、SETEX
以及PSETEX
命令的效果,因此Redis
未来的版本可能会移除并废弃SETNX
、SETEX
和PSETEX
这三个命令。
返回值: 在Redis 2.6.12版本之前,SET
命令老是返回OK
。
从Redis 2.6.12版本开始,SET
命令只在设置操做成功完成时才返回OK
;若是命令使用了NX
或者XX
选项, 可是由于条件没达到而形成设置操做未执行, 那么命令将返回空批量回复(NULL Bulk Reply)。
代码演示:
# 使用 EX 选项
redis> SET key-with-expire-time "hello" EX 10086
OK
redis> GET key-with-expire-time
"hello"
redis> TTL key-with-expire-time
(integer) 10069
复制代码
key
相关联的字符串值。key
不存在,那么返回特殊值nil
;不然,返回键key
的值。key
的值并不是字符串类型,那么返回一个错误,由于GET
命令只能用于字符串值。redis> GET db
(nil)
redis> SET db redis
OK
redis> GET db
"redis"
复制代码
N
为被删除的key
的数量,其中删除单个字符串类型的key
,时间复杂度为O(1)
;删除单个列表、集合、有序集合或哈希表类型的key
,时间复杂度为O(M)
,M
为以上数据结构内的元素数量。key
,不存在的key
会被忽略。key
的数量。# 同时删除多个 key
redis> SET name "redis"
OK
redis> SET type "key-value store"
OK
redis> SET website "redis.com"
OK
redis> DEL name type website
(integer) 3
复制代码
N
为被设置的键数量。MSET
将使用新值去覆盖旧值,若是这不是你所但愿的效果,请考虑使用MSETNX
命令,这个命令只会在全部给定键都不存在的状况下进行设置。MSET
是一个原子性(atomic) 操做,全部给定键都会在同一时间内被设置,不会出现某些键被设置了可是另外一些键没有被设置的状况。MSET
命令老是返回OK
。redis> MSET date "2012.3.30" time "11:00 a.m." weather "sunny"
OK
redis> MGET date time weather
1) "2012.3.30"
2) "11:00 a.m."
3) "sunny"
复制代码
N
为被设置的键数量。MSETNX
命令也会拒绝执行对全部键的设置操做。MSETNX
是一个原子性(atomic) 操做,全部给定键要么就所有都被设置,要么就所有都不设置,不可能出现第三种状态。1
;若是由于某个给定键已经存在而致使设置未能成功执行,那么命令返回0
。redis> MSETNX rmdbs "MySQL" nosql "MongoDB" key-value-store "redis"
(integer) 1
redis> MGET rmdbs nosql key-value-store
1) "MySQL"
2) "MongoDB"
3) "redis"
复制代码
N
为给定键的数量。nil
表示。MGET
命令将返回一个列表,列表中包含了全部给定键的值。redis> SET redis redis.com
OK
redis> SET mongodb mongodb.org
OK
redis> MGET redis mongodb
1) "redis.com"
2) "mongodb.org"
redis> MGET redis mongodb mysql # 不存在的 mysql 返回 nil
1) "redis.com"
2) "mongodb.org"
3) (nil)
复制代码
N次GET和一次MGET对比
总所周知,Redis采用的是客户端-服务器方式,即在一次round trip中,客户端发送一条命令,服务器解析命令并执行,而后向客户端返回结果,若是执行N
条命令,就是N
个请求N
次执行N
个返回
N
条命令都放在一个请求中,一次请求多个执行一个返回,那么就能够大大的下降网络时间的开销,这个也就是Redis的pipline
N次SET和一次MSET对比
同7
Redis的哈希是键值对的集合,是字符串字段和字符串值之间的映射。
Hash
数据结构即数据存储为field
、value
的格式存储
field
、
value
当作一对键值对结构
key
中域field
的值设置为value
,若是给定的哈希表不存在,那么一个新的哈希表将被建立并执行HSET
操做,若是域field
已存在于哈希表中,那么它的旧值将被新值value
覆盖。HSET
命令在哈希表中新建立field
域并成功为它设置值时,命令返回1
;若是域field
已经存在于哈希表,而且HSET
命令成功使用新值覆盖了它的旧值,那么命令返回0
。redis> HSET website google "www.g.cn"
(integer) 1
redis> HGET website google
"www.g.cn"
复制代码
HGET
命令在默认状况下返回给定域的值,若是给定域不存在于哈希表中,又或者给定的哈希表并不存在,那么命令返回nil
。 代码演示:redis> HSET homepage redis redis.com
(integer) 1
redis> HGET homepage redis
"redis.com"
复制代码
N
为哈希表的大小,谨慎用。key
不存在,返回空列表。 代码演示:redis> HSET people jack "Jack Sparrow"
(integer) 1
redis> HSET people gump "Forrest Gump"
(integer) 1
redis> HGETALL people
1) "jack" # 域
2) "Jack Sparrow" # 值
3) "gump"
4) "Forrest Gump"
复制代码
N
为要删除的域的数量。key
中的一个或多个指定域,不存在的域将被忽略。# 测试数据
redis> HGETALL abbr
1) "a"
2) "apple"
3) "b"
4) "banana"
5) "c"
6) "cat"
7) "d"
8) "dog"
# 删除单个域
redis> HDEL abbr a
(integer) 1
# 删除不存在的域
redis> HDEL abbr not-exists-field
(integer) 0
# 删除多个域
redis> HDEL abbr b c
(integer) 2
redis> HGETALL abbr
1) "d"
2) "dog"
复制代码
N
为field-value
对的数量。field-value
(域-值)对设置到哈希表key
中,此命令会覆盖哈希表中已存在的域,若是key
不存在,一个空哈希表被建立并执行HMSET
操做。OK
,当key
不是哈希表(hash)类型时,返回一个错误。 代码演示:redis> HMSET website google www.google.com yahoo www.yahoo.com
OK
redis> HGET website google
"www.google.com"
redis> HGET website yahoo
"www.yahoo.com"
复制代码
N
为给定域的数量。key
中,一个或多个给定域的值,若是给定的域不存在于哈希表,那么返回一个nil
值,由于不存在的key
被看成一个空哈希表来处理,因此对一个不存在的key
进行HMGET
操做将返回一个只带有nil
值的表。redis> HMSET pet dog "doudou" cat "nounou" # 一次设置多个域
OK
redis> HMGET pet dog cat fake_pet # 返回值的顺序和传入参数的顺序同样
1) "doudou"
2) "nounou"
3) (nil) # 不存在的域返回nil值
复制代码
N
次GET
和一次MGET
对比,大概相同列表用于储存多个有序的字符串,列表是一种比较灵活的数据结构,能够充当栈和队列的角色。
列表的value
实际上是一个双向链表,能够在链表的两头插入或者删除元素
value
插入到列表key
的表头,若是有多个value
值,那么各个value
值按从左到右的顺序依次插入到表头:好比说,对空列表mylist
执行命令LPUSH mylist a b c
,列表的值将是c b a
,这等同于原子性地执行LPUSH mylist a
、LPUSH mylist b
和LPUSH mylist c
三个命令,若是key
不存在,一个空列表会被建立并执行LPUSH
操做,当key
存在但不是列表类型时,返回一个错误。LPUSH
命令后,列表的长度。 代码演示:# 加入单个元素
redis> LPUSH languages python
(integer) 1
# 加入重复元素
redis> LPUSH languages python
(integer) 2
redis> LRANGE languages 0 -1 # 列表容许重复元素
1) "python"
2) "python"
# 加入多个元素
redis> LPUSH mylist a b c
(integer) 3
redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"
复制代码
value
插入到列表key
的表尾(最右边),若是有多个value
值,那么各个value
值按从左到右的顺序依次插入到表尾:好比说,对空列表mylist
执行命令RPUSH mylist a b c
,列表的值将是c b a
,这等同于原子性地执行RPUSH mylist a
、RPUSH mylist b
和RPUSH mylist c
三个命令,若是key
不存在,一个空列表会被建立并执行RPUSH
操做,当key
存在但不是列表类型时,返回一个错误。RPUSH
命令后,列表的长度。 代码演示:# 添加单个元素
redis> RPUSH languages c
(integer) 1
# 添加剧复元素
redis> RPUSH languages c
(integer) 2
redis> LRANGE languages 0 -1 # 列表容许重复元素
1) "c"
2) "c"
# 添加多个元素
redis> RPUSH mylist a b c
(integer) 3
redis> LRANGE mylist 0 -1
1) "a"
2) "b"
3) "c"
复制代码
key
新的头元素。key
不存在时,返回nil
。 代码演示:# 加入单个元素
redis> LLEN course
(integer) 0
redis> RPUSH course algorithm001
(integer) 1
redis> RPUSH course c++101
(integer) 2
redis> LPOP course # 移除头元素
"algorithm001"
复制代码
key
新的尾元素。key
不存在时,返回nil
。 代码演示:redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> RPOP mylist # 返回被弹出的元素
"three"
redis> LRANGE mylist 0 -1 # 列表剩下的元素
1) "one"
2) "two"
复制代码
N
为到达下标index
过程当中通过的元素数量。所以,对列表的头元素和尾元素执行LINDEX
命令,复杂度为O(1)。key
中,下标为index
的元素,下标(index)参数start
和stop
都以0
为底,也就是说,以0
表示列表的第一个元素,以1
表示列表的第二个元素,以此类推,你也可使用负数下标,以-1
表示列表的最后一个元素,-2
表示列表的倒数第二个元素,以此类推,若是key
不是列表类型,返回一个错误。index
的元素。若是index
参数的值不在列表的区间范围内(out of range),返回nil
。redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LINDEX mylist 0
"Hello"
redis> LINDEX mylist -1
"World"
redis> LINDEX mylist 3 # index不在 mylist 的区间范围内
(nil)
复制代码
N
为寻找pivot
过程当中通过的元素数量。value
插入到列表key
当中,位于值pivot
以前或以后,当pivot
不存在于列表key
时,不执行任何操做,当key
不存在时,key
被视为空列表,不执行任何操做,若是key
不是列表类型,返回一个错误。pivot
,返回-1
。若是key
不存在或为空列表,返回0
。redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2
redis> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"
# 对一个非空列表插入,查找一个不存在的 pivot
redis> LINSERT mylist BEFORE "go" "let's"
(integer) -1 # 失败
# 对一个空列表执行 LINSERT 命令
redis> EXISTS fake_list
(integer) 0
redis> LINSERT fake_list BEFORE "nono" "gogogog"
(integer) 0 # 失败
复制代码
Redis的Set
是String
类型的无序集合,这里的集合也就是咱们小学都接触到的集合,能够求交集、并集、差集等。集合成员是惟一的,这就意味着集合中不能出现重复的数据。集合是经过哈希表实现的,因此添加,删除,查找的复杂度都是 O(1)。
左边为key
,是字符串类型。右边为value
,能够将一些字符串进行一些组合,是集合类型。Redis中的集合类型还支持集合之间的操做,这与Redis中的其余数据结构是不一样的,Redis能够对两个集合进行操做,取两个集合的交集,并集,差集以及对称差集等。
N
为被添加的元素的数量。member
元素加入到集合key
当中,已经存在于集合的member
元素将被忽略,假如key
不存在,则建立一个只包含member
元素做成员的集合,当key
不是集合类型时,返回一个错误。# 添加单个元素
redis> SADD bbs "discuz.net"
(integer) 1
# 添加剧复元素
redis> SADD bbs "discuz.net"
(integer) 0
# 添加多个元素
redis> SADD bbs "tianya.cn" "groups.google.com"
(integer) 2
redis> SMEMBERS bbs
1) "discuz.net"
2) "groups.google.com"
3) "tianya.cn"
复制代码
count
个元素并返回被移除的元素。key
不存在或key
是空集时,返回nil
。redis> SMEMBERS db
1) "MySQL"
2) "MongoDB"
3) "Redis"
redis> SPOP db
"Redis"
redis> SMEMBERS db
1) "MySQL"
2) "MongoDB"
redis> SPOP db
"MySQL"
redis> SMEMBERS db
1) "MongoDB"
复制代码
N
为给定member
元素的个数。key
中的一个或多个member
元素,不存在的member
元素会被忽略,当key
不是集合类型,返回一个错误。# 测试数据
redis> SMEMBERS languages
1) "c"
2) "lisp"
3) "python"
4) "ruby"
# 移除单个元素
redis> SREM languages ruby
(integer) 1
# 移除不存在元素
redis> SREM languages non-exists-language
(integer) 0
# 移除多个元素
redis> SREM languages lisp python c
(integer) 3
redis> SMEMBERS languages
(empty list or set)
复制代码
N
为集合的基数。key
中的全部成员,不存在的key
被视为空集合。# key 不存在或集合为空
redis> EXISTS not_exists_key
(integer) 0
redis> SMEMBERS not_exists_key
(empty list or set)
# 非空集合
redis> SADD language Ruby Python Clojure
(integer) 3
redis> SMEMBERS language
1) "Python"
2) "Ruby"
3) "Clojure"
复制代码
Redis有序集合和集合同样也是String
类型元素的集合,且不容许重复的成员。不一样的是每一个元素都会关联一个double
类型的分数。Redis正是经过分数来为集合中的成员进行从小到大的排序。有序集合的成员是惟一的,但分数(score)却能够重复。集合是经过哈希表实现的,因此添加,删除,查找的复杂度都是O(1)。
有序集合的value
包括score
和value
两部分,其中score
表示分值用来排序的
N
是有序集的基数,M
为成功添加的新成员的数量。member
元素及其score
值加入到有序集key
当中。若是某个member
已是有序集的成员,那么更新这个member
的score
值,并经过从新插入这个member
元素,来保证该member
在正确的位置上。score
值能够是整数值或双精度浮点数。若是key
不存在,则建立一个空的有序集并执行ZADD
操做。当key
存在但不是有序集类型时,返回一个错误。ZADD
命令添加了NX
、XX
、CH
、INCR
四个选项:NX
:member
必须不存在,才能够设置成功,用于添加。XX
:member
必须存在,才能够设置成功,用于更新。CH
:返回这次操做后,有序集合元素和分数发生变化的个数。INCR
:对score
作增长,至关于ZINCRBY
。 返回值: 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。redis> ZADD ztest 100 java 99 python 80 go 120 kotlin
(integer) 4
# 查看有序集合内全部元素而且按分数排序
coderknock> ZRANGE ztest 0 -1 WITHSCORES
1) "go"
2) "80"
3) "python"
4) "99"
5) "java"
6) "100"
7) "kotlin"
8) "120"
# 选项填写在 key 后面,位置不能错误
redis> ZADD ztest 100 java 99 python 80 go 120 kotlin CH
(error) ERR syntax error
redis> ZADD CH ztest 100 java 99 python 80 go 120 kotlin
(error) ERR syntax error
# 下面两个语句进行了对比,若是不加 CH 显示的数量不包括更新和已经存在的。
redis> ZADD ztest CH 100 java 99 python 80 go 121 kotlin
(integer) 1
redis> ZADD ztest 100 java 99 python 80 go 120 kotlin
(integer) 0
复制代码
N
是有序集的基数,M
为成功移除的成员的数量。key
中的一个或多个成员,不存在的成员将被忽略,当key
存在但不是有序集类型时,返回一个错误。# 测试数据
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
5) "google.com"
6) "10"
# 移除单个元素
redis> ZREM page_rank google.com
(integer) 1
redis> ZRANGE page_rank 0 -1 WITHSCORES
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
# 移除多个元素
redis> ZREM page_rank baidu.com bing.com
(integer) 2
redis> ZRANGE page_rank 0 -1 WITHSCORES
(empty list or set)
# 移除不存在元素
redis> ZREM page_rank non-exists-element
(integer) 0
复制代码