Redis复习记录(二):数据类型与基本操作

一,数据库管理

1,查看所有数据库:

127.0.0.1:6379> CONFIG GET databases
1) "databases"
2) "16"

为什么这里只显示了数据库个数为16,且并内有显示数据库名?
因为 redis 默认的数据库个数就是十六个,可以查看配置文件:

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16

这里的注释就解释了第二个问题,实际上 redis 是根据数据库序列号来确定当前数据库的。
2,切换数据库与查看当前数据库名:
切换数据库时直接指定数据库序号(从0开始)就行。

127.0.0.1:6379> SELECT 3
OK
127.0.0.1:6379[3]> SELECT 0
OK
127.0.0.1:6379>

切换成功后,会在端口号后面显示当前数据库序号。
默认使用第一个数据库(0号),且不显示序号。

3,清空数据库:
清空数据库意味着删除数据库中的所有键值对,需谨慎!

# 清空当前数据库
flushdb
# 清空所有数据库
flushall

使用 Redis 进行应用设计和开发的一个核心概念是数据类型 。

在使用 Redis 进行应用设计和开发时,我们首先应该考虑的是, Redis原生支持的哪种数据类型最适合我们的场景 。然后直接使用 API 发送数据所对应的命令来操作想要操作的目标数据,而无需像在关系数据库中那样,使用 SQL 来操作数据。

这将通过一个Relp应用来学习Redis操作。Relp是一个供用户评论和推荐优秀餐厅、购物中心或其他服务的应用。

二,使用字符串( string )类型

1,SET 命令将一个字符串值关联到一个键

SET key value [EX seconds] [PX milliseconds] [NX|XX] 将字符串值 value 关联到 key 。

  • 如果 key 已经持有其他值, SET 就覆写旧值,无视类型。

  • 对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。

可选参数:

  • 从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:

  • EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。

  • PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value 。

  • NX:只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。

  • XX:只在键已经存在时,才对键进行设置操作。

将餐厅名称和地址分别用作键和值:

127.0.0.1:6379> SET "Extreme Pizza" "300 Broadway, New York, NY"
OK

2,GET 命令可以轻松地取回字符串的值

GET key 返回 key 所关联的字符串值。

  • 如果 key 不存在那么返回特殊值 nil 。

  • 假如 key 储存的值不是字符串类型,返回一个错误,因为 GET 只能用于处理字符串值。

127.0.0.1:6379> GET "Extreme Pizza"
"300 Broadway, New York, NY"

3,STRLEN 命令返回字符串的长度

STRLEN key 返回 key 所储存的字符串值的长度。

  • 当 key 储存的不是字符串值时,返回一个错误。

获取“Extreme Pizza,,地址的长度。

127.0.0.1:6379> STRLEN "Extreme Pizza"
(integer) 26

4,APPEND 命令可以向一个键的字符串值末尾追加字符串

APPEND key value 向一个键的字符串值末尾追加字符串

  • 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。

  • 如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。

想更新“Extreme Pizza"的地址。

127.0.0.1:6379> APPEND "Extreme Pizza" " 10011"
(integer) 32

5,SETRANGE 命令可以覆盖字符串值的一部分

SETRANGE key offset value 用 value 参数覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始。

  • 不存在的 key 当作空白字符串处理。

  • SETRANGE 命令会确保字符串足够长以便将 value 设置在指定的偏移量上,如果给定 key原来储存的字符串长度比偏移量小(比如字符串只有 5 个字符长,但你设置的offset是10),那么原字符和偏移量之间的空白将用零字节(zerobytes, “\x00” )来填充。

更新“ Extreme Pizza"的地址。

127.0.0.1:6379> SETRANGE "Extreme Pizza" 14 "Washington, DC 20009"
(integer) 34
127.0.0.1:6379> GET "Extreme Pizza"
"300 Broadway, Washington, DC 20009"

6,SETNX 命令仅在键不存在时设置键的值

SETNX key value 将 key 的值设为 value ,当且仅当 key 不存在。

  • 若给定的 key 已经存在,则 SETNX 不做任何动作。

  • SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

  • 设置成功,返回 1 。 设置失败,返回 0 。

127.0.0.1:6379> SETNX "Lobster Palace"  "437 Main St, Chicago, IL"
(integer) 1
127.0.0.1:6379> SETNX "Extreme Pizza" "300 Broadway, New York, NY 10011"
(integer) 0

7,MSET 和 MGET 命令来一次性地设置和获取多个键的值

MSET key value [key value ...] 同时设置一个或多个 key-value 对。

  • 如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值,如果这不是你所希望的效果,请考虑使用 MSETNX命令:它只会在所有给定 key 都不存在的情况下进行设置操作。

  • MSET 是一个原子性(atomic)操作,所有给定 key 都会在同一时间内被设置,某些给定 key 被更新而另一些给定 key没有改变的情况,不可能发生。

127.0.0.1:6379> MSET "Sakura Sushi" " 123 Ellis St, Chicago, IL" "Green Curry Thai" "456 American Way, Seattle, WA"
OK

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

  • 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。因此,该命令永不失败。
127.0.0.1:6379> MGET "Sakura Sushi" "Green Curry Thai" "nonexistent"
1) " 123 Ellis St, Chicago, IL"
2) "456 American Way, Seattle, WA"
3) (nil)

#三,使用列表( list )类型
Redis 中的列表更像是数据结构世界中的双向链表。

1,LPUSH 在列表的左端插入

LPUSH key value [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 存在但不是列表类型时,返回一个错误。

使用一个列表来存储用户最喜欢的餐厅 :

127.0.0.1:6379> LPUSH favorite_restaurants " PF Chang's" "Olive Garden"
(integer) 2

2,LRANGE获取列表中所有值

LRANGE key start stop 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。

  • 下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

获取列表中所有餐厅的名称:

127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Olive Garden"
2) " PF Chang's"

3,RPUSH在列表的右端插入

RPUSH key value [value ...] 将一个或多个值 value 插入到列表 key 的表尾(最右边)。

  • 如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b、 RPUSH mylist c 。

  • 如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。

  • 当 key 存在但不是列表类型时,返回一个错误。

在列表的右端插入餐厅的名称:

127.0.0.1:6379> RPUSH favorite_restaurants "Outback Steakhouse" "Red Lobster"
(integer) 4

4,LINSERT 将之插入到指定位置前后

LINSERT key BEFORE|AFTER pivot value 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。

  • 当 pivot 不存在于列表 key 时,不执行任何操作。

  • 当 key 不存在时, key 被视为空列表,不执行任何操作。

  • 如果 key 不是列表类型,返回一个错误。

在“PF Chang ’ s”之后插入一个新餐厅的名称:

127.0.0.1:6379> LINSERT favorite_restaurants AFTER " PF Chang's" "Indian Tandoor"
(integer) 5

5,LINDEX 获取指定位置的值

LINDEX key index 返回列表 key 中,下标为 index 的元素。

  • 下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

  • 如果 key 不是列表类型,返回一个错误。

获取列表中位于索引位置 3 处餐厅的名称:

127.0.0.1:6379>  LINDEX favorite_restaurants 3
"Outback Steakhouse"

6,LPOPRPOP 从列表中删除一个元素

LPOP key 移除并返回列表 key 的头元素。

127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Olive Garden"
2) " PF Chang's"
3) "Indian Tandoor"
4) "Outback Steakhouse"
5) "Red Lobster"
127.0.0.1:6379> LPOP favorite_restaurants
"Olive Garden"
127.0.0.1:6379> LPOP favorite_restaurants
" PF Chang's"
127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Indian Tandoor"
2) "Outback Steakhouse"
3) "Red Lobster"
127.0.0.1:6379> LPOP non_existent
(nil)

RPOP key 移除并返回列表 key 的尾元素

127.0.0.1:6379> RPOP favorite_restaurants
"Red Lobster"
127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Indian Tandoor"
2) "Outback Steakhouse"

7,LTRIM 命令保留指定范围内的元素

LTRIM key start stop 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

举个例子,执行命令 LTRIM list 0 2 ,表示只保留列表 list 的前三个元素,其余元素全部删除。

  • 下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

  • 当 key 不是列表类型时,返回一个错误。

  • LTRIM 命令通常和 LPUSH 命令或 RPUSH 命令配合使用,举个例子:
    LPUSH log newest_log
    LTRIM log 0 99
    这个例子模拟了一个日志程序,每次将最新日志 newest_log放到 log 列表中,并且只保留最新的 100 项。

删除最近关门的餐厅:

127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "PF Chang's"
2) "Indian Tandoor"
3) "Outback Steakhouse"
127.0.0.1:6379> LTRIM favorite_restaurants 1 -1
OK
127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Indian Tandoor"
2) "Outback Steakhouse"

8,LSET 命令设置列表中指定索引位置处元素的值

LSET key index value 将列表 key 下标为 index 的元素的值设置为 value 。

  • 当 index 参数超出范围,或对一个空列表( key 不存在)进行 LSET 时,返回一个错误。

更新餐厅名:

127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Indian Tandoor"
2) "Outback Steakhouse"
127.0.0.1:6379> LSET favorite_restaurants 1 "Longhorn Steakhouse"
OK
127.0.0.1:6379> LRANGE favorite_restaurants 0 -1
1) "Indian Tandoor"
2) "Longhorn Steakhouse"

9, BLPOPBRPOP 是LPOP 和 RPOP 命令有对应的阻塞版本

三,使用哈希( hash )类型

哈希对于存储对象属性而言是一种完美的数据类型 。

将使用哈希来存储餐厅的信息,例如地址、电话号码和评分等。

1,HMSET 命令来设置哈希键-多个字段-值

HMSET key field value [field value ...] 同时将多个 field-value (域-值)对设置到哈希表 key 中。

  • 此命令会覆盖哈希表中已存在的域。

  • 如果 key 不存在,一个空哈希表被创建并执行 HMSET 操作。

设置“ Kyoto Ramen”餐厅的属性信息:

127.0.0.1:6379> HMSET "Kyoto Ramen" "address" "801 Miss ion St, San Jose, CA" "phone" "555-123-6543" "rating" "5.0"
OK

结构如下:
"Kyoto Ramen” = {
    ”address ”:801 Miss ion St, San Jose, CA”,
    ”phone ”:555-123-6543,
    ”rating ”:5.0}

2,HMGET 命令从一个哈希中获取多个字段对应的值

HMGET key field [field ...] 返回哈希表 key 中,一个或多个给定域的值。

  • 如果给定的域不存在于哈希表,那么返回一个 nil 值。

  • 因为不存在的 key 被当作一个空哈希表来处理,所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表。

127.0.0.1:6379> HMGET "Kyoto Ramen" "address" "phone" "rating"
1) "801 Miss ion St, San Jose, CA"
2) "555-123-6543"
3) "5.0"

3,HGET 命令从一个哈希中获取某个字段对应的值

HGET key field 返回哈希表 key 中给定域 field 的值。

127.0.0.1:6379>  HGET "Kyoto Ramen" "rating"
"5.0"

4,HEXISTS 命令测试一个哈希中是否存在某个字段

HEXISTS key field 查看哈希表 key 中,给定域 field 是否存在。

127.0.0.1:6379> HEXISTS "Kyoto Ramen" "phone"
(integer) 1
127.0.0.1:6379> HEXISTS "Kyoto Ramen" "hours"
(integer) 0

5,HGETALL 命令获取一个哈希中的所有字段和值

HGETALL key 返回哈希表 key 中,所有的域和值。

  • 在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。
127.0.0.1:6379> HGETALL "Kyoto Ramen"
1) "address"
2) "801 Miss ion St, San Jose, CA"
3) "phone"
4) "555-123-6543"
5) "rating"
6) "5.0"

6,HSET 命令设置单个字段的值

HSET key field value 将哈希表 key 中的域 field 的值设为 value 。

  • 如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。

  • 如果域 field 已经存在于哈希表中,旧值将被覆盖。

修改餐厅评分并添加开业状态:

127.0.0.1:6379> HSET "Kyoto Ramen" "rating" "4.9"
(integer) 0
127.0.0.1:6379> HSET "Kyoto Ramen" "status" "open"
(integer) 1
127.0.0.1:6379> HMGET "Kyoto Ramen" "rating" "status"
1) "4.9"
2) "open"

7,HOEL 命令从哈希中删除字段

HGET key field 返回哈希表 key 中给定域 field 的值。

127.0.0.1:6379> HDEL "Kyoto Ramen" "address" "phone"
(integer) 2
127.0.0.1:6379> HGETALL "Kyoto Ramen"
1) "rating"
2) "4.9"
3) "status"
4) "open"

8,HSETNX 命令则仅在字段不存在的情况下才设置字段的值

HSETNX key field value 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。

  • 若域 field 已经存在,该操作无效。

  • 如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令。

127.0.0.1:6379> HSETNX "Kyoto Ramen" "phone" "555-555-0001"
(integer) 1
127.0.0.1:6379> HSETNX "Kyoto Ramen" "phone" "555-555-1111"
(integer) 0

9,HSCAN 命令来增量地获取所有字段和值

一个哈希最多能够容纳(2^32)-1个字段 。 如果一个哈希的宇段非常多,那么执行 HGETALL 命令时可能会阻塞 Redis 服务器。 在这种情况下,我们可以使用 HSCAN 命令来增量地获取所有字段和值.

该命令会增量地迭代遍历元素,从而不会造成服务器阻塞 。 HSCAN 命令是一种基于指针的迭代器,因此我们需要在每次调用命令时指定一个游标(从 0 开始)。 当一次 HSCAN 运行结束后, Redis 将返回一个元素列表以及一个新的游标,这个游标可以用于下一次迭代。

HSCAN key cursor [MATCH pattern] [COUNT number]

  • 选项 MATCH 可以用来匹配满足指定 G lob 表达式的字段 。 选项 COUNT 用来说明在每次迭代中应该返回多少个元素 。

但是,这个选项仅仅是一种参考,Redis 并不保证返回的元素数量就是 COUNT个,COUNT 的默认值是 10 。

设我们有一个非常大的哈希,其中有数百万个甚至更多的字段。 下面,让我们使用 HSCAN 来遍历包含关键字 garden 的字段:

127.0.0.7:6379> HSCAN restaurant_ratings O MATCH *garden*
1)"309"
2) 1)"panda garden"
2)"3.9"
3)"chang’s garden"
4)"4.5"
5)"rice garden"
6)"4 .8"

使用由服务器返回的新游标 309 来进行一次新的迭代:\

127.0.0.7:6379> HSCAN restaurant_ratings 309 MATCH *garden*
1)"0"
2) 1)"szechuwan garden"
2)"4.9"
3)"garden wok restaurant"
4)"4.7"
5)"win garden"
6)"4.0"
7)"east garden restaurant"
8)"4 6"

四,使用集合( set )类型

集合类型是由唯一 、无序对象组成的集合( collection ) 。 它经常用于测试某个成员是否在集合中 、 重复项删除和集合运算(求并、交、差集)。

1,SADD 命令将元素插入集合

SADD key member [member ...] 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。

  • 假如 key 不存在,则创建一个只包含 member 元素作成员的集合。

  • 当 key 不是集合类型时,返回一个错误。

给"Original Buffalo Wings"餐厅添加标签:

127.0.0.1:6379> SADD "Original Buffalo Wings" "affordable" "spicy" "busy" "great taste"
(integer) 4

2,,SISMEMBER 命令测试一个元素是否位于集合中

SISMEMBER key member 判断 member 元素是否集合 key 的成员。

  • 如果 member 元素是集合的成员,返回 1 。 如果 member 元素不是集合的成员,或 key 不存在,返回 0 。
127.0.0.1:6379> SISMEMBER "Original Buffalo Wings" "busy"
(integer) 1
127.0.0.1:6379> SISMEMBER "Original Buffalo Wings" "costly"
(integer) 0

3,SREM 命令从集合中删除元素

SREM key member [member ...] 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。

  • 当 key 不是集合类型,返回一个错误。

餐厅的标签中删除“busy”和”spicy”:

127.0.0.1:6379> SREM "Original Buffalo Wings" "busy" "spicy"
(integer) 2
127.0.0.1:6379> SISMEMBER "Original Buffalo Wings" "busy"
(integer) 0
127.0.0.1:6379> SISMEMBER "Original Buffalo Wings" "spicy"
(integer) 0

4,SCARD 命令获取集合中成员的数量

SCARD key 返回集合 key 的基数(集合中元素的数量)。

127.0.0.1:6379> SCARD "Original Buffalo Wings"
(integer) 2

5,SMEMBERS 命令列出集合中的所有元素

SMEMBERS key 返回集合 key 中的所有成员。

  • 不存在的 key 被视为空集合。
127.0.0.1:6379> SMEMBERS "Original Buffalo Wings"
1) "great taste"
2) "affordable"
  • 但是,与我们在使用哈希类型中所提到的 HGETALL 类似,在一个大的集合中使用 SMEMBERS 命令可能会阻塞服务器。 因此,我们并不推荐使用 SMEMBERS 命令,而是应该使用 SSCAN 命令 。 SSCAN 与我们在使用哈希类型中的 HSCAN 命令的用法非常类似。

6,集合运算
SUNIONSUNIONSTORE 用于计算并集,
SINTERSINTERSTORE 用于计算交集,
SDIFFSDIFFSTORE 用于计算差集 。
不带 STORE 后缀的命令只返回相应操作的结果集合,而带 STORE 后缀的命令则会将结果存储到一个指定的键中 。

给另一家餐厅"Big Bear Wings"添加标签 ,然后获取"Original Buffalo Wings ”和” Big Bear Wings ”餐厅共有的标签:

127.0.0.1:6379> SMEMBERS "Original Buffalo Wings"
1) "great taste"
2) "affordable"
127.0.0.1:6379> SADD "Big Bear Wings" "affordable" "spacious" "great music"
(integer) 3
127.0.0.1:6379> SINTER "Original Buffalo Wings" "Big Bear Wings"
1) "affordable"
127.0.0.1:6379> SINTERSTORE "common_tags" "Original Buffalo Wings" "Big Bear Wings"
(integer) 1
127.0.0.1:6379> SMEMBERS "common_tags"
1) "affordable"

五,使用有序集合( sorted set )类型

单词“ Sorted”意味着这种集合中的每个元素都拥有一个可用于排序的权重,并且我们可以按顺序从集合中获取元素,在某些需要一直保持数据有序的场景中,使用这种原生的有序特性是很方便的 。

1,ZADD 命令插入成员与score

ZADD key score member [[score member] [score member] ...] 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。

  • 如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该member 在正确的位置上。

  • score 值可以是整数值或双精度浮点数。

  • 如果 key 不存在,则创建一个空的有序集并执行 ZADD 操作。

  • 当 key 存在但不是有序集类型时,返回一个错误。

  • 返回值:被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。

  • ZADD 命令中使用 NX 选项,能够实现在不更新已存在成员的情况下只添加新的成员
  • 选项 xx 允许我们在不向集合中增加新元素的情况下更新集合(即只更新存在的成员而不添加新成员)
  • 多个不同的成员可能具有相同的权重。在这种情况下,Redis将按照字典顺序进行排序

将点评数和每个餐厅的名字放入一个有序集合中:

127.0.0.1:6379> ZADD ranking:restaurants 100 "Olive Garden" 23 "PF Changs" 34 "Outback Steakhouse" 45 "Red Lobster" 88 "Longhorn Steakhouse"
(integer) 5

2,ZREVRANGE 命令获取指定范围内的成员

ZREVRANGE key start stop [WITHSCORES] 返回有序集 key 中,指定区间内的成员。

  • 其中成员的位置按 score 值递减(从大到小)来排列。 具有相同 score 值的成员按字典序的逆序(reverse lexicographical order)排列。 除了成员按 score 值递减的次序排列这一点外, ZREVRANGE 命令的其他方面和 ZRANGE 命令一样。

获取这个评分排名:

127.0.0.1:6379> ZREVRANGE ranking:restaurants 0 -1 WITHSCORES
 1) "Olive Garden"
 2) "100"
 3) "Longhorn Steakhouse"
 4) "88"
 5) "Red Lobster"
 6) "45"
 7) "Outback Steakhouse"
 8) "34"
 9) "PF Changs"
10) "23"
127.0.0.1:6379> ZREVRANGE ranking:restaurants 0 -1
1) "Olive Garden"
2) "Longhorn Steakhouse"
3) "Red Lobster"
4) "Outback Steakhouse"
5) "PF Changs"

3,ZINCRBY命令为指定成员的score增加数值

ZINCRBY key increment member 为有序集 key 的成员 member 的 score 值加上增量 increment 。

  • 可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -5 member ,就是让
    member 的 score 值减去 5 。

  • 当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD
    key increment member 。

  • 当 key 不是有序集类型时,返回一个错误。

  • score 值可以是整数值或双精度浮点数。

如果 Relp 中的某个用户点了赞,对餐厅的投票数加一 :

127.0.0.1:6379>  ZINCRBY ranking:restaurants 1 "Red Lobster"
"46"

4,ZREVRANK命令据score获取成员排名

ZREVRANK key member 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。

  • 排名以 0 为底,也就是说, score 值最大的成员排名为 0 。

  • 使用 ZRANK 命令可以获得成员按 score 值递增(从小到大)排列的排名。

浏览某个特定餐厅的排名:

127.0.0.1:6379> ZREVRANK ranking:restaurants "Red Lobster"
(integer) 2

5,ZSCORE命令获取score

ZSCORE key member 返回有序集 key 中,成员 member 的 score 值。

  • 如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 null。

浏览某个特定餐厅的投票数:

127.0.0.1:6379> ZSCORE ranking:restaurants "Olive Garden"
"100"

6,ZUNIONSTORE 命令合并两个sorted set

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] 计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以numkeys 参数指定,并将该并集(结果集)储存到destination

  • 默认情况下,结果集中某个成员的 score 值是所有给定集下该成员 score 值之和 。

  • WEIGHTS:可以为 每个给定有序集分别指定一个乘法因子(multiplication factor),每个给定有序集的所有成员的 score 值在传递给聚合函数(aggregation function)之前都要先乘以该有序集的因子。如果没有指定该选项,乘法因子默认设置为 1 。

  • AGGREGATE:可以指定并集的结果集的聚合方式。默认使用的参数 SUM ,可以将所有集合中某个成员的 score 值之和作为结果集中该成员的 score 值;使用参数 MIN,可以将所有集合中某个成员的最小 score 值作为结果集中该成员的 score 值;而参数 MAX 则是将所有集合中某个成员的最大 score值作为结果集中该成员的 score 值。

127.0.0.1:6379> ZADD ranking2:restaurants 50 "Olive Garden" 33 "PF Changs" 55 "Outback Steakhouse" 190 "Kung Pao House"

(integer) 4
127.0.0.1:6379> ZUNIONSTORE totalranking 2 ranking:restaurants ranking2:restaurants WEIGHTS 1 2
(integer) 6
127.0.0.1:6379> ZREVRANGE totalranking 0 -1 WITHSCORES
 1) "Kung Pao House"
 2) "380"
 3) "Olive Garden"
 4) "200"
 5) "Outback Steakhouse"
 6) "144"
 7) "PF Changs"
 8) "89"
 9) "Longhorn Steakhouse"
10) "88"
11) "Red Lobster"
12) "46"

六,使用 Hyperloglog 类型

在日常的各种数据处理场景中,“唯一计数”是一项常见的任务 。 在 Redis 中,虽然我们可以使用集合来进行唯一计数;但是,当数据量增大到上千万时,就需要考虑内存消耗和性能下降问题了。

如果我们不需要获取数据集的内容,而只是想得到不同值的个数,那么就可以使用 HyperLogLog(HLL)数据类型来优化使用集合类型时存在的内存和性能问题。

1,PFADD 命令将元素加入到一个 HyperLogLog 类型的key

PFADD key element [element ...]

计算 Relp 中到访名为 Olive Garden 的餐厅的不同客户数:

127.0.0.1:6379> PFADD "Counting:Olive Garden" "0000123"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden" "0023992"
(integer) 1

2,PFCOUNT命令统计HyperLogLog 类型的key中元素个数

PFCOUNT key [key ...] 返回给定 HyperLogLog 的基数估算值。

127.0.0.1:6379> PFCOUNT "Counting:Olive Garden"
(integer) 2

3,PFMERGE 命令合并多个HyperLogLog 类型的key

PFMERGE destkey sourcekey [sourcekey ...] 将多个 HyperLogLog 合并为一个HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有 给定 HyperLogLog 进行并集计算得出的。

如果想要展示 Olive Garden 在一个星期中的独立访客数,并将其作为每周流行度的标志 。 那么,我们可以每天生成一个 HLL ,然后用 PFMERGE 命令把这 7 天的数据合并为一个:

127.0.0.1:6379> PFADD "Counting:Olive Garden:20170903" "0023992" "0023991" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170904" "0023992" "0023991" "0045992"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170905" "0024492" "0023211" "0045292"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170906" "0023999" "0063991" "0045922"
(integer) 1
127.0.0.1:6379>  PFADD "Counting:Olive Garden:20170907" "0023292" "0023991" "0045921"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170908" "0043282" "0023984" "0045092"
(integer) 1
127.0.0.1:6379> PFADD "Counting:Olive Garden:20170909" "0023992" "0023991" "0045992"
(integer) 1
127.0.0.1:6379> PFCOUNT "Counting:Olive Garden:20170903week"
(integer) 14

七,使用 Geo 类型

随着移动端设备机的不断普及, 基于地理位置的服务变得越来越受欢迎。 Redis 从 3.2 版本开始正式引人了Geo相关的 API ,用于支持存储和查询这些地理位置相关场景中的坐标 。

1,GEOADD命令设置地点经纬度数据

GEOADD location-set longitude latitude member [longitude latitude member ...]

把位于加州的五家餐厅增加到名为 restaurants:CA 的 Geo 集合中:

127.0.0.1:6379> GEOADD restaurants:CA -121.896321 37.916750 "Olive Garden" -117.910937 33.804047 "P.F. Changs" -118.508020 34.453276 "Outback Steakhouse" -119.152439 34.264558 "Red Lobster" -122.276909 39.458300 "Longhorn Charcoal Pit"
(integer) 5

2,GEOPOS 命令从 Geo 集合中获取指定成员的坐标:

127.0.0.1:6379> GEOPOS restaurants:CA "Red Lobster"
1) 1) "-119.15243893861771"
   2) "34.264557072833789"

3,GEODIST 命令获取两个地理位置的距离

GEODIST location-set location-x location-y [unit]
其中 unit 参数是距离单位,可选填

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。
127.0.0.1:6379> GEODIST restaurants:CA "P.F. Changs" "Outback Steakhouse" km
"90.7557"

4,GEORADIUS命令获取指定范围内的坐标点

GEORADIUS location-set longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [ASC|DESC] [COUNT count]

  • radius表示范围距离,距离单位是m|km|ft|mi

可选参数:

  • WITHCOORD:传入WITHCOORD参数,则返回结果会带上匹配位置的经纬度。
  • WITHDIST:传入WITHDIST参数,则返回结果会带上匹配位置与给定地理位置的距离。
  • ASC|DESC:默认结果是未排序的,传入ASC为从近到远排序,传入DESC为从远到近排序。
  • WITHHASH:传入WITHHASH参数,则返回结果会带上匹配位置的hash值。 COUNT
  • count:传入COUNT参数,可以返回指定数量的结果

假设读者位于在 Mount Diablo State Park, 其经/纬度是-121.923170/37.878506,如果读者想知道距当前位置 skrn 以内的餐厅,那么可以使用:

127.0.0.1:6379> GEORADIUS restaurants:CA -121.923170 37.878506 5 km
1) "Olive Garden"

5,GEORADIUSBYMEMBER 命令搜索 Geo 集合中指定范围内的坐标点
搜索 Geo 集合中距离“Outback Steakhouse,距离小于 100 km 的餐厅:

127.0.0.1:6379> GEORADIUSBYMEMBER restaurants:CA "Outback Steakhouse" 100 km
1) "Red Lobster"
2) "Outback Steakhouse"
3) "P.F. Changs"

Geo 集合实际上被存储为一个有序集合( Redis 中的 zset ),因此有序集合支持的所有命令都可以用于 Geo 数据类型 。

八,键管理

Redis 中的数据都是由键值对组成的 。 因此,管理键是应用程序开发和 Redis 管理的另一个基本知识。

1,DBSIZE命令获取所有键的个数

127.0.0.1:6379> DBSIZE
(integer) 50025

2, KEYS命令或SCAN命令获取所有键
在 Redis 中的一个命令执行过程期间 ,所有服务器接收到的其他命令都必须等待被处理。 因此,对于生产环境的性能来说,调用KEYS 命令是一个危险的操作。 对于这个问题,可以使用此前案例中所提到的 SCAN 类命令,如SCANSSCAN ,以在不阻塞服务器的情况下在 Redis 服务器上遍历键 。

采用全量式KEYS命令:

KEYS pattern

查找所有符合给定模式 pattern 的 key :

  • KEYS * 匹配数据库中所有 key 。
  • KEYS h?llo 匹配 hello 、hallo 和 hxllo 等。
  • KEYS h*llo 匹配 hllo 和 heeeeello 等。
  • KEYS h[ae]llo 匹配 hello 和 hallo。
  • 特殊符号用 \ 隔开。
127.0.0.1:6379> KEYS *
......
50023) "user_agent:2789"
50024) "simple_registration:579"
50025) "user_agent:8587"
(0.73s)

采用增量式的SCAN命令:

127.0.0.1:6379> scan 0
1) "18432"
2)  1) "company:3945"
    2) "detailed_registration:508"
    3) "customer:5211"
    4) "detailed_registration:659"
    5) "customer:6139"
    6) "company:1640"
    7) "simple_registration:2049"
    8) "company:3892"
    9) "user_agent:9178"
   10) "simple_registration:6059"
127.0.0.1:6379> SCAN 18432
1) "14336"
2)  1) "company:1542"
    2) "customer:4306"
    3) "user_agent:6220"
    4) "company:8466"
    5) "customer:2375"
    6) "customer:7657"
    7) "detailed_registration:1230"
    8) "customer:4381"
    9) "customer:5321"
   10) "detailed_registration:2876"
   11) "simple_registration:5163"

3,EXISTS 命令判断一个键是否存在

EXISTS key 检查给定 key 是否存在。

  • 若 key 存在,返回 1 ,否则返回 0 。
127.0.0.1:6379> EXISTS "simple_registration:7681"
(integer) 1
127.0.0.1:6379> EXISTS "simple_registration:99999"
(integer) 0

4,TYPE 命令获取键的数据类型

TYPE key 返回 key 所储存的值的类型

  • none (key不存在) 	
    
  • string (字符串)

  • list (列表)

  • set (集合)

  • zset (有序集)

  • hash (哈希表)

127.0.0.1:6379>  TYPE "company:3859"
hash

5,RENAMERENAMENX 命令重命名一个键:

RENAME key newkey 将 key 改名为 newkey 。

  • 当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。

  • 当 newkey 已经存在时, RENAME 命令将覆盖旧值。

RENAME key newkey 将 key 改名为 newkey 。

  • 当且仅当 newkey 不存在时,将 key 改名为 newkey 。 修改成功时,返回 1 。

当 key 不存在时,返回一个错误。

127.0.0.1:6379> EXISTS "customer:6591"
(integer) 1
127.0.0.1:6379> EXISTS "customer:659l:renamed"
(integer) 0
127.0.0.1:6379> RENAME "customer:6591" "customer:659l:renamed"
OK
127.0.0.1:6379> EXISTS "customer:6591"
(integer) 0
127.0.0.1:6379> EXISTS "customer:659l:renamed"
(integer) 1

RENAME 会在目标键己存在时将其删除 。 这个 DEL 操作可能导致高延迟 。因此,重命名操作的最佳实践是,如果目标键已存在则先对其执行UNLINK然后再进行重命名 。

6,DEL 命令或 UNLINK 命令删除键

DEL key [key ...] 删除给定的一个或多个 key 。

  • 不存在的 key 会被忽略。 被删除 key 的数量。
127.0.0.1:6379> DEL "detailed_registration:l665" "simple_registration:6411" "user_agent:l683 "
(integer) 1

UNLINK 在 Redis 4.0 以上版本引人,主要用于执行大KEY的异步删除.

127.0.0.1:6379> UNLINK "company:1664"
(integer) 1

应该对 DEL 命令额外留意。 如果要删除的键是字符串以外的数据类型 ,那么当键中的元素数量很大时就可能会遭遇服务器延迟 。 为了避免这种灾难,应该使用 UNLINK 替代 。 UNLINK会在另一个线程而不是主事件循环线程中执行删除操作,因而不会阻塞事件的处理。

7,超时设置
为键设置超时时间(意味着客户端访问服务器的这个键值时,会先判断是否过期):

# 设置超时时间,单位秒。
EXPIRE key seconds

# 剩余过期秒数,返回-1表示没有设置过过期时间,对于不存在的key,返回-2
TTL key 

# 持久化,永不过期。
PERSIST key

8,key的设计规范

key的一个格式约定:
1: 第1段放置表名作为前缀,如,tag:
2: 第2段放置用于区分key的字段——对应mysql中的主键的列名,如userid
3: 第3段放置主键值,如2,3,4…, a , b ,c 4:
4: 第4段放置要存储的列名

举个例子:将用户表转为键值对存储。

userid	username	password	email
9		lisi		1111111		lisi@163.com

set user:userid:9:username lisi
set user:userid:9:password 111111
set user:userid:9:email    lisi@163.com

然后查看某个用户的所有信息:

keys user:userid:9*

更多键管理命令与原理请参考官方文档

九,用python实现一个redis小项目

这是《redis in action》中的一个小项目,旨在进一步理解对不同数据类型的使用。

描述:构建一个文章投票网站——如果一篇文章获得了至少200张支持票(up vote),那么网站就认为这篇文章是一篇有趣的文章,就是把文章放到文章列表前100位至少一天;暂时不提供投反对票(down vote)的功能。

存储文章信息:对于网站里的每篇文章,需要有文章的标题、指向文章的网址、发布文章的用户、文章的发布时间、文章得到的投票数量等信息。

实现:使用hash数据类型
在这里插入图片描述

时间榜:存储文章的发布时间,用于后续的评分计算
评分功能:为了产生一个能够随着时间流逝而不断减少的评分,程序需要根据文章的发布时间和当前时间来计算文章的评分。为了尽量节约内存,我们规定当一篇文章发布期满一周之后,用户将不能再对它进行投票,文章评分将被固定。
实现:使用zset类型
在这里插入图片描述

评分榜:存储文章的评分,
在这里插入图片描述

补充:为了防止用户对同一篇文章进行多次投票,网站需要为每篇文章记录一个已投票用户名单。文章的评分被固定下来后,而记录文章已投票用户名单的集合也会被删除。
实现:使用set类型
在这里插入图片描述

发布文章:
在这里插入图片描述

获取文章:

文章投票:
在这里插入图片描述

在这里插入代码片
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值