redis学习笔记

redis是键值对数据库,redis的值不仅可以是字符串,还可以是字符串、列表、散列、集合、有序集合、HyperLogLog。 redis将数据存储在内存,读写数据的时候不会收到磁盘IO速度的限制,所以速度快。
一、基本操作
1、字符串键
Redis 字符串数据类型的相关命令用于管理 redis 字符串值,基本语法如下:
1.1为字符串键设置值:
1.1.1SET key value
复杂度为 O(1) 。
redis> SET msg "hello world"
OK
redis> SET msg "goodbye" # 覆盖原来的值 "hello world"
OK
1.1.2 SET key value [NX|XX]
如果给定了 NX 选项,那么命令仅在键 key 不存在的情况下,才进行设置操作;如果键 key 已经存
在,那么 SET ... NX 命令不做动作(不会覆盖旧值)。
如果给定了 XX 选项,那么命令仅在键 key 已经存在的情况下,才进行设置操作;如果键 key 不存
在,那么 SET ... XX 命令不做动作(一定会覆盖旧值)。
在给定 NX 选项和 XX 选项的情况下,SET 命令在设置成功时返回 OK ,设置失败时返回 nil 。
redis> SET nx-str "this will fail" XX # 键不存在,指定 XX 选项导致设置失败
(nil)
redis> SET nx-str "this will success" NX # 键不存在,所以指定 NX 选项是可行的
OK
redis> SET nx-str "this will fail" NX # 键已经存在,指定 NX 选项导致设置失败
(nil)
redis> SET nx-str "this will success again!" XX # 键已经存在,指定 XX 选项是可行的
OK
1.2获取字符串的值
1.2.1GET key
返回字符串键 key 储存的值。
复杂度为 O(1) 。
redis> SET msg "hello world"
OK
redis> GET msg
hello world
1.3仅在键不存在的情况下进行设置
1.3.1 SETNX key value
仅在键 key 不存在的情况下,将键 key 的值设置为 value ,效果和 SET key value NX 一样。
NX 的意思为“Not eXists”(不存在)。
键不存在并且设置成功时,命令返回 1 ;因为键已经存在而导致设置失败时,命令返回 0 。
复杂度为 O(1) 。
redis> SETNX new-key "i am a new key!"
1
redis> SETNX new-key "another new key here!" # 键已经存在,设置失败
0
redis> GET new-key # 键的值没有改变
i am a new key!
1.4一次设置多个不存在的键
1.4.1 MSETNX key value [key value ...]
只有在所有给定键都不存在的情况下, MSETNX 会为所有给定键设置值,效果和同时执行多个
SETNX 一样。如果给定的键至少有一个是存在的,那么 MSETNX 将不执行任何设置操作。
返回 1 表示设置成功,返回 0 表示设置失败。复杂度为 O(N) , N 为给定的键数量。
redis> MSETNX nx-1 "hello" nx-2 "world" nx-3 "good luck"
1
redis> SET ex-key "bad key here"
OK
redis> MSETNX nx-4 "apple" nx-5 "banana" ex-key "cherry" nx-6 "durian"
0
因为 ex-key 键已经存在,所以第二个 MSETNX 会执行失败,所有键都不会被设置。
1.5 设置新值并返回旧值
1.5.1 GETSET key new-value
将字符串键的值设置为 new-value ,并返回字符串键在设置新值之前储存的旧值(old value)。
复杂度为 O(1) 。
redis> SET getset-str "i'm old value" # 先给字符串键设置一个值
OK
redis> GETSET getset-str "i'm new value" # 更新字符串键的值,并返回之前储存的旧值
i'm old value
redis> GET getset-str # 确认一下,新值已被设置
i'm new value
1.6 追加内容到字符串末尾
1.6.1APPEND key value
将值 value 推入到字符串键 key 已储存内容的末尾。
O(N), 其中 N 为被推入值的长度。
redis> SET myPhone "nokia"
OK
redis> APPEND myPhone "-1110"
(integer) 10
redis> GET myPhone
"nokia-1110"
1.7 返回值的长度
1.7.1STRLEN key
返回字符串键 key 储存的值的长度。
因为 Redis 会记录每个字符串值的长度,所以获取该值的复杂度为 O(1) 。
redis> SET msg "hello"
OK
redis> STRLEN msg
(integer) 5
redis> APPEND msg " world"
(integer) 11
redis> STRLEN msg
(integer) 11
1.8索引
字符串的索引( index)以 0 为开始,从字符串的开头向字符串的结尾依次递增,字符串第一个字符的索
引为 0 ,字符串最后一个字符的索引为 N-1 ,其中 N 为字符串的长度。
除了(正数)索引之外,字符串还有负数索引:负数索引以 -1 为开始,从字符串的结尾向字符串的开头
依次递减,字符串的最后一个字符的索引为 -N ,其中 N 为字符串的长度。
1.8.1范围设置
SETRANGE key index value
从索引 index 开始,用 value 覆写(overwrite)给定键 key 所储存的字符串值。只接受正数索引。
命令返回覆写之后,字符串值的长度。复杂度为 O(N), N 为 value 的长度。
redis> SET msg "hello"
OK
redis> SETRANGE msg 1 "appy"
(integer) 5
redis> GET msg
"happy"
1.8.2范围取值
GETRANGE key start end
返回键 key 储存的字符串值中,位于 start 和 end 两个索引之间的内容(闭区间,start 和 end 会被包括
在内)。和 SETRANGE 只接受正数索引不同, GETRANGE 的索引可以是正数或者负数。
复杂度为 O(N) , N 为被选中内容的长度。
redis> SET msg "hello world"
OK
redis> GETRANGE msg 0 4
"hello"
redis> GETRANGE msg -5 -1
"world"

1.9数字操作
增加或者减少字符串键储存的数字值。只要储存在字符串键里面的值可以被解释为 64 位整数,或者 IEEE-754 标准的 64 位浮点数,那么用户就可以对这个字符串键执行针对数字值的命令。
对于一个保存着数字的字符串键 key ,我们可以使用 INCRBY 命令来增加它的值,或者使用 DECRBY
命令来减少它的值。如果执行 INCRBY 或者 DECRBY 时,键 key 不存在,那么命令会将键 key 的
值初始化为 0 ,然后再执行增加或者减少操作。
1.9.1INCRBY / DECRBY 示例
redis> INCRBY num 100 # 键 num 不存在,命令先将 num 的值初始化为 0 ,
(integer) 100 # 然后再执行加 100 操作
redis> INCRBY num 25 # 将值再加上 25
(integer) 125
redis> DECRBY num 10 # 将值减少 10
(integer) 115
redis> DECRBY num 50 # 将值减少 50
(integer) 65
1.9.2增一和减一
因为针对数字值的增一和减一操作非常常见,所以 Redis 特别为这两个操作创建了 INCR 命令和
DECR 命令。
redis> SET num 10
OK
redis> INCR num
(integer) 11
redis> DECR num
(integer) 10

1.10浮点数的自增和自减
1.10.1 INCRBYFLOAT key increment
为字符串键 key 储存的值加上浮点数增量 increment ,命令返回操作执行之后,键 key 的值。
没有相应的 DECRBYFLOAT ,但可以通过给定负值来达到 DECRBYFLOAT 的效果。
复杂度为 O(1) 。
redis> SET num 10
OK
redis> INCRBYFLOAT num 3.14
"13.14"
redis> INCRBYFLOAT num -2.04 # 通过传递负值来达到做减法的效果
"11.1"
注:即使字符串键储存的是数字值,它也可以执行 APPEND、STRLEN、SETRANGE 和 GETRANGE 。
当用户针对一个数字值执行这些命令的时候,Redis 会先将数字值转换为字符串,然后再执行命令。
redis> SET number 123
OK
redis> STRLEN number # 转换为 "123" ,然后计算这个字符串的长度
3
redis > APPEND number 456 # 转换为 "123" ,然后与 "456" 进行拼接
6
redis> GET number
123456
1.11二进制数据操作
设置和获取字符串储存的二进制数据,执行二进制位运算
1.11.1设置和获取二进制数据
SET 、GET 、SETNX、 APPEND 等命令同样可以用于设置二进制数据。
# 因为 Redis 自带的客户端 redis-cli 没办法方便的设置二进制数据
# 所以这里使用 Python 客户端来进行
>>> import redis
>>> r = redis.Redis()
>>> r.set('bits', 0b10010100) # 将字符串键 bits 的值设置为二进制 10010100
True
>>> bin(int(r.get('bits'))) # 获取字符串键 bits 储存的二进制值(需要进行转换)
'0b10010100'
>>> r.append('bits', 0b111) # 将 0b111 (也即是十进制的 7)推入到 bits 已有二进制位的末尾
4L
>>> bin(int(r.get('bits'))) # 推入之前的值为 0b10010100 = 148
'0b10111001111' # 推入之后的值为 0b10111001111 = 1487
1.11.2二进制位的索引
和储存文字时一样,字符串键在储存二进制位时,索引也是从 0 开始的。
但是和储存文字时,索引从左到右依次递增不同,当字符串键储存的是二进制位时,二进制位的索引会
从左到右依次递减。

1.11.3设置二进制位的值
SETBIT key index value
将给定索引上的二进制位的值设置为 value ,命令返回被设置的位原来储存的旧值。
复杂度为 O(1) 。
redis> SETBIT bits 2 1
(integer) 0
1.11.4获取二进制位的值
GETBIT key index
返回给定索引上的二进制位的值。
复杂度为 O(1) 。
redis> GETBIT bits 7
(integer) 1
redis> GETBIT bits 6
(integer) 0
redis> GETBIT bits 4
(integer) 1

1.11.5计算值为 1 的二进制位的数量
BITCOUNT key [start] [end]
计算并返回字符串键储存的值中,被设置为 1 的二进制位的数量。
一般情况下,给定的整个字符串键都会进行计数操作,但通过指定额外的 start 或 end 参数,可以让计
数只在特定索引范围的位上进行。
start 和 end 参数的设置和 GETRANGE 命令类似,都可以使用负数值:比如 -1 表示最后一个位,而 -2
表示倒数第二个位,以此类推。
复杂度为 O(N) ,其中 N 为被计算二进制位的数量。




2、散列
一个散列由多个域值对(field-value pair)组成,散列的域和值都可以是文字、整数、浮点数或者二进制数据。同一个散列里面的每个域必须是独一无二、各不相同的,而域的值则没有这一要求,换句话说,不同域的值可以是重复的。通过命令,用户可以对散列执行设置域值对、获取域的值、检查域是否存在等操作,也可以让 Redis 返回散列包含的所有域、所有值或者所有域值对。
2.1关联域值对
HSET key field value
在散列键 key 中关联给定的域值对 field 和 value 。
如果域 field 之前没有关联值,那么命令返回 1 ;
如果域 field 已经有关联值,那么命令用新值覆盖旧值,并返
回 0 。
复杂度为 O(1) 。
redis> HSET message "id" 10086
(integer) 1
redis> HSET message "sender" "peter"
(integer) 1
redis> HSET message "receiver" "jack"
(integer) 1
2.2获取域关联的值
HGET key field
返回散列键 key 中,域 field 所关联的值。如果域 field 没有关联值,那么返回 nil 。
复杂度为 O(1) 。
redis> HGET message "id"
"10086"
redis> HGET message "sender"
"peter"
redis> HGET message "content"
"Good morning, jack!"
redis> HGET message "NotExistsField"
(nil)
2.3仅当域不存在时,关联域值对
HSETNX key field value
如果散列键 key 中,域 field 不存在(也即是, 还没有与之相关联的值),那么关联给定的域值对 field 和
value 。
如果域 field 已经有与之相关联的值,那么命令不做动作。
复杂度为 O(1) 。
redis> HSETNX message "content" "Good morning, jack!"
(integer) 1
redis> HSETNX message "content" "Good morning, jack!"
(integer) 0
2.4检查域是否存在
HEXISTS key field
查看散列键 key 中,给定域 field 是否存在:存在返回 1 ,不存在返回 0 。
复杂度为 O(1) 。
redis> HEXISTS message "id"
(integer) 1
redis> HEXISTS message "sender"
(integer) 1
redis> HEXISTS message "content"
(integer) 0
redis> HEXISTS message "NotExistsField"
(integer) 0
2.5删除给定的域值对
HDEL key field [field ...]
删除散列键 key 中的一个或多个指定域,以及那些域的值。
不存在的域将被忽略。命令返回被成功删除的域值对数量。
复杂度为 O(N) ,N 为被删除的域值对数量。
redis> HDEL message "id"
(integer) 1
redis> HDEL message "receiver"
(integer) 1
redis> HDEL message "sender"
(integer) 1
2.6获取散列包含的键值对数量
HLEN key
返回散列键 key 包含的域值对数量。
复杂度为 O(1) 。
redis> HLEN message
(integer) 4
redis> HDEL message "date"
(integer) 1
redis> HLEN message
(integer) 3
2.7批量操作
2.7.1一次设置或获取散列中的多个域值对

redis> HMSET message "id" 10086 "sender" "peter" "receiver" "jack"
OK
redis> HMGET message "id" "sender" "receiver"
1) "10086"
2) "peter"
3) "jack"
2.7.2获取散列包含的所有域、值、或者域值对

为什么命令叫 HKEYS 而不是 HFIELDS ?
对于散列来说,key 和 field 表示的是同一个意思,并且 key 比 field 更容易拼写,
所以 Redis 选择使用 HKEYS 来做命令的名字,而不是 HFIELDS 。
2.8数字操作
2.8.1对域的值执行自增操作

虽然 Redis 没有提供与以上两个命令相匹配的 HDECRBY 命令和 HDECRBYFLOAT 命令,但我们同样可以通过
将 increment 设为负数来达到做减法的效果。
redis> HINCRBY numbers x 100 # 域不存在,先将值初始化为 0 ,然后再执行 HINCRBY 操作
(integer) 100
redis> HINCRBY numbers x -50 # 传入负值,做减法
(integer) 50
redis> HINCRBYFLOAT numbers x 3.14 # 浮点数计算
"53.14"
2.9散列键和字符串键
2.9.1使用散列的好处(1):将数据放到同一个地方
散列可以让我们将一些相关的信息储存在同一个地方,而不是直接分散地储存在整个数据库里面,这不
仅方便了数据管理,还可以尽量避免误操作发生。
redis> MSET "id" 10086
"sender" "peter"
"receiver" "jack"
OK
redis> HMSET message
"id" 10086
"sender" "peter"
"receiver" "jack"
OK
举个例子,要删除字符串键记录
的消息信息,我们需要输入三个
键,而要删除散列键储存的消息
信息,我们只要输入一个键。
2.9.2使用散列的好处(2):避免键名冲突
在介绍字符串键的时候,我们说过,可以在命名键的时候,使用分割符来避免命名冲突,但更好的办法是
直接使用散列键来储存键值对数据。
举个例子,如果我们需要储存多条消息,那么我们可能会按照格式 message::<id>::<field> 的方式来创
建字符串键并储存数据,比如使用 message::12345::receiver 键来储存 id 为 12345 的消息的接收者,
使用 message::10086::sender 键来储存 id 为 10086 的发送者,诸如此类。
但更好的办法是直接使用 message:<id> 散列键来表示消息信息,并将与消息有关的各项信息储存到散
列的各个域里面,比如创建 message::12345 散列,并将该消息的各项信息储存分别储存到这个散列的
id 域、receiver 域和 sender 域里面。
这保证了数据库中每个键的作用都是固定的、单一的,储存的信息都是被隔离的,从而最大限度地避免
键名冲突。
对比
以下两个数据库分别以字符串键和散列键两种形式保存了相同的信息,但是很明显,使用字符串键的
数据库创建的键数量多,而使用散列键的数据库创建的键数量则少。
随着域数量的增加,使用散列会比使用字符串少创建很多数据库键。

2.9.3使用散列的好处(3):减少内存占用
在一般情况下,保存相同数量的键值对信息,使用散列键比使用字符串键更节约内存。
因为在数据库里面创建的每个键都带有数据库附加的管理信息(比如这个键的类型、最后一次被访问
的时间等等),所以数据库里面的键越多,服务器在储存附加管理信息方面耗费的内存就越多,花在管
理数据库键上的 CPU 也会越多。
除此之外,当散列包含的域值对数量比较少的时候,Redis 会自动使用一种占用内存非常少的数据结
构来做散列的底层实现,在散列的数量比较多的时候,这一措施对减少内存有很大的帮助。
2.9.4结论
只要有可能的话,就尽量使用散列键而不是字符串键来储存键值对数据,因为散列键管理方便、能够避
免键名冲突、并且还能够节约内存。
一些没办法使用散列键来代替字符串键的情况:
1. 使用二进制位操作命令:因为 Redis 目前支持对字符串键进行 SETBIT、GETBIT、BITOP 等操作,
如果你想使用这些操作,那么只能使用字符串键。
2. 使用过期功能:Redis 的键过期功能目前只能对键进行过期操作,而不能对散列的域进行过期操
作,因此如果你要对键值对数据使用过期功能的话,那么只能把键值对储存在字符串里面。关于过
期键的详细信息会在之后介绍。
3、列表
3.1从列表的左端推入值
LPUSH key value [value ...]
将一个或以上数量的值依次推入到列表的左端命令返回新值被推入之后,列表之前包含的 项的数量
复杂度为 O(N) ,其中 N 为被推入的值的数量,如果只推入一个值,那么命令的复杂度为 O(1)
redis> LPUSH lst "Lua"
(integer) 1
redis> LPUSH lst "Python"
(integer) 2
redis> LPUSH lst "C"
(integer) 3
从列表的左端推入多个值:
redis> LPUSH lst "Lua" "Python" "C"
(integer) 3
和依次执行以下三个命令效果一样:
LPUSH lst "Lua"
LPUSH lst "Python"
LPUSH lst "C"
提示:值被推入的顺序和参数给定是顺序正好相反。
3.2从列表的右端推入值
RPUSH key value [value ...]
例:redis> RPUSH lst "Clojure"
(integer) 1
redis> RPUSH lst "Ruby"
(integer) 2
redis> RPUSH lst "C"
(integer) 3
从列表的右端推入多个值:
redis> RPUSH lst "Clojure" "Ruby" "C"
(integer) 3
和依次执行以下三个命令效果一样:
RPUSH lst "Clojure"
RPUSH lst "Ruby"
RPUSH lst "C"
提示:值被推入的顺序和参数给定是顺序正好相反。
3.3从列表的两端弹出项

redis> RPUSH lst "Clojure" "Ruby" "C" "Python" "Lua"
(integer) 5
redis> LPOP lst
"Clojure"
redis> LPOP lst
"Ruby"
redis> RPOP lst
"Lua"
redis> RPOP lst
"Python"
3.4获取列表的长度:
LLEN key
redis> LLEN lst
(integer) 5
redis> LPOP lst
"Clojure"
redis> LLEN lst
(integer) 4
3.5返回给定索引上的项:
LINDEX key index

redis> LINDEX lst 1
"Ruby"
redis> LINDEX lst 4
"Lua"
redis> LINDEX lst -3
"C"
3.6 返回给定索引范围之内的所有项
LRANGE key start stop
redis> LRANGE lst 0 2
1) "Clojure"
2) "Ruby"
3) "C"
redis> LRANGE lst -3 -1
1) "C"
2) "Python"
3) "Lua"
3.7设定指定索引上的列表项
LSET key index value
3.8在指定位置插入列表项
LINSERT key BEFORE|AFTER pivot value
3.9从列表中删除指定的值
LREM key count value

4、集合键
Redis 的集合以无序的方式储存多个各不相同的元素。
4.1添加元素
SADD key element [element ...]
如果已经存在,则忽略,命令返回新添加到集合的元素数量。
redis> SADD friends "peter"
(integer) 1
redis> SADD friends "jack" "tom" "john"
(integer) 3
redis> SADD friends "may" "tom"
(integer) 1
4.2移除元素
SREM key element [element ...]
移除集合中一个或者多个元素,如果不存在集合中,则忽略。
redis> SREM friends "peter"
(integer) 1
redis> SREM friends "tom" "john"
(integer) 2
4.3检查给定元素是否存在集合中
SISMEMBER key element
如果存在,返回1,不存在返回0。
redis> SISMEMBER friends "peter"
(integer) 1
redis> SISMEMBER friends "li lei"
(integer) 0
redis> SISMEMBER NOT-EXISTS-KEY "element"
(integer) 0
4.4返回集合的大小
SCARD key
redis> SCARD friends
(integer) 6
redis> SREM friends "peter" "jack" "tom"
(integer) 3
redis> SCARD friends
(integer) 3
4.5返回集合所包含的所有元素
SMEMBERS key
redis> SMEMBERS friends
1) "jack"
2) "peter"
3) "may"
4) "tom"
5) "john"
6) "ben"
当集合的基数较大时,执行这个命令有可能会造成服务器阻塞,可以迭代集合中的元素。
4.6从集合中随机的弹出一个元素
SPOP key
redis> SADD friends "peter" "jack" "tom" "john" "may" "ben"
(integer) 6
redis> SPOP friends
"may"
redis> SMEMBERS friends
1) "tom"
2) "john"
3) "jack"
4) "peter"
5) "ben"
4.6从集合中随机的返回一个元素。
SRANDMEMBER key [count]
redis> SRANDMEMBER friends #随机的返回一个元素
"ben"
redis> SRANDMEMBER friends 3 # 从集合中随机的返回三个无重复的元素
1) "john"
2) "jack"
3) "peter"
redis> SRANDMEMBER friends -3 #从集合中随机的返回三个有可能重复的元素
1) "may"
2) "peter"
3) "may"
4.7计算集合
4.7.1SDIFF key [key ...] 计算所有给定集合的差集,
redis> SADD number1 "123" "456" "789"
(integer) 3
redis> SADD number2 "123" "456" "999"
(integer) 3
redis> SDIFF number1 number2
1) "789"
4.7.2 SDIFFSTORE destkey key [key ...] 计算所有给定集合的差集,并将结果储存在destkey
4.7.3 SINTER key [key ...] 计算所有给定集合的交集,并返回结果
redis> SADD number1 "123" "456" "789"
(integer) 3
redis> SADD number2 "123" "456" "887"
(integer) 3
redis> SINTER number1 number2
1) "123"
2) "456"
4.7.4 SINTERSTORE destkey key [key ...] 计算所有给定集合的交集,并将结果储存在destkey
4.7.5 SUNION key [key ...] 计算所有给定集合的并集,并返回结果
redis> SADD number1 "123" "456" "789"
(integer) 3
redis> SADD number2 "123" "456" "887"
(integer) 3
redis> SUNION number1 number2
1) "123"
2) "456"
3) "789"
4) "887"
4.7.6 SUNIONSTORE destkey key [key ...] 计算所有给定集合的并集,并将结果储存在destkey
4.8有序集合
有序集合和集合一样,都可以包含任意数量的、各不相同的元素( element),不同于集合的是,有序集
合的每个元素都关联着一个浮点数格式的分值(score),并且有序集合会按照分值,以从小到大的顺序
来排列有序集合中的各个元素。
虽然有序集合中的每个元素都必须是各不相同的,但元素的分值并没有这一限制,换句话来说,两个不
同元素的分值可以是相同的。
4.8.1 添加元素 ZADD key score element [[score element] [score element] ...]
按照给定的分值和元素,将任意数量的元素添加到有序集合里面,命令的返回值为成功添加的元素数
量。
redis> ZADD fruits-price 3.2 香蕉
1
redis> ZADD fruits-price 2.0 西瓜
1
redis> ZADD fruits-price 4.0 番石榴 7.0 梨 6.8 芒果
3
4.8.2 删除元素 ZREM key element [element ...]
从有序集合中删除指定的元素,以及这些元素关联的分值,命令返回被成功删除的元素数量。
redis> ZADD fruits-price …
5
redis> ZREM fruits-price 番石榴 梨 芒果
3
redis> ZREM fruits-price 西瓜
1
4.8.3 返回元素的分值
ZSCORE key element
返回有序集合中,指定元素的分值。
redis> ZSCORE fruits-price 西瓜
2
redis> ZSCORE fruits-price 香蕉
3.2000000000000002
redis> ZSCORE fruits-price 芒果
6.7999999999999998
4.8.4 增加或减少元素的分值
ZINCRBY key increment element
为有序集合指定元素的分值加上增量 increment ,命令返回执行操作之后,元素的分值。
没有相应的 ZDECRBY 命令,但可以通过将 increment 设置为负数来减少分值。
redis> ZINCRBY fruits-price 1.5 西瓜
3.5
redis> ZINCRBY fruits-price -0.8 香蕉
2.4000000000000004
4.8.5 返回有序集合的基数
ZCARD key
4.8.6 返回元素的排名(rank)ZRANK key element
返回指定元素在有序集合中的排名,其中排名按照元素的分值从小到大计算。
排名以 0 开始。
4.8.7 返回元素的逆序排名 ZREVRANK key member
返回成员在有序集合中的逆序排名,其中排名按照元素的分值从大到小计算。
排名以 0 开始。
4.8.8获取指定索引范围内的升序元素
ZRANGE key start stop [WITHSCORES]
返回有序集合在按照分值从小到大排列元素(升序排列) 的情况下,索引 start 至索引 stop 范围之内的所
有元素。
两个索引都可以是正数或者负数。当给定 WITHSCORES 选项时,命令会将元素和分值一并返回。
4.8.9 获取指定索引范围内的降序元素
ZREVRANGE key start stop [WITHSCORES]
返回有序集合在按照分值从大到小排列元素(降序排列) 的情况下,索引 start 至索引 stop 范围之内的所
有元素。
两个索引都可以是正数或者负数。当给定 WITHSCORES 选项时,命令会把元素和分值一并返回。
4.8.10 获取指定分值范围内的升序元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集合在按照分值升序排列元素的情况下,分值在 min 和 max 范围之内的所有元素。
给定 WITHSCORES 选项时,元素和分值会一并返回。给定 LIMIT 选项时,可以通过 offset 参数指定返
回的结果集要跳过多少个元素,而 count 参数则用于指定返回的元素数量。
4.8.11 获取指定分值范围内的降序元素
ZREVRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集合在按照分值降序排列元素的情况下,分值在 min 和 max 范围之内的所有元素。
给定 WITHSCORES 选项时,元素和分值会一并返回。给定 LIMIT 选项,可以通过 offset 参数指定返回
的结果集要跳过多少个元素,而 count 参数则用于指定返回的元素数量。
4.8.12 计算给定分值范围内的元素数量
ZCOUNT key min max
返回有序集合在升序排列元素的情况下,分值在 min 和 max 范围内的元素数量。
4.8.13 移除指定排名范围内的升序排列元素
ZREMRANGEBYRANK key start stop
移除有序集合中,元素按升序进行排列的情况下,指定排名范围内的所有元素。
4.8.14 移除指定分值范围内的升序排列元素
ZREMRANGEBYSCORE key min max
移除有序集合中,分值范围介于 min 和 max 之内的所有元素。
4.8.15 计算并集 ZUNIONSTORE destkey numkeys key [key ...]
4.8.16 计算交集 ZINTERSTORE destkey numkeys key [key ...]
5 HyperLogLog
使用常量空间估算大量元素的基数。
HyperLogLog 可以接受多个元素作为输入,并给出输入元素的基数估算值:
• 基数:集合中不同元素的数量。比如 {'apple', 'banana', 'cherry', 'banana', 'apple'} 的基数就是 3 。
• 估算值:算法给出的基数并不是精确的,可能会比实际稍微多一些或者稍微少一些,但会控制在合
理的范围之内。
HyperLogLog 的优点是,即使输入元素的数量或者体积非常非常大,计算基数所需的空间总是固定
的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基
数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以
HyperLogLog 不能像集合那样,返回输入的各个元素。
5.1将元素添加至 HyperLogLog
PFADD key element [element ...]
将任意数量的元素添加到指定的 HyperLogLog 里面。
这个命令可能会对 HyperLogLog 进行修改,以便反映新的基数估算值,如果 HyperLogLog 的基数估算
值在命令执行之后出现了变化, 那么命令返回 1 , 否则返回 0 。
命令的复杂度为 O(N) ,N 为被添加元素的数量。
5.2 返回给定 HyperLogLog 的基数估算值
PFCOUNT key [key ...]
当只给定一个 HyperLogLog 时,命令返回给定 HyperLogLog 的基数估算值。
当给定多个 HyperLogLog 时,命令会先对给定的 HyperLogLog 进行并集计算,得出一个合并后的
HyperLogLog ,然后返回这个合并 HyperLogLog 的基数估算值作为命令的结果(合并得出的
HyperLogLog 不会被储存,使用之后就会被删掉)。
当命令作用于单个 HyperLogLog 时, 复杂度为 O(1) , 并且具有非常低的平均常数时间。
当命令作用于多个 HyperLogLog 时, 复杂度为 O(N) ,并且常数时间也比处理单个 HyperLogLog 时要
大得多。
5.3 合并多个 HyperLogLog
PFMERGE destkey sourcekey [sourcekey ...]
将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有
给定 HyperLogLog 进行并集计算得出的。
命令的复杂度为 O(N) , 其中 N 为被合并的 HyperLogLog 数量, 不过这个命令的常数复杂度比较高。
二、数据库
redis是一个键值对数据库服务器,当我们调用命令时,创建一个键值对的时候,这个键值对会被放到redis的某个数据库里面。
1、查看键的类型
TYPE key
返回键储存的值的类型。复杂度为O(1)。
返回值 值的类型
none 键不存在
string 字符串或者HyperLogLog(HLL是二进制值)
hash 散列
list 列表
set 集合
zset 有序集合
2、删除键
DEL KEY[KEY ...]
删除给定的任意多个键,不存在的键会被忽略,命令返回成功删除的键数量。
3、检查键是否存在
EXIST key
检查给定的键是否存在于数据库,存在返回1,不存在返回0.
4、修改键的名字
RENAME key newkey 将键的名字从key改为newkey,如果newkey存在,那么覆盖,键key不存在,或者key和newkey同名时,返回错误。
RENAMENX key newkey 如果键newkey不存在,那么将键key改名为newkey;如果newkey已经村镇,那么不做动作。
5、sort命令
在redis里面,只有列表和有序集合是以有序的方式来存储值的:
列表按照值被推入的顺序来储存值
有序集合按照元素的分值来排序元素。
SORT key [BY pattern] [LIMIT offset count] [GET pattern[GET pattern ...]] [ASC|DESC] [ALPHA] [SORE sestination]
如果不指定顺序,默认按照升序排序。
ALPHA:可以让srot命令按照字典顺序排序,只对文字进行排序。
6、随机的获取某个键
RANDOMKEY
7、返回数据库中与给定模式相匹配的键
KEYS pattern
返回当前数据库中,所有匹配给定模式pattern的键
渐进地遍历整个数据库
因为KEYS命令会一次性地遍历整个数据库来获取所有与给定模式相匹配的键,所以随着数据库包含的键值对越来越多,这个命令的执行速度也会越来越慢,而对一个非常大的数据库执行keys命令,将导致服务器被阻塞一段时间。
为了解决这个问题,redis从2.8.0版本开始提供SCAN命令,这个命令可以以渐进的方式,分多次遍历整个数据库,并返回匹配给定模式的键。
keys和scan命令的对比

8、获取数据库大小
DBSIZE
9、清空当前数据库
FLUSHDB
10、切换数据库
redis服务器默认情况下会创建16个数据库,分别是0号数据库到15号数据库,客户端一般默认使用0号数据库,但用户可以通过调用 select num命令来切换到num号数据库。每个数据库都是独立的,一个数据库里面的键值对不会对另一个影响。
11、清空所有数据库
flushall
三、附加功能
1、键过期功能
让 Redis 在指定的时间自动删除特定的键。
1.1设置生存时间
EXPIRE key seconds 将键 key 的生存时间设置为指定的秒数。
PEXPIRE key milliseconds 将键 key 的生存时间设置为指定的毫秒数。
如果给定的键不存在,那么 EXPIRE 和 PEXPIRE 将返回 0 ,表示设置失败;如果命令返回 1 ,那么表
示设置成功。
当一个键被设置了生存时间之后,它的生存时间将会随着时间的流逝而减少:时间过去一毫秒,键的生
存时间就减少一毫秒;时间过去一秒钟,键的生存时间就减少一秒钟;以此类推。
当一个键的生存时间被减少至低于 0 时,Redis 就会自动将这个键删除掉。
1.2设置过期时间
EXPIREAT key timestamp 将键 key 的过期时间设置为指定的秒级 UNIX 时间戳。
PEXPIREAT key milliseconds-timestamp 将键 key 的过期时间设置为指定的毫秒级 UNIX 时间戳。
如果给定的键不存在,那么 EXPIREAT 和 PEXPIREAT 将返回 0 ,表示设置失败;如果命令返回 1 ,
那么表示设置成功。
对于被设置了过期时间的键来说,当键的过期时间小于当前时间的时候,Redis 就会自动地删除该键。
1.3返回键的剩余生存时间
在为一个键设置过期时间或者生存时间之后,用户可以使用 TTL 命令或者 PTTL 命令查看这个键的剩
余生存时间,以此来获知键还有多久才会被 Redis 删除:
TTL key 以秒为单位,返回键的剩余生存时间
PTTL key 以毫秒为单位,返回键的剩余生存时间
返回值 意义
-2 键不存在。
-1 键存在,但没有设置过期时间或者生存时间。
>= 0 键的剩余生存时间。
1.4 移除键的过期时间或生存时间
PERSIST key
移除为键 key 设置的过期时间或生存时间,使得它不会被 Redis 自动删除。
移除成功时命令返回 1 ;如果命令没有设置过期时间或生存时间,那么命令返回 0 。
2、发布与订阅:
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

2.1订阅频道
SUBSCRIBE channel [channel ...]
订阅给定的一个或多个频道。
2.2订阅模式
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个模式, pattern 参数可以包含 glob 风格的匹配符,比如:
• news::* 模式可以匹配 news::bussiness 、 news::it 、 news::sports::football 等频道;
• news::[ie]t 模式可以匹配 news::it 频道或者 news::et 频道;
• news::?t 模式可以匹配 news::it 、 news::et 、 news::at 等频道;
2.3退订频道和退订模式
UNSUBSCRIBE [channel [channel ...]] 退订指定的频道。如果执行时没有指定任何频道,那么退订已订阅的所有频道。
PUNSUBSCRIBE [pattern [pattern ...]] 退订指定的模式。如果执行时没有指定任何模式,那么退订已订阅的所有模式。
2.4查看被订阅的频道
PUBSUB CHANNELS [pattern] 列出目前至少有一个订阅者的频道。如果给定了可选的 pattern 参数,那么只列出与模式相匹配的频道。
2.5查看频道的订阅者数量
PUBSUB NUMSUB [channel-1 ... channel-N] 返回给定频道的订阅者数量。
2.6查看被订阅模式的数量
PUBSUB NUMPAT 返回服务器目前被订阅的模式数量。
3.流水线:
在一般情况下,用户每执行一个 Redis 命令,客户端和服务器都需要进行一次通信:客户端向服务器发送命令请求,而服务器则会将执行命令所得的命令回复返回给客户端。
在大多数情况下, 执行命令时的绝大部分时间都耗费在了发送命令和接收回复的过程上,因此减少客户端与服务器之间的通信次数,可以有效地提高程序的执行效率。
流水线可以将多条命令打包一起发送,并且在一次回复中接收所有被执行命令的结果,使用这个功能可以有效地提升程序在执行多条命令时的效率。
4.事务
Redis 的事务功能允许用户将多个命令包裹起来,然后一次性地、按顺序地执行被包裹的所有命令。
在事务执行的过程中,服务器不会中断事务而改去执行其他命令请求,只有在事务包裹的所有命令都被执行完毕之后,服务器才会去处理其他命令请求。
MULTI 开始一个新的事务。
MULTI
开始一个事务。
在这个命令执行之后,客户端发送的所有针对数据库或者数据库键的命令都不会被立即执行,而是被放
入到一个事务队列里面,并返回 QUEUED 表示命令已入队。
redis> MULTI # 开始一个事务
OK
redis> SET msg "hello world" # 将这个 SET 命令放入事务队列
QUEUED
redis> EXPIRE msg 10086 # 将这个 SET 命令放入事务队列
QUEUED
DISCARD 放弃事务。
取消事务,放弃执行事务队列中的所有命令。复杂度为 O(1)。
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXPIRE msg 10086
QUEUED
redis> DISCARD # 事务已被取消
OK
redis> SET msg "hello world"
OK
EXEC 执行事务中的所有命令。
按照命令被入队到事务队列中的顺序,执行事务队列中的所有命令。
命令的复杂度为队列中所有命令的复杂度之和。
命令的返回值是一个列表,列表里包含了事务队列中所有被执行命令的返回值。
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXPIRE msg 10086
QUEUED
redis> EXEC
1) OK # SET 命令的返回值
2) (integer) 1 # EXPIRE 命令的返回值
WATCH 命令
为了消除 ZDECRBY 实现中的竞争条件, 我们需要用到 Redis 提供的 WATCH 命令, 这个命令需要在
开始一个事务之前执行, 它接受任意多个键作为参数, 并对输入的键进行监视:
WATCH key [key ...]
如果被监视的键在事务提交之前(也即是 EXEC 命令执行之前), 已经被其他客户端抢先修改了, 那么
服务器将拒绝执行客户端提交的事务, 并返回 nil 作为事务的回复:
5、脚本
Redis 脚本使用 Lua 解释器来执行脚本。执行脚本的常用命令为  EVAL
通过调用redis.call()函数或者redis.pcall()函数。redis.call()如果脚本出错会返回出错的名字,而redis.pcall()函数如果出错,则会返回错误信息。
热河Lua脚本,只要被EVAL命令执行过一次,就会被储存到服务器的脚本缓存里面,用户只要通过EVALSHA命令,指定被缓存脚本的SHA1值,就可以在不发送脚本的情况下,再次执行脚本。
EVAL script numkeys key [ key ...] arg [ arg ...] 执行脚本
Evalsha 命令根据给定的 sha1 校验码,执行缓存在服务器中的脚本。
SCRIPT Exists 命令:表示脚本是否已经被加入到脚本缓存里面,是的话返回1,不是的话返回0;
SCRIPT LOAD script:将脚本储存到脚本缓存里面,等待将来的EVALSHA使用。
SCRIPT FLUSH:清楚脚本缓存存储的所有脚本;
SCRIPT KILL:杀死运行超时的脚本。如果脚本已经执行过写入操作,那么还需要使用SHUTDOWN NOSAVE命令来强制服务器不保存数据,以免错误的数据被保存到数据库里面。

未完待续

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值