Redis 操作数据
# 20.Redis 操作数据
在使用 Redis 来存取数据之前,我们得先聊聊 Redis 支持的数据结构,然后才是讲解其存取命令。注意 Redis 不区分命令大小写。
# Redis 的数据结构
首先,Redis 可以看成一个 Map,使用 key-value 的方式来存储数据;其中,key 都是字符串,value 则有 5 种取值:
- 字符串类型 string,也是最常用的一种
- 哈希类型 hash : 可以理解为是一个 map
- 列表类型 list :可以理解为是一个 列表,类似 LinkedList,支持重复元素
- 集合类型 set : 可以理解为是一个集合,类似 HashSet,不允许重复元素
- 有序集合类型 sortedset:有序的集合,不允许重复元素
# 字符串类型 string
存储数据的语法格式:set key value
,设置成功后会返回 OK,多次 set 会覆盖之前设置的数据。
127.0.0.1:6379> set username peterjxl
OK
2
获取数据的语法格式:get key
,如果 key 不存在则返回 nil
(可以理解为是 null)
127.0.0.1:6379> get username
"peterjxl"
127.0.0.1:6379> get usder
(nil)
2
3
4
删除数据的格式: del key
127.0.0.1:6379> del age
(integer) 1
2
set, get, del,是非常基本的用法,还有很多用法,例如可以追加字符串:
127.0.0.1:6379> set peterjxl https://www.peterjxl
OK
127.0.0.1:6379> append peterjxl .com
(integer) 24
127.0.0.1:6379> get peterjxl
"https://www.peterjxl.com"
2
3
4
5
6
7
8
或者重命名 key:
127.0.0.1:6379> rename peterjxl mywebsite
OK
127.0.0.1:6379> get mywebsite
"https://www.peterjxl.com"
2
3
4
5
还可以自增一个 value(如果是字母,则自增无效):
127.0.0.1:6379> set visitors 0
OK
127.0.0.1:6379> incr visitors
(integer) 1
127.0.0.1:6379> incr visitors
(integer) 2
127.0.0.1:6379> get visitors
"2"
2
3
4
5
6
7
8
9
10
11
或者指定增加的数字:
127.0.0.1:6379> incrby visitors 100
(integer) 102
127.0.0.1:6379> get visitors
"102"
2
3
4
5
同时获得/设置多个键值
MGET key [key …]
MSET key value [key value …]
2
MGET/MSET 与 GET/SET 相似,不过 MGET/MSET 可以同时获得/设置多个键的键值。例如:
redis> MSET key1 v1 key2 v2 key3 v3
OK
redis> GET key2
"v2"
redis> MGET key1 key3
1) "v1"
2) "v3"
2
3
4
5
6
7
8
9
更多语法,可以参考 Redis 官方命令手册 (opens new window),部分语法如下:这里就不一一演示了
语法 | 作用 |
---|---|
SET key value | 设置 key = value |
GET key | 获得键 key 对应的值 |
GETSET key value | 设置键的字符串值,并返回旧值 |
SETNX key value | 设置键的值,只有当该键不存在 |
STRLEN key | 得到存储在键的值的长度 |
INCR key | 增加键的整数值一次 |
INCRBY key increment | 由给定的数量递增键的整数值 |
INCRBYFLOAT key increment | 由给定的数量递增键的浮点值 |
DECR key | 递减键一次的整数值 |
DECRBY key decrement | 递减键一次的指定的整数值 |
APPEND key value | 追加值到一个键 |
DEL key | 如果存在删除键 |
RENAME key newkey | 更改键的名称 |
TYPE key | 返回存储在键的数据类型的值。 |
..... | ...... |
# 哈希类型 hash
存储:hset key field value
,这里创建一个名字为 key 的 set 集合,并往集合里存放了键值对 field-value,例如:
127.0.0.1:6379> hset myhashset username peterjxl
(integer) 1
127.0.0.1:6379> hset myhashset password 123456
(integer) 1
2
3
4
5
获取:hget key filed
,这里获取一个名字为 key 的集合,然后根据 filed 获取集合里的 value,例如:
127.0.0.1:6379> hget myhashset username
"peterjxl"
127.0.0.1:6379> hget myhashset password
"123456"
2
3
4
5
获取所有值:hgetall key
127.0.0.1:6379> hgetall myhashset
1) "username"
2) "peterjxl"
3) "password"
4) "123456"
2
3
4
5
删除集合里的某个 key:hdel key field
,这里获取一个名字为 key 的集合,然后删除集合里 field 的键值对
127.0.0.1:6379> hdel myhashset username
(integer) 1
2
和 string 类型一样,集合类型也有同时设置多个值的情况,例如:
HMSET key field1 value1 field2 value2
同理,还有 HMGET 获取多个值,HEXISTS 判断值是否存在,HINCRBY 增加指定整数,HLEN 获取字段数量.....等命令
# 列表类型 list
list 是一个简单的字符串列表,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边)。可以看成是一个队列。
列表类型内部是使用双向链表(double linked list)实现的。
添加数据:
lpush mylist value
:将元素加入列表左边,列表里的元素先右移,然后再将新元素放到第一个位置
rpush mylist value
:将元素加入列表右边,可以理解为追加新元素
127.0.0.1:6379> lpush myList a
(integer) 1
127.0.0.1:6379> lpush myList b
(integer) 2
127.0.0.1:6379> rpush myList c
(integer) 3
2
3
4
5
6
7
8
还可以一次添加多个数据:
127.0.0.1:6379> lpush myList2 a b c
(integer) 3
2
这和一个一个添加数据的结果是一样的。
获取数据:lrange key start end
,其中,key 是 list 的名字,start 是开始下标,end 是结束下标,注意以下情况:
- 如果下标是负数,表示从右边开始计算序数,如 "−1" 表示最右边第一个元素,"-2" 表示最右边第二个元素....
- 如果 start 的索引位置比 stop 的索引位置靠后,则会返回空列表。
- 如果 stop 大于实际的索引范围,则会返回到列表最右边的元素。
例如 lrange list1 0 3
表示获取 0 到 3 的数据,不包括 3;lrange myList2 0 -1
表示获取列表中的所有元素:
127.0.0.1:6379> lrange myList 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> lrange myList2 0 -1
1) "c"
2) "b"
3) "a"
2
3
4
5
6
7
8
9
删除数据:
lpop key
: 删除列表最左边的元素,并将元素返回rpop key
: 删除列表最右边的元素,并将元素返回
127.0.0.1:6379> lpop myList
"b"
127.0.0.1:6379> rpop myList
"c"
2
3
4
5
获取 list 长度:llen key
127.0.0.1:6379> llen myList
(integer) 1
2
删除列表中指定的值
LREM key count value
LREM 命令会删除列表中前 count 个值为 value 的元素,返回值是实际删除的元素个数。根据 count 值的不同,LREM 命令的执行方式会略有差异。
(1)当 count > 0 时 LREM 命令会从列表左边开始删除前 count 个值为 value 的元素。
(2)当 count < 0 时 LREM 命令会从列表右边开始删除前 |count| 个值为 value 的元素。
(3)当 count = 0 是 LREM 命令会删除所有值为 value 的元素。例如:
更多语法可以参考文档:Redis 列表(List)_redis 教程 (opens new window)
# 集合类型 set
集合类型不允许重复元素。
存储:sadd key value
127.0.0.1:6379> sadd myset a
(integer) 1
127.0.0.1:6379> sadd myset a
(integer) 0
2
3
4
5
获取:smembers key
获取 set 集合中所有元素,注意顺序是不一致的
127.0.0.1:6379> sadd myset b
(integer) 1
127.0.0.1:6379> sadd myset c
(integer) 1
127.0.0.1:6379> smembers myset
1) "c"
2) "b"
3) "a"
2
3
4
5
6
7
8
9
10
删除:srem key value
删除 set 集合中的某个元素
127.0.0.1:6379> srem myset a
(integer) 1
127.0.0.1:6379> smembers myset
1) "c"
2) "b"
2
3
4
5
6
除此之外,集合类型还支持集合运算,例如并集,交集等。更多语法可参考文档:Redis 集合(Set)_redis 教程 (opens new window)
# 有序集合类型 sortedset
sortedset 不允许重复元素,且元素有顺序。每个元素都会关联一个 double 类型的分数,Redis 正是通过分数来为集合中的成员进行从小到大的排序。所以我们存储数据时还要加上一个分数(分数可以看成是优先级,值小的排前面)
存储:zadd key score value
,重复添加则会覆盖之前的数据
127.0.0.1:6379> zadd mysort 60 zhangsan
(integer) 1
127.0.0.1:6379> zadd mysort 50 lisi
(integer) 1
127.0.0.1:6379> zadd mysort 80 wangwu
(integer) 1
2
3
4
5
6
7
8
获取:zrange key start end [withscores]
127.0.0.1:6379> zrange mysort 0 -1
1) "lisi"
2) "zhangsan"
3) "wangwu"
2
3
4
withscores 表示同时显示分数:
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "zhangsan"
2) "60"
3) "wangwu"
4) "80"
5) "lisi"
6) "500"
2
3
4
5
6
7
删除:zrem key value
127.0.0.1:6379> zrem mysort lisi
(integer) 1
2
除此之外,还支持排序,根据分数范围查询 key 等命令,删除指定范围分数的 key,更多语法可参考:Redis 有序集合(sorted set)_redis 教程 (opens new window)
# 通用命令
keys *
: 查询所有的键,可以写正则表达式
127.0.0.1:6379> keys *
1) "mysort"
2) "myList"
3) "myset"
4) "username"
5) "mywebsite"
6) "visitors"
7) "myhashset"
127.0.0.1:6379> keys my*
1) "mysort"
2) "myList"
3) "myset"
4) "mywebsite"
5) "myhashset"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pattern 支持 glob 风格通配符格式:
符号 | 含义 |
---|---|
? | 匹配一个字符 |
* | 匹配任意个字符(含 0 个) |
[] | 匹配括号间的任意字符,可以用“-” 符号表示一个范围,入 a [b-d] 可以匹配 ab,ac 和 ad |
\x | 匹配字符 x,用于转义符号,例如匹配“?”就需要使用? |
KEYS 命令需要遍历 Redis 中的所有键,当键的数量较多时会影响性能,不建议在生产环境中使用。如果想要查看当前 Redis 中含有键的数量,可以通过 DBSIZE 命令(后续会讲)
type key
: 获取键对应的 value 的类型
127.0.0.1:6379> type mywebsite
string
127.0.0.1:6379> type mySet
set
2
3
4
5
返回值可能是 string(字符串类型)、hash(散列类型)、list(列表类型)、set(集合类型)、zset(有序集合类型)
del key
:删除指定的 key,可以删除多个键,返回值是删除的键的个数。
127.0.0.1:6379> del mysort
(integer) 1
127.0.0.1:6379> del username password
(integer) 2
2
3
4
5
DEL 命令的参数不支持通配符,但我们可以结合 Linux 的管道和 xargs 命令自己实现删除所有符合规则的键,比如要删除所有以“user:”开头的键,就可以执行 redis-cli KEYS "user:*" | xargs redis-cli DEL
另外由于 DEL 命令支持多个键作为参数,所以还可以执行如下命令来达到同样的效果,但是性能更好。
redis-cli DEL `redis-cli KEYS "user:*"`
EXISTS
可以用来判断一个键是否存在:如果键存在则返回整数类型 1,否则返回 0。例如:
EXISTS key
FLUSHALL 命令,用来清空所有数据,慎用
# 总结
不同数据类型,其存取命令的前缀也是不同的,总结如下:
- 存取 String 类型,直接使用 get,set 命令,两个命令前面没有前缀;
- 哈希类型的数据,有个前缀命令 H,例如 hget,hset
- 列表类型的数据,有个前缀 L,例如 lpush,lrange
- 集合类型的命令,有个前缀 S,例如 sadd
- 有序集合的命令,前缀 Z,例如 zadd
注意:
- Redis 的集合类型不支持数据类型嵌套。比如集合类型的每个元素都只能是字符串,不能是另一个集合或散列表等。
- 如果参数包含空格,在 redis-cli 中输入需要双引号以示区分。
Redis 的语法比起 MySQL 还是很简单的,例如获取一个值只需要一个 get 命令,不像关系型数据库,需要写一长串的 SQL。
Redis 有上百个命令,但常用的也就那几个,更多语法,请参考 官网文档 (opens new window),读者也可以在 cli 中使用 help + 命令
来查看某个命令的用法,例如:
127.0.0.1:6379> help set
SET key value [EX seconds] [PX milliseconds] [NX|XX]
summary: Set the string value of a key
since: 1.0.0
group: string
2
3
4
5
6
为了友好的使用,Redis 还将所有命令都进行了分组,同时使用 help + @ + 组名
进行查看每个组中所有命令,以下是所有分组信息:
generic #一般命令组,对大多数类型适用
string #字符串类型命令组,使用所有字符串类型
list #列表类型命令组
set #集合类型命令组
sorted_set #有序集合命令组
hash #hash操作命令组
pubsub #发布命令组
transactions #事务操作命令组
connection #连接相关命令组
server #服务器相关命令组
scripting #lua 脚本命令组
hyperloglog #hyperloglog类型命令组,redis在 2.8.9 版本添加了 HyperLogLog 结构
cluster #集群相关命令组
geo #经纬度相关命令组,适用于3.2.0以后的版本
2
3
4
5
6
7
8
9
10
11
12
13
14
示例:查看事务操作所有命令
127.0.0.1:6379> help @transactions
DISCARD -
summary: Discard all commands issued after MULTI
since: 2.0.0
EXEC -
summary: Execute all commands issued after MULTI
since: 1.2.0
MULTI -
summary: Mark the start of a transaction block
since: 1.2.0
UNWATCH -
summary: Forget about all watched keys
since: 2.2.0
WATCH key [key ...]
summary: Watch the given keys to determine execution of the MULTI/EXEC block
since: 2.2.0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21