Redis简明入门教程

本文来源:http://www.it-refer.com/2020/07/07/redis-tutorial-try-redis-io/

【第一节】
Redis是键值(key-value)存储数据库家族中的一员。
何为键值存储?其本质是具备将数据(value)存储到一个键(key)中的能力。这些数据后续可通过并只能通过之前那个key来获取。
通常,Redis被称为数据结构服务器。这是因为,从表面来看,Redis可以以key-value这样简单的形式来存储或获取数据。
但实际上,存储在Redis中的value可以包含复杂的数据结构,比如:字符串、链表、哈希表、集合、有序集合以及适用于概率学的数据结构hyperloglog。

先举个例子。
我们使用set命令将“fido”这个value存储到“server:name”这个key中。
SET server:name “fido”

Redis可以“持久”(依赖于数据过期和持久化策略)存储我们的数据。

这样,我们后续就可以询问Redis:保存在server:name键中的值是什么?
Redis会告诉我们:fido。这通过以下命令实现:
GET server:name
=> “fido”

你可以直接在redis命令行工具redis-cli中输入本文中的命令,=> 代表命令执行后的的输出。

Redis提供用于检测一个key是否存在的命令:
EXISTS server:name
=> 1
EXISTS server:blabla
=> 0
若key存在,返回1;不存在,返回0.

【第二节】
其他基本命令包括:del(删除一个key及存储其中的value)、incr(增加存储在key中数字的数值)。
SET connections 10
INCR connections
=> 11
INCR connections
=> 12
DEL connections
INCR connections
=> 1

incr支持设置每次操作的增量,默认为1。
INCRBY connections 100
=> 101

和incr对应的是decr,用于减少数值型value的值。
DECR connections
=> 100
DECRBY connections 10
=> 90
incr和decr非常适合计数器场景。

【第三节】
也许你会问:incr和decr这样的操作很简单啊,可以通过几行代码就能实现。比如:
x = GET count
x = x + 1
SET count x

确实。但这只适用于单客户端访问一个key的场景。想想一下,如果有两个客户端同时访问这个key呢?
A读取计数器的值为10,同时B也读到了10.
A将计数器的值加1后,将其写回数据库,此时计数器值为11;
B也将计数器的值加1,并将其写回数据库。此时计数器的值仍为11,而不是12.

显然,这种场景之下的计数器并没有起到正确的计数作用。

这是因为上述两个客户端对key的增加操作不是原子性的,需要3步才能完成。
Redis的incr很好的避免了这个问题,它是一个原子操作,一步搞定。

Redis中所有通过单条命令实现的操作都是原子的,包括那些适用于复杂数据结构上的操作。

因此使用Redis命令修改键值时,我们不需要考虑并发访问的问题。

【第四节】
我们向Redis存储key时,可以设置其存活时间,即这个key只在Redis中保留一段时间,过期后就不可再被访问。
这在Redis中通过expire和ttl命令实现。这两个命令的时间单位是秒。还有两个相似的命令,其时间单位是毫秒:pexpire和pttl。
SET resource:lock “Redis Demo”
EXPIRE resource:lock 120

上边,expire将resource:lock的过期时长设为120秒。可以使用ttl查看某个key的剩余存活时长。
TTL resource:lock
=> 113
//113秒之后
TTL resource:lock
=> -2

-2表示这个key不复存在。-1表示表示key永不过期。
注意,若对一个key重新执行set操作,其过期时长将被重置。
SET resource:lock “Redis Demo 1”
EXPIRE resource:lock 120
TTL resource:lock
=> 119

SET resource:lock “Redis Demo 2”
TTL resource:lock
=> -1

set接受额外的参数用于在设置key的值的同时直接设置其过期时长,这“两个”操作是一个原子操作。
SET resource:lock “Redis Demo 3” EX 5
TTL resource:lock
=> 5

Redis也支持取消一个key的过期设置,使其永久存在。这通过persist命令实现。
SET resource:lock “Redis Demo 3” EX 5
PERSIST resource:lock
TTL resource:lock
=> -1

【第五节】
我们开始时已经提到,Redis支持一些复杂的数据结构。现在做下介绍。
第一个就是list。list是一系列的有序值。与list相关的一些重要命令包括:rpush、lpush、llen、lrange、lpop、rpop等。
Redis中的list是可以随手就用的,只要表示list的key不是其他类型。什么意思?
在Redis中,你不需要在使用复杂数据结构之前,先创建一个key然后再为其赋值。你可以直接使用命令来操作这些结构,如果指定的key不存在,Redis会自动创建这个key。
相应的,如果一个key在经历一些操作之后变为空值,这个key也会自动从key空间中被删除。

rpush:向list尾部追加一个元素。
RPUSH friends “Alice”
RPUSH friends “Bob”

lpush:在list头部插入一个元素。
LPUSH friends “Sam”

lrange:获取list元素子集。它的第一个参数是起始元素的索引,第二个参数是结束元素的索引。
第二个参数是-1时,表示一直到list的最后一个(倒数第一个)元素,-2表示倒数第二个元素,以此类推。
LRANGE friends 0 -1
=> 1) “Sam”, 2) “Alice”, 3) “Bob”

LRANGE friends 0 1
=> 1) “Sam”, 2) “Alice”

LRANGE friends 1 2
=> 1) “Alice”, 2) “Bob”

除了添加和获取基于索引的子集之外,list还可以从开头或结尾删除并获取一个元素,即pop操作。
lpop:删除并返回list的第一个元素。
LPOP friends
=> “Sam”

rpop:删除并返回list的最后一个元素。
RPOP friends
=> “Bob”

llen:获取list元素个数。
LLEN friends
=> 1

rpush和lpush参数个数是可变的,我们可以在一条命令中指定多个参数。
RPUSH friends 1 2 3
=> 6
这里,6表示执行push之后list的长度。

【第六节】
接下来,我们介绍set。set和list类似,区别在于,set中的元素是无序的,并且是唯一的。
这两种数据结构都很重要。list可快速访问头部或尾部的元素,set可快速测试元素是否存在。

和set相关的一些重要命令包括:sadd、srem、sismember、smembers和sunion等。

sadd:向set中添加元素,支持可变参数,能同时添加多个元素。
SADD superpowers “flight”
SADD superpowers “x-ray vision” “reflexes”

srem:从set中删除元素,返回值1或0表示元素是否存在于set中。
SREM superpowers “reflexes”
=> 1
SREM superpowers “making pizza”
=> 0

sismember:测试元素是否存在于set中,返回1表示存在,0表示不存在。
SISMEMBER superpowers “flight”
=> 1
SISMEMBER superpowers “reflexes”
=> 0

sunion:计算两个或多个set的并集,返回所有并集中的元素。
SADD birdpowers “pecking”
SADD birdpowers “flight”
SUNION superpowers birdpowers
=> 1) “pecking”, 2) “x-ray vision”, 3) “flight”

sadd的执行结果和srem的结果一样重要。0表明要添加的元素已存在,1表示添加成功。
SADD superpowers “flight”
=> 0
SADD superpowers “invisibility”
=> 1

set也有个和list类似的pop命令,用于从其中删除并返回若干元素。由于set是无序的,被删除并返回的元素也是随机的。
SADD letters a b c d e f
=> 6
SPOP letters 2
=> 1) “c” 2) “a”

spop在key之后的参数为要删除的元素的个数。
set专门有一个命令用于随机返回其中的若干元素,只是返回,不删除。这个命令是srandmember。用法和spop类似,可自行试验。

【第七节】
set是很好用的数据结构,但因为其中的元素是无序的,对某些场景就不太合适了。
Redis 1.2开始引入了有序set:sorted set。
sorted set和set有些相似,区别在于其中的每个元素都关联了个分数(score)。这个分数用于对sorted set中的元素进行排序。

ZADD hackers 1940 “Alan Kay”
ZADD hackers 1906 “Grace Hopper”
ZADD hackers 1953 “Richard Stallman”
ZADD hackers 1965 “Yukihiro Matsumoto”
ZADD hackers 1916 “Claude Shannon”
ZADD hackers 1969 “Linus Torvalds”
ZADD hackers 1957 “Sophie Wilson”
ZADD hackers 1912 “Alan Turing”
这个例子中,集合元素的score是生日年份,元素的值为人名。

我们可以使用zrange获取sorted set中某个范围段的元素。
ZRANGE hackers 2 4
=> 1) “Claude Shannon”, 2) “Alan Kay”, 3) “Richard Stallman”

【第八节】
字符串、list、set和sorted set这些结构已经能处理很多工作了,但Redis还提供了一种数据结构:hash。
hash是字符串字段到字符串值的映射,所以适合表示对象结构。

比如,一个User包含name、surname、age等字段。我们可以用hash存储User的信息。
HSET user:1000 name “John Smith”
HSET user:1000 email “john.smith@example.com”
HSET user:1000 password “s3cret”
我们使用用户标识user:1000作为key,将各个字段依次设置到key中。

可以一次同时设置多个字段值。
HMSET user:1001 name “Mary Jones” password “hidden” email “mjones@example.com”

使用hgetall来获取所有字段。
HGETALL user:1000

也可以每次只获取一个字段的值。
HGET user:1001 name => “Mary Jones”

Redis支持对hash中的某个字段进行incr操作。
HSET user:1000 visits 10
HINCRBY user:1000 visits 1
=> 11
HINCRBY user:1000 visits 10
=> 21

HDEL user:1000 visits
HINCRBY user:1000 visits 1
=> 1

【本文译自Redis在线演示教程