Task02:数据库的基本使用(Redis)

1. 安装及启动

详见Task01:熟悉新闻推荐系统的基本流程

2. 简介及特点

详见第5章_数据库相关(二)

3. 数据库的基本操作

3.1 切换数据库

redis.conf配置中默认16个库,下标从0~15。进入客服端默认选中第0个库,可以通过select命令进行切换,index表示库的小标。

SELECT index

演示如下:默认是在下标为0的库,现在切换到1库,库的编号在命令行中有提示

127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> 

3.2 查看key的数量

127.0.0.1:6379> DBSIZE

实例如下:

127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> dbsize
(integer) 0
127.0.0.1:6379[1]> select 2
OK
127.0.0.1:6379[2]> dbsize
(integer) 0

3.3 清空当前库

删除当前选择的数据库中的所有数据,这个命令永远不会出现失败。

127.0.0.1:6379> FLUSHDB

3.4 清空所有库

删除所有数据库里面的数据,注意是所有数据库,这个命令永远不会出现失败。

127.0.0.1:6379> FLUSHALL

4. key的基本操作

4.1 查找指定key是否存在

KEYS pattern

该指令查找数据库所有符合pattern的key,其中pattern可以为?、* 、[abc…]、[a-d]等方式。其中?代表一个任意一个字符,*代表任意0个或多个字符,[abc…]代表只能是[]中的值,[a-d]代表a到d范围内总的值。

示例如下:

127.0.0.1:6379> keys *
1) "name"
2) "type"
127.0.0.1:6379> keys n*?
1) "name"
127.0.0.1:6379> keys [a-z][nam][nam]e
1) "name"
127.0.0.1:6379> 

除去*代表任意0个或多个字符,其他模式只能代表一个字符

4.2 查询指定key的数量

EXISTS key or [key]

该指令为了查找一个或多个key,返回存在key值的数量。

127.0.0.1:6379> keys *
1) "name"
2) "type"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists name type
(integer) 2
127.0.0.1:6379> 

4.3 设置指定key的过期时间

EXPIRE key seconds

expire 设置 key 的过期时间,时间过期后,key 会被自动删除,设置成功返回1,key不存在返回0。

 TTL key

ttl 命令以秒为单位返回key的剩余过期时间,如果key不存在返回 -2 key 存在但没有关联超时时间则返回 -1 。

127.0.0.1:6379> expire name 60
(integer) 1
127.0.0.1:6379> ttl name
(integer) 58
127.0.0.1:6379> ttl tape
(integer) -2
127.0.0.1:6379> ttl type
(integer) -1
127.0.0.1:6379> ttl name
(integer) 35
127.0.0.1:6379> ttl name
(integer) -2

4.4 查看指定key的数据类型

TYPE key

type命令以字符串的形式返回存储在 key 中的值的类型,可返回的类型有:string, list, set, zset,hashstream,如果key值不存在返回none

127.0.0.1:6378> set key1 "value"
OK
127.0.0.1:6378> lpush key2 "value"
(integer) 1
127.0.0.1:6378> SADD key3 "value"
(integer) 1
127.0.0.1:6378> type key1
string
127.0.0.1:6378> type key2
list
127.0.0.1:6378> type key3
set
127.0.0.1:6378> type key
none

4.5 删除指定的key

DEL key or [key]

del命令删除指定的key,不存在的key忽略,返回0,如果key存在,返回删除的key的个数。

127.0.0.1:6378> del key
(integer) 0
127.0.0.1:6378> del key1 key2
(integer) 2

5. 字符串的基本操作

​ 字符串是Redis中最常见的数据类型,它能够存储任何形式的字符串,其中包括二进制格式,JSON格式,序列化格式等数据。而string相关的命令则是用于管理redis字符串值

5.1 set

set命令将key是定为指定的字符串,如果key存在,则会覆盖原来的值。

SET key value [EX seconds] [PX milliseconds] [NX|XX]

其中set可以为设定的值设置过期时间,EX表示秒数,PX表示毫秒。参数NX表示只有键key不存在的时候才会设置key的值,XX表示只有键key存在的时候才会设置key的值。

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name 'Mickey'
OK
127.0.0.1:6379> set type 'mouse'
OK
127.0.0.1:6379> set gender 'male'
OK
127.0.0.1:6379> set pet 'Pluto'
OK
127.0.0.1:6379> keys *
1) "pet"
2) "gender"
3) "name"
4) "type"
127.0.0.1:6379> 

5.2 get

get命令返回与键 key 相关联的字符串值。

GET key

如果key不存在,返回nil,如果key的值是非字符串类型,那么返回一个错误。

127.0.0.1:6379> keys *
1) "pet"
2) "gender"
3) "name"
4) "type"
127.0.0.1:6379> get name
"Mickey"
127.0.0.1:6379> get gender
"male"
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379> 

5.3 append

append命令将指定的key追加值。如果key存在,并且是字符串,则会将value追加到key原值的末尾,如果key值是非字符串则会报错,当key不存在时候,改命令类似于set,简单将key设定为value。

APPEND KEY_NAME NEW_VALUE
127.0.0.1:6379> keys *
1) "name"
2) "pet"
3) "type"
127.0.0.1:6379> get name
"Mickey"
127.0.0.1:6379> append name ' Minnie'
(integer) 13
127.0.0.1:6379> get name
"Mickey Minnie"
127.0.0.1:6379> 

5.4 incr

incr 命令将 key 中储存的数字值增一。如果key不存在,key值会被初始化为0,在进行incr操作。如果字符串类型的值不能表示为数字,则会报错。

INCR KEY_NAME 
127.0.0.1:6379> keys *
1) "age"
2) "name"
3) "pet"
4) "type"
127.0.0.1:6379> get age
"24"
127.0.0.1:6379> incr age
(integer) 25
127.0.0.1:6379> get age
"25"
127.0.0.1:6379> 

5.5 decr

decr命令将 key 中储存的数字值减一,和incr命令相似。

DECR KEY_NAME
127.0.0.1:6379> get age
"25"
127.0.0.1:6379> DECR age
(integer) 24
127.0.0.1:6379> GET age
"24"
127.0.0.1:6379> 

5.6 strlen

Strlen 命令将获取指定 key 所储存的字符串值的长度,如果key存储的不是字符串类型或不存在时,返回错误。

STRLEN KEY_NAME
127.0.0.1:6379> keys *
1) "pet"
2) "name"
3) "age"
4) "type"
127.0.0.1:6379> strlen name
(integer) 13
127.0.0.1:6379> strlen age
(integer) 2
127.0.0.1:6379> 

5.7 setrange

SetRange命令是将从偏移量 offset 开始, 用 value 参数覆盖键 key 储存的字符串值。

SETRANGE key offset value

不存在的键 key 当作空白字符串处理,如果键 key 原来储存的字符串长度比偏移量小,那么原字符和偏移量之间的空白将用零字节("\x00" )进行填充。

127.0.0.1:6379> set name 'Mickey'
OK
127.0.0.1:6379> strlen name
(integer) 6
127.0.0.1:6379> setrange name 7 'Minnie'
(integer) 13
127.0.0.1:6379> get name
"Mickey\x00Minnie"
127.0.0.1:6379> 

我们发现name的长度为6,如果offset6,那就是在第6个字符的后面,紧接着单词Mickey插入单词Minnie

也就是从0开始编号的6位置开始插入新的字符,如果设置offset7,那就是中间间隔的有一个空格

5.8 getrange

GetRange命令返回存储在 key 中的字符串的子串,由 start 和 end 偏移决定(都包括在内)。负数偏移提供相对字符串结尾的偏移。并且该命令会通过将结果范围限制为字符串的实际长度来处理超出范围的请求。

GETRANGE key start end

当key不存在返回空字符串。

127.0.0.1:6379> get name
"Mickey\x00Minnie"
127.0.0.1:6379> strlen name
(integer) 13
127.0.0.1:6379> getrange name 0 6
"Mickey\x00"
127.0.0.1:6379> getrange name 7 13
"Minnie"
127.0.0.1:6379> getrange name 7 15
"Minnie"
127.0.0.1:6379> getrange name 16 15
""
127.0.0.1:6379> 

不存在的地方都默认为空字符

5.9 mset

命令设置多个 key 的值为各自对应的 value。如果key存在,则会用新值替换旧值,如果key不存在,会重新创建,该命令总是返回“OK”,因为 MSET不会失败。

MSET key value [key value ...]
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> mset name 'Mickey' type 'mouse'
OK
127.0.0.1:6379> keys *
1) "name"
2) "type"
127.0.0.1:6379> 

这个感觉像是,many set

5.10 mget

命令返回所有(一个或多个)给定 key 的值,值的类型是字符串。 如果给定的 key 里面有某个 key 不存在或者值不是字符串,那么这个 key 返回特殊值 nil 。

MGET key [key ...]
127.0.0.1:6379> keys *
1) "name"
2) "type"
127.0.0.1:6379> mget name type
1) "Mickey"
2) "mouse"
127.0.0.1:6379> 

同上,这个感觉像是,many get

6. 列表的基本操作

6.1 lpush

Lpush 将一个或多个值插入到列表key 的头部。如果 key 不存在,那么在进行 push 操作前会创建一个空列表。如果 key 对应的值不是 list 类型,那么会返回一个错误。可以使用一个命令把多个元素 push 进入列表。

LPUSH key value [value ...]
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush name 'Mickey' 'Minnie' 'Goofy'
(integer) 3
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> llen name
(integer) 3
127.0.0.1:6379> lrange name 0 3
1) "Goofy"
2) "Minnie"
3) "Mickey"
127.0.0.1:6379> lrange name 1 3
1) "Minnie"
2) "Mickey"
127.0.0.1:6379> lrange name 1 2
1) "Minnie"
2) "Mickey"
127.0.0.1:6379> 

感觉像是,left push,在列表头部

然后是依次插入头部,所以说最后一个在最头部

6.2 rpush

Rpush 将向存储在 key 中的列表的尾部插入所有指定的值。如果 key 不存在,那么会创建一个空的列表然后再进行 push 操作。 当 key 保存的不是列表,那么会返回一个错误。

RPUSH key value [value ...]
127.0.0.1:6379> llen name
(integer) 3
127.0.0.1:6379> lrange name 0 2
1) "Goofy"
2) "Minnie"
3) "Mickey"
127.0.0.1:6379> rpush name 'Donald'
(integer) 4
127.0.0.1:6379> lrange name 0 3
1) "Goofy"
2) "Minnie"
3) "Mickey"
4) "Donald"
127.0.0.1:6379> 

应该是right push,因为是在列表尾部

6.3 lrange

Lrange将返回列表中指定区间内的元素(闭区间),区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。如果start大于最大小标,那么叫返回空列表。

LRANGE key start end
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
list
127.0.0.1:6379> llen name
(integer) 4
127.0.0.1:6379> lrange name 0 3
1) "Goofy"
2) "Minnie"
3) "Mickey"
4) "Donald"
127.0.0.1:6379> 

应该是,list range

6.4 lindex

Lindex 将返回列表 key 里索引 index 位置存储的元素。 index 下标是从 0 开始索引的,所以 0 是表示第一个元素, 1 表示第二个元素,并以此类推。 负数索引用于指定从列表尾部开始索引的元素,在这种方法下,-1 表示最后一个元素,-2 表示倒数第二个元素,并以此往前推。当 key 值不是列表的时候,会返回错误。

LINDEX key index
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
list
127.0.0.1:6379> llen name
(integer) 4
127.0.0.1:6379> lindex name 0
"Goofy"
127.0.0.1:6379> lindex name 1
"Minnie"
127.0.0.1:6379> 

那就是,list index

6.5 llen

Llen 将用于返回存储在 key 中的列表长度。 如果 key 不存在,则 key 被解释为一个空列表,返回 0 。 如果 key 不是列表类型,返回一个错误。

LLEN key
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
list
127.0.0.1:6379> llen name
(integer) 4
127.0.0.1:6379> 

那就是,list len,之前的是,str len

6.6 lrem

Lrem将用于从列表 key 中删除前 count 个值等于 element 的元素。 这个 count 参数通过下面几种方式影响这个操作,如果count > 0, 从头到尾删除值为 value 的元素;如果count < 0,将从尾到头删除值为 value 的元素;如果 count = 0 将移除所有值为 value 的元素

LREM key count value
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
list
127.0.0.1:6379> llen name
(integer) 4
127.0.0.1:6379> lrange name 0 3
1) "Goofy"
2) "Minnie"
3) "Mickey"
4) "Donald"
127.0.0.1:6379> rpush name 'Goofy' 'Goofy'
(integer) 6
127.0.0.1:6379> lpush name 'Mickey' 'Mickey'
(integer) 8
127.0.0.1:6379> lrange name 0 7
1) "Mickey"
2) "Mickey"
3) "Goofy"
4) "Minnie"
5) "Mickey"
6) "Donald"
7) "Goofy"
8) "Goofy"
127.0.0.1:6379> lrem name 1 Mickey
(integer) 1
127.0.0.1:6379> lrange name 0 7
1) "Mickey"
2) "Goofy"
3) "Minnie"
4) "Mickey"
5) "Donald"
6) "Goofy"
7) "Goofy"
127.0.0.1:6379> lrem name -2 'Goofy'
(integer) 2
127.0.0.1:6379> lrange name 0 7
1) "Mickey"
2) "Goofy"
3) "Minnie"
4) "Mickey"
5) "Donald"
127.0.0.1:6379> 

应该是,list remove,然后count去决定方向

6.7 lset

Lset 将用于设置列表 key 中 index 位置的元素值为 element。

LSET key index value
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
list
127.0.0.1:6379> llen name
(integer) 5
127.0.0.1:6379> lrange name 0 4
1) "Mickey"
2) "Goofy"
3) "Minnie"
4) "Mickey"
5) "Donald"
127.0.0.1:6379> lset name 0 Goofy
OK
127.0.0.1:6379> lrange name 0 4
1) "Goofy"
2) "Goofy"
3) "Minnie"
4) "Mickey"
5) "Donald"
127.0.0.1:6379> 

应该是,list set

6.8 linsert

Linsert 将用于把 value插入到列表 的第一个 pivot 的前面或后面。当 key 不存在时,这个list会被看作是空list,什么都不执行;当 key 存在,值不是列表类型时,返回错误。

LINSERT key BEFORE|AFTER pivot value
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
list
127.0.0.1:6379> llen name
(integer) 5
127.0.0.1:6379> lrange name 0 -1
1) "Goofy"
2) "Goofy"
3) "Minnie"
4) "Mickey"
5) "Donald"
127.0.0.1:6379> linsert name before Goofy Mickey
(integer) 6
127.0.0.1:6379> lrange name 0 -1
1) "Mickey"
2) "Goofy"
3) "Goofy"
4) "Minnie"
5) "Mickey"
6) "Donald"
127.0.0.1:6379> linsert name after Goofy Mickey
(integer) 7
127.0.0.1:6379> lrange name 0 -1
1) "Mickey"
2) "Goofy"
3) "Mickey"
4) "Goofy"
5) "Minnie"
6) "Mickey"
7) "Donald"
127.0.0.1:6379> 

应该是,list insert

7. 哈希表的基本操作

hash类似于java中的HashMap,在Reids中做了更多的优化。此外hash是一个string类型的field和value的映射表,特别适合用于存储对象。例如我们可以借用hash数据结构来存储用户信息,商品信息等。

7.1 hset

Hset 命令用于为存储在 key 中的哈希表的 field 字段赋值 value 。如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。如果字段(field)已经存在于哈希表中,旧值将被覆盖。

HSET key field value
127.0.0.1:6379> lrange name 0 -1
1) "Goofy"
2) "Minnie"
3) "Mickey"
4) "Donald"
127.0.0.1:6379> hset type Goofy dog
(integer) 1
127.0.0.1:6379> hget type Goofy
"dog"
127.0.0.1:6379> 

应该是,hash set

7.2 hget

Hget 命令用于返回哈希表中指定字段 field 的值。如果给定的字段或 key 不存在时,返回 nil 。

HGET key field
127.0.0.1:6379> lrange name 0 -1
1) "Goofy"
2) "Minnie"
3) "Mickey"
4) "Donald"
127.0.0.1:6379> hset type Goofy dog
(integer) 1
127.0.0.1:6379> hget type Goofy
"dog"
127.0.0.1:6379> 

应该是,hash get

7.3 hmset

Hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。此命令会覆盖哈希表中已存在的字段,如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。

HMSET key field value [field value ...]
127.0.0.1:6379> hmset type Minnie mouse Mickey mouse Donald duck
OK

属于是,hash many set

7.4 hgetall

Hgetall 命令用于返回存储在 key 中的哈希表中所有的域和值。返回值以列表形式返回哈希表的字段及字段值,若 key 不存在,返回空列表。

HGETALL key
127.0.0.1:6379> hgetall type
1) "Goofy"
2) "dog"
3) "Minnie"
4) "mouse"
5) "Mickey"
6) "mouse"
7) "Donald"
8) "duck"

属于是,hash get all

7.5 hdel

Hdel 命令用于删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。 如果 key 不存在,会被当作空哈希表处理并返回 0 。

HDEL key field [field ...]
127.0.0.1:6379> hgetall type
1) "Goofy"
2) "dog"
3) "Minnie"
4) "mouse"
5) "Mickey"
6) "mouse"
7) "Donald"
8) "duck"
127.0.0.1:6379> hdel type Goofy
(integer) 1
127.0.0.1:6379> hgetall type
1) "Minnie"
2) "mouse"
3) "Mickey"
4) "mouse"
5) "Donald"
6) "duck"
127.0.0.1:6379> 

应该是,hash del

7.6 hexists

Hexists 命令用于查看哈希表的指定字段field 是否存在。如果表含有给定字段field会返回1,否则返回0。

HEXISTS key field
127.0.0.1:6379> hgetall type
1) "Minnie"
2) "mouse"
3) "Mickey"
4) "mouse"
5) "Donald"
6) "duck"
127.0.0.1:6379> HEXISTS type Donald
(integer) 1
127.0.0.1:6379> HEXISTS type Goofy
(integer) 0
127.0.0.1:6379> 

应该是,hash exists

7.7 hkeys

Hkeys返回存储在 key 中哈希表的所有域。当 key 不存在时,返回空表。

HKEYS key
127.0.0.1:6379> hgetall type
1) "Minnie"
2) "mouse"
3) "Mickey"
4) "mouse"
5) "Donald"
6) "duck"
127.0.0.1:6379> hkeys type
1) "Minnie"
2) "Mickey"
3) "Donald"
127.0.0.1:6379> 

应该是,hash keys,也就是,hash fields

7.8 hvals

Hvals 命令返回哈希表所有域(field)的值。当 key 不存在时,返回空表。

HVALS key
127.0.0.1:6379> hgetall type
1) "Minnie"
2) "mouse"
3) "Mickey"
4) "mouse"
5) "Donald"
6) "duck"
127.0.0.1:6379> hvals type
1) "mouse"
2) "mouse"
3) "duck"
127.0.0.1:6379> 

应该是,hash values

8. 集合的基本操作

8.1 sadd

Sadd 将命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。假如集合 key 不存在,则创建一个只包含被添加的元素作为成员的集合。当集合 key 不是集合类型时,返回一个错误。

SADD key member [member ...]
127.0.0.1:6379> sadd name Mickey Minnie Goofy 
(integer) 3

这里是,set add,应该是合并了set many add,之前都是分开的

8.2 smembers

Smembers 将返回存储在 key 中的集合的所有的成员。 不存在的集合被视为空集合。

SMEMBERS key  
127.0.0.1:6379> sadd name Mickey Minnie Goofy 
(integer) 3
127.0.0.1:6379> smembers name
1) "Mickey"
2) "Goofy"
3) "Minnie"

应该是,set members

8.3 sismember

sIsMember 将用于判断元素 member 是否集合 key 的成员。如果成员元素是集合的成员,返回 1 ;如果成员元素不是集合的成员,或 key 不存在,返回0。

SISMEMBER key member
127.0.0.1:6379> smembers name
1) "Mickey"
2) "Goofy"
3) "Minnie"
127.0.0.1:6379> SISMEMBER name Goofy
(integer) 1
127.0.0.1:6379> SISMEMBER name Donald
(integer) 0
127.0.0.1:6379> 

比较神奇,set is member,直译不通,意译还行

8.4 scard

Scard 将返回集合中元素的数量。

SCARD key 
127.0.0.1:6379> smembers name
1) "Mickey"
2) "Goofy"
3) "Minnie"
127.0.0.1:6379> scard name
(integer) 3
127.0.0.1:6379> 

更加神奇,挺别扭的,应该是set card

因为在高数中,card,指的是集合当中元素的数量

8.5 srem

Srem将在集合中删除指定的元素。如果指定的元素不是集合成员则被忽略。如果集合 key 不存在则被视为一个空的集合,该命令返回0。如果key的类型不是一个集合,则返回错误。

srem key member [member ...]
127.0.0.1:6379> smembers name
1) "Pluto"
2) "Mickey"
3) "Goofy"
4) "Minnie"
127.0.0.1:6379> srem name Pluto
(integer) 1
127.0.0.1:6379> smembers name
1) "Mickey"
2) "Goofy"
3) "Minnie"
127.0.0.1:6379> 

就是,set remove

8.6 srandmember

如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

SRANDMEMBER key [count]
127.0.0.1:6379> smembers name
1) "Mickey"
2) "Goofy"
3) "Minnie"
127.0.0.1:6379> SRANDMEMBER name 1
1) "Goofy"
127.0.0.1:6379> SRANDMEMBER name 2
1) "Minnie"
2) "Goofy"
127.0.0.1:6379> SRANDMEMBER name 3
1) "Mickey"
2) "Minnie"
3) "Goofy"
127.0.0.1:6379> SRANDMEMBER name 4
1) "Mickey"
2) "Minnie"
3) "Goofy"
127.0.0.1:6379> SRANDMEMBER name 3
1) "Mickey"
2) "Minnie"
3) "Goofy"
127.0.0.1:6379> SRANDMEMBER name 0
(empty list or set)
127.0.0.1:6379> SRANDMEMBER name -1
1) "Mickey"
127.0.0.1:6379> SRANDMEMBER name -2
1) "Mickey"
2) "Mickey"
127.0.0.1:6379> SRANDMEMBER name -3
1) "Mickey"
2) "Mickey"
3) "Mickey"
127.0.0.1:6379> 

是,set rand member

8.7 spop

Spop 将从集合 key中删除并返回一个或多个随机元素。这个命令和 SRANDMEMBER相似, SRANDMEMBER 只返回随机成员但是不删除这些返回的成员。

SPOP key [count]
127.0.0.1:6379> smembers name
1) "Mickey"
2) "Goofy"
3) "Minnie"
127.0.0.1:6379> spop name 1
1) "Mickey"
127.0.0.1:6379> smembers name
1) "Goofy"
2) "Minnie"
127.0.0.1:6379> 

是,set pop

9. 有序集合的操作

Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
 
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
 
有序集合的成员是唯一的,但分数(score)却可以重复。
 
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

相当于说在集合的基础上又增加了一个权重,有字典那味儿了,键不能重复,但是值可以重复

9.1 zadd

Zadd 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。如果有序集合 key 不存在,则创建一个空的有序集并执行 ZADD操作。当 key 存在但不是有序集类型时,返回一个错误。score 值可以是整数值或双精度浮点数,score 可为正也可以为负。

ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
  • XX: 仅更新存在的成员,不添加新成员。
  • NX: 不更新存在的成员。只添加新成员。
  • LT: 更新新的分值比当前分值小的成员,不存在则新增。
  • GT: 更新新的分值比当前分值大的成员,不存在则新增。
  • CH: 返回变更成员的数量。变更的成员是指 新增成员 和 score值更新的成员,命令指明的和之前score值相同的成员不计在内。 注意: 在通常情况下,ZADD返回值只计算新添加成员的数量。
  • INCR: ZADD 使用该参数与 ZINCRBY 功能一样。一次只能操作一个score-element对。
     
  • >= 2.4: 支持一次增加或更新多个成员。
  • >= 3.0.2: 增加 XX, NX, CH 和 INCR 选项。
  • >=6.2: 增加 GT 和 LT 选项。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd name 1 Mickey 1 Minnie 2 Pluto
(integer) 3
127.0.0.1:6379> 

9.2 zrange

Zrange将返回有序集中,指定区间内(闭区间)的成员,其中成员的按分数值递增(从小到大)来排序,具有相同分数值的成员按字典序(lexicographical order )来排列。如果你需要成员按值递减(从大到小)来排列,可以使用 ZREVRANGE命令。下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。其中 start和stop参数的细节同lrange命令。

ZRANGE key start stop [WITHSCORES]
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
zset
127.0.0.1:6379> zcard name
(integer) 3
127.0.0.1:6379> zrange name 0 2
1) "Mickey"
2) "Minnie"
3) "Pluto"
127.0.0.1:6379> 

9.3 zrevrange

zRevRange 将返回有序集key中,指定区间内的成员。其中成员的位置按score值递减(从高到低)来排列。具有相同score值的成员按字典序的反序排列。 除了成员排序相反外,ZREVRANGE命令的其他方面和ZRANGE命令一样。

ZREVRANGE key start stop [WITHSCORES]
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> type name
zset
127.0.0.1:6379> zcard name
(integer) 3
127.0.0.1:6379> zrange name 0 2
1) "Mickey"
2) "Minnie"
3) "Pluto"
127.0.0.1:6379> zrevrange name 0 2 withscores
1) "Pluto"
2) "2"
3) "Minnie"
4) "1"
5) "Mickey"
6) "1"
127.0.0.1:6379> 

9.3 zrem

Zrem 将从有序集合key中删除指定的成员member。如果member不存在则被忽略。当key存在,但是不是有序集合类型时,返回类型错误。返回的是从有序集合中删除的成员个数,不包括不存在的成员。

ZREM key member [member ...]
127.0.0.1:6379> zrange name 0 2
1) "Mickey"
2) "Minnie"
3) "Pluto"
127.0.0.1:6379> zrem name Pluto
(integer) 1
127.0.0.1:6379> zrange name 0 2
1) "Mickey"
2) "Minnie"
127.0.0.1:6379> 

9.4 zcard

Zcard 将返回有序集的成员个数。 当 key 不存在时,返回 0 。

ZCARD key
127.0.0.1:6379> zrange name 0 2
1) "Mickey"
2) "Minnie"
127.0.0.1:6379> zcard name
(integer) 2
127.0.0.1:6379> 

9.5 zrangebyscore

该指令将返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。具有相同 score 值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset count ),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score 值一起返回。

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
127.0.0.1:6379> zcard name
(integer) 5
127.0.0.1:6379> zrange name 0 4 withscores
 1) "Mickey"
 2) "1"
 3) "Minnie"
 4) "1"
 5) "Pluto"
 6) "2"
 7) "Goofy"
 8) "3"
 9) "Donald"
10) "4"
127.0.0.1:6379> zrangebyscore name 2 3 withscores
1) "Pluto"
2) "2"
3) "Goofy"
4) "3"

9.6 zrevrangebyscore

Redis Zrevrangebyscore 返回有序集中指定分数区间内的所有的成员。有序集成员按分数值递减(从大到小)的次序排列。具有相同分数值的成员按字典序的逆序(reverse lexicographical order )排列。除了成员按分数值递减的次序排列这一点外, ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE 命令一样。

ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
127.0.0.1:6379> zcard name
(integer) 5
127.0.0.1:6379> zrange name 0 4 withscores
 1) "Mickey"
 2) "1"
 3) "Minnie"
 4) "1"
 5) "Pluto"
 6) "2"
 7) "Goofy"
 8) "3"
 9) "Donald"
10) "4"
127.0.0.1:6379> zrangebyscore name 2 3 withscores
1) "Pluto"
2) "2"
3) "Goofy"
4) "3"
127.0.0.1:6379> zrevrangebyscore name 2 3 withscores
(empty list or set)
127.0.0.1:6379> zrevrangebyscore name 3 2 withscores
1) "Goofy"
2) "3"
3) "Pluto"
4) "2"
127.0.0.1:6379> 

9.7 zcount

Zcount 将返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。

ZCOUNT key min max
127.0.0.1:6379> zrangebyscore name 2 3 withscores
1) "Pluto"
2) "2"
3) "Goofy"
4) "3"
127.0.0.1:6379> zcount name 2 3
(integer) 2
127.0.0.1:6379> 

10. Python调用Redis

10.1 连接

10.1.1 直连模式

直连模式的方式简单方便,适合少量长期连接的场景。其中host参数是ip地址,如果Redis服务存在于本地,可以使用127.0.0.1,或者换成Redis服务所在的ip地址。db表示当前选择的库,其参数值可以是 0-15;如果设置连接数据库的密码,那么就需要使用password进行验证。

>>> import redis
>>> r = redis.Redis(host='127.0.0.1',port=6379,db=0,password='')
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
10.1.2 连接池模式

连接池模式是使用 connection pool(连接池)来管理 redis server 的所有连接,每个Redis实例会维护自己的连接池来管理管理对一个 redis server 所有的连接,避免每次建立,释放连接的开销。

>>> import redis
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True, max_connections=10)
>>>> pool
ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>
>>> r1 = redis.Redis(connection_pool=pool)   #  第一个客户端访问
>>>> r1
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> r2 = redis.Redis(connection_pool=pool)   #  第二个客户端访问
>>> r2
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 

10.2 基本操作

10.2.1 String类型
>>> import redis
>>> 
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
>>> r = redis.StrictRedis(connection_pool=pool)
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> r.set('name','jiang')
True
>>> r.append("name","you") # 在redis name对应的值后面追加内容
8
>>> r.getrange('name',0,-1)
'jiangyou'
>>> 
>>> r.mset({'age':'26','home':'liaoning'})
True
>>> r.mget('name','age','home')
['jiangyou', '26', 'liaoning']
>>> r.strlen('name')
8
>>> 
>>> r.incrby('age',5) 
31
>>> r.get('age')
'31'
>>> r.decrby('age',5)
26
>>> r.get('age')
'26'
>>> r.incrbyfloat('age',5.2)
31.2
>>> r.incrbyfloat('age',-10.5)
20.7
>>> 
>>> r.getrange('name',0,-1)
'jiangyou'
>>> r.setrange('name',5,'hahaha')  # 修改字符串内容,从指定字符串索引开始向后替换。
11
>>> r.getrange('name',0,-1)
'jianghahaha'
>>> r.delete('name')
1
>>> 

10.2.2 Hash类型
>>> import redis
>>> 
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
>>> r = redis.StrictRedis(connection_pool=pool)
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> r.hset('user1','name','zhangsan')   # user1对应的hash中设置一个键值对(不存在,则创建;否则,修改)
1
>>> r.hset('user1','age','22')          # user1对应的hash中设置一个键值对(不存在,则创建;否则,修改)
1
>>> r.hincrbyfloat('user1','age',0.5)   # 自增user1对应的hash中的指定key的值,不存在则创建key=amount
22.5
>>> r.hmget('user1','name','age')
['zhangsan', '22.5']
>>> 
>>> # 一次性设置多个field和value
>>> user_dict = {
...   'password':'123',
...   'gender':'M',
...   'home':'辽宁'
... }
>>> r.hmset('user1',user_dict)        #  在user1对应的hash中批量设置键值对 
<stdin>:1: DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead.
True
>>> 
>>> r.hlen('user1')
5
>>> r.hgetall('user1')
{'name': 'zhangsan', 'age': '22.5', 'password': '123', 'gender': 'M', 'home': '辽宁'}
>>> r.hkeys("user1")
['name', 'age', 'password', 'gender', 'home']
>>> r.hvals("user1")
['zhangsan', '22.5', '123', 'M', '辽宁']
>>> r.hexists("user1","home") #  检查user1对应的hash是否存在当前传入的home
True
>>> r.hdel("user1",'home')               #  将user1对应的hash中指定key的键值对删除
1
>>> 
10.2.3 List类型
>>> import redis
>>> 
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
>>> pool
ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>
>>> r = redis.StrictRedis(connection_pool=pool)
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> r.lpush('database','sql','mysql','redis')     #   在database对应的list中添加元素,每个新的元素都添加到列表的最左边
3
>>> r.lrange('database',0,-1)
['redis', 'mysql', 'sql']
>>> 
>>> r.linsert('database','before','mysql','mongodb')
4
>>> #   在database对应的列表的某一个值前或后插入一个新值,其含义为在第三个参数的前(before)或后(after) 插入参数四
>>> 
>>> r.lrange('database',0,-1) #  在database对应的列表分片获取数据
['redis', 'mongodb', 'mysql', 'sql']
>>> 
>>> r.llen('database') #  database对应的list元素的个数
4
>>> 
>>> r.lindex('database',2) #在database对应的列表中根据索引获取列表元素
'mysql'
>>> 
>>> r.lset('database', 0, 'redisdb')   #  对database对应的list中的某一个索引位置重新赋值     
True
>>> r.lrange('database',0,-1)
['redisdb', 'mongodb', 'mysql', 'sql']
>>> 
>>> r.rpop('database') #  在database对应的列表的右侧获取第一个元素并在列表中移除,返回值则是第一个元素
'sql'
>>> 
>>> r.ltrim('database',0,1) # 在database对应的列表中移除没有在start-end索引之间的值
True
>>> 
>>> r.brpop('database',1)     # 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧  [如果列表中为空时,则返回None]
('database', 'mongodb')
>>> 
>>> r.delete('database')
1
>>> 

10.2.4 set类型
>>> import redis
>>> 
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,password="",decode_responses=True,max_connections=10)
>>> pool
ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>
>>> r = redis.StrictRedis(connection_pool=pool)
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> r.sadd("name","zhangsan")        #  给name对应的集合中添加元素
1
>>> r.sadd("name","zhangsan","lisi","wangwu")
2
>>> 
>>> r.smembers('name') #  获取name对应的集合的所有成员
{'zhangsan', 'wangwu', 'lisi'}
>>> 
>>> r.scard("name") #  获取name对应的集合中的元素个数
3
>>> 
>>> r.sismember('name','zhangsan') #  检查value是否是name对应的集合内的元素,返回值为True或False
True
>>> 
>>> r.smembers('name')
{'zhangsan', 'wangwu', 'lisi'}
>>> r.spop('name') #  随机删除并返回指定集合的一个元素
'zhangsan'
>>> r.smembers('name')
{'wangwu', 'lisi'}
>>> 
>>> r.smembers('name')
{'wangwu', 'lisi'}
>>> r.srem("name", "lisi")
1
>>> r.smembers('name')
{'wangwu'}
>>> 
>>> r.sadd("name","a","b")
2
>>> r.sadd("name1","b","c")
2
>>> r.sadd("name2","b","c","d")
3
>>> 
>>> r.sinter("name","name1","name2") #  获取多个name对应集合的交集
{'b'}
>>> r.sunion("name","name1","name2") #  获取多个name对应的集合的并集
{'b', 'c', 'a', 'd', 'wangwu'}
>>> r.sdiff("name","name1","name2") #  在第一个name对应的集合中且不在其他name对应的集合的元素集合
{'a', 'wangwu'}
>>> 
>>> r.flushdb()
True
>>> 
10.2.5 sortedSet类型
>>> import redis
>>> 
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,decode_responses=True,max_connections=10)
>>> pool
ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>
>>> r = redis.StrictRedis(connection_pool=pool)
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> mapping = {
...     'zhangsan':85,
...     'lisi':92, 
...     'wangwu':76
... }
>>> r.zadd('C++',mapping,nx=True)       #  在C++对应的有序集合中添加元素
3
>>> r.zrange('C++',0,-1,withscores=True) #  获取C++对应的有序集合的所有元素
[('wangwu', 76.0), ('zhangsan', 85.0), ('lisi', 92.0)]
>>> 
>>> r.zcard("C++") # 获取C++对应的有序集合元素的数量
3
>>> r.zcount('C++',min=0,max=90) 
# 获取C++对应的有序集合中分数 在 [min,max] 之间的个数
2
>>> 
>>> r.zincrby(name='C++',value='lisi',amount=3)  
 # 增加C++对应的有序集合的lisi对应的分数
95.0
>>> r.zrange('C++',0,-1,desc=False,withscores=True) 
# 按照索引范围获取C++对应的有序集合的元素,排序规则,默认按照分数从小到大排序
[('wangwu', 76.0), ('zhangsan', 85.0), ('lisi', 95.0)]
>>> r.zrevrange('C++',0,-1,withscores=True)
# 按照索引范围获取C++对应的有序集合的元素,排序规则,默认按照分数从大到小排序
[('lisi', 95.0), ('zhangsan', 85.0), ('wangwu', 76.0)]
>>> 
>>> r.zrangebyscore('C++',70,90) 
# 按照分数范围获取C++对应的有序集合的元素,排序规则,默认按照分数从小到大排序
['wangwu', 'zhangsan']
>>> r.zrevrangebyscore('C++',90,70) 
# 按照分数范围获取C++对应的有序集合的元素,排序规则,默认按照分数从大到小排序
['zhangsan', 'wangwu']
>>> 
>>> r.zrank('C++','lisi')
#  Zrank 返回有序集中指定成员的排名,有序集成员按分数值递增(从小到大)顺序排列。
2
>>> r.zrevrank('C++','lisi') 
#  Zrevrank 返回有序集中指定成员的排名,有序集成员按分数值递增(从大到小)顺序排列。
0
>>> 
>>> mapping = {
...     'xuliu':74,
...     'lisi':82, 
...     'wangwu':87
... }
>>> r.zadd('python',mapping,nx=True)
3
>>> r.zinterstore('sum_score_i',['C++','python'],aggregate='sum')   
# 获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
2
>>> r.zrange('sum_score_i',0,-1,withscores=True)
[('wangwu', 163.0), ('lisi', 177.0)]
>>> r.zunionstore('sum_score_u',['C++','python'],'min') 
# 获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
4
>>> r.zrange('sum_score_u',0,-1,withscores=True)
[('xuliu', 74.0), ('wangwu', 76.0), ('lisi', 82.0), ('zhangsan', 85.0)]
>>> 
>>> r.zrem('C++', 'zhangsan')                 
#  删除C++对应的有序集合中值是zhangsan的成员
1
>>> r.zrange('C++',0,-1,withscores=True)
[('wangwu', 76.0), ('lisi', 95.0)]
>>> 
>>> r.zremrangebyscore('C++', min=80, max=100) 
1
>>> r.zrange('C++',0,-1,withscores=True)
[('wangwu', 76.0)]
>>> 
>>> r.zremrangebyrank('python', min=1, max=3)
2
>>> r.zrange('python',0,-1,withscores=True)
[('xuliu', 74.0)]
>>> 

10.2.6 管道操作

Redis 模块默认在执行每次请求都会向连接池请求创建连接和断开申请操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作(即为一次操作)。

>>> import redis
>>> 
>>> pool = redis.ConnectionPool(host="127.0.0.1",port=6379,db=0,decode_responses=True,max_connections=10)
>>> 
>>> pool
ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>
>>> r = redis.StrictRedis(connection_pool=pool)
>>> r
Redis<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> pipe = r.pipeline(transaction=True)
>>> pipe
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> 
>>> pipe.set('name', 'jiangyou')
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> r.mget("name")
[None]
>>>
>>> pipe.set('age', 'age')
Pipeline<ConnectionPool<Connection<host=127.0.0.1,port=6379,db=0>>>
>>> r.mget("name","age")
[None, None]
>>>
>>> pipe.execute()
[True, True]
>>> r.mget("name","age")
['jiangyou', 'age']
>>> 
>>> import os
>>> res = os.system('clear')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值