Redis数据类型有5种:分别是字符串(string)、散列(hash)、列表(list)、集合(set)、有序集合(sort set)。
- 字符串
- 字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据
- 可以用其存储用户的邮箱、JSON 化的对象甚至是一张图片
- 一个字符串类型键允许存储的数据的最大容量是512 MB
- 字符串类型是其他4种数据类型的基础,其他数据类型和字符串类型的差别从某种角度来说只是组织字符串的形式不同
字符串操作命令
- 赋值命令
# 赋值
SET key value
# 取值
GET key
- 赋值命令示例
127.0.0.1:6379> SET username tom
OK
127.0.0.1:6379> GET username
"tom"
127.0.0.1:6379> GET password # 当键不存在时会返回空结果。
(nil)
- 递增数字:字符串类型可以存储任何形式的字符串,当存储的字符串是整数形式时,Redis 提供了一个实用的命令 INCR,其作用是让当前键值递增,并返回递增后的值。
# 当要操作的键不存在时会默认键值为0,所以第一次递增后的结果是1。
127.0.0.1:6379> INCR num
(integer) 1
127.0.0.1:6379> INCR num
(integer) 2
127.0.0.1:6379> GET num
"2"
- 当键值不是整数时Redis会提示错误
127.0.0.1:6379> SET foo bar
OK
127.0.0.1:6379> INCR foo
(error) ERR value is not an integer or out of range
- 增加指定的整数
127.0.0.1:6379> INCRBY num 2
(integer) 4
127.0.0.1:6379> INCRBY num 2
(integer) 6
- 递减数字
127.0.0.1:6379> DECR num
(integer) 5
127.0.0.1:6379> DECRBY num 2
(integer) 3
- 向尾部追加值
127.0.0.1:6379> SET hi Hello
OK
127.0.0.1:6379> APPEND hi " World" # 因为字符串包含空格,需要使用引号
(integer) 11 # 返回值为hi的总长度
127.0.0.1:6379> GET hi
"Hello World"
- 获取字符串长度
127.0.0.1:6379> STRLEN hi
(integer) 11
- 中文字符返回字节数
127.0.0.1:6379> SET name 张三
OK
127.0.0.1:6379> STRLEN name
(integer) 6 # UTF-8编码的中文,由于“张”和“三”两个字的UTF-8编码的长度都是3,所以此例中会返回6。
- 同时获得/设置多个键值
127.0.0.1:6379> MSET username tom password guodong.com
OK
127.0.0.1:6379> MGET username password
1) "tom"
2) "guodong.com"
- 判断字段是否存在
127.0.0.1:6379> EXISTS num
(integer) 1
127.0.0.1:6379> EXISTS number
(integer) 0
- 字段不存在时赋值
127.0.0.1:6379> SETNX number 100
(integer) 1
127.0.0.1:6379> GET number
"100"
- 查看所有的key
127.0.0.1:6379> KEYS *
- 删除字段
127.0.0.1:6379> DEL number
(integer) 1
127.0.0.1:6379> DEL number
(integer) 0
- 查看键的类型
127.0.0.1:6379> TYPE name
string
字符串实践
- Redis 对于键的命名并没有强制的要求,但比较好的实践是用“对象类型:对象ID:对象属性”来命名一个键,如使用键【
user:1:friends
】来存储ID为1的用户的好友列表。 - 例:如果你正在编写一个博客网站,博客的一个常见的功能是统计文章的访问量,我们可以为每篇文章使用一个名为【
post:文章ID:page.view
】的键来记录文章的访问量,每次访问文章的时候使用INCR命令使相应的键值递增。
# 有用户访问文章ID号为42的博文,则将其访问计数加1
127.0.0.1:6379> INCR post:42:page.view
(integer) 1
127.0.0.1:6379> GET post:42:page.view
"1"
127.0.0.1:6379> INCR post:42:page.view
(integer) 2
127.0.0.1:6379> GET post:42:page.view
"2"
- 散列类型
- 散列类型(hash)的键值也是一种字典结构,其存储了字段(field)和字段值的映射
- 字段值只能是字符串
- 散列类型适合存储对象。使用对象类别和 ID 构成键名,使用字段表示对象的属性,而字段值则存储属性值
散列类型操作命令
- 赋值与取值
# 设置单个字段
127.0.0.1:6379> HSET user1 name bob
(integer) 1
127.0.0.1:6379> HSET user1 gender male
(integer) 1
127.0.0.1:6379> HGET user1 name
"bob"
127.0.0.1:6379> HGET user1 gender
"male"
# 设置多个字段
127.0.0.1:6379> HMSET user1 email bob@guodong.com phone 13412345678
OK
127.0.0.1:6379> HMGET user1 email phone
1) "bob@guodong.com"
2) "13412345678"
# 获取所有字段
127.0.0.1:6379> HGETALL user1
1) "name"
2) "bob"
3) "gender"
4) "male"
5) "email"
6) "bob@guodong.com"
7) "phone"
8) "13412345678"
- 判断
# 判断字段是否存在
127.0.0.1:6379> HEXISTS user1 address
(integer) 0
127.0.0.1:6379> HEXISTS user1 name
(integer) 1
# 当字段不存在时赋值
127.0.0.1:6379> HSETNX user1 address beijing
(integer) 1
127.0.0.1:6379> HSETNX user1 address beijing
(integer) 0
- 数字递增
127.0.0.1:6379> HINCRBY user1 age 20
(integer) 20
127.0.0.1:6379> HINCRBY user1 age 1
(integer) 21
- 删除字段
127.0.0.1:6379> HDEL user1 age
(integer) 1
- 只获取字段名
127.0.0.1:6379> HKEYS user1
1) "name"
2) "gender"
3) "email"
4) "phone"
5) "address"
- 只获取值
127.0.0.1:6379> HVALS user1
1) "bob"
2) "male"
3) "bob@guodong.com"
4) "13412345678"
5) "beijing"
- 获得字段数量
127.0.0.1:6379> HLEN user1
(integer) 5
散列类型实践
- 例:将文章ID号为10的文章以散列类型存储在Redis中
127.0.0.1:6379> HSET post:10 title 例解Python
(integer) 1
127.0.0.1:6379> HGETALL post:10
1) "title"
2) "\xe4\xbe\x8b\xe8\xa7\xa3Python"
127.0.0.1:6379> HSET post:10 author Zhang
(integer) 1
127.0.0.1:6379> HMSET post:10 date 2021-05-01 summary 'Python Programming'
OK
127.0.0.1:6379> HGETALL post:10
1) "title"
2) "\xe4\xbe\x8b\xe8\xa7\xa3Python"
3) "author"
4) "Zhang"
5) "date"
6) "2021-05-01"
7) "summary"
8) "Python Programming"
- 列表类型
-
列表类型(list)可以存储一个有序的字符串列表
-
常用的操作是向列表两端添加元素,或者获得列表的某一个片段
-
列表类型内部是使用双向链表(double linked list)实现的,获取越接近两端的元素速度就越快
-
使用链表的代价是通过索引访问元素比较慢
-
这种特性使列表类型能非常快速地完成关系数据库难以应付的场景:如社交网站的新鲜事,我们关心的只是最新的内容,使用列表类型存储,即使新鲜事的总数达到几千万个,获取其中最新的100条数据也是极快的
列表类型操作命令
- LPUSH命令用来向列表左边增加元素,返回值表示增加元素后列表的长度
127.0.0.1:6379> LPUSH numbers 1
(integer) 1
127.0.0.1:6379> LPUSH numbers 2 3
(integer) 3
- 取出列表所有元素
127.0.0.1:6379> LRANGE numbers 0 -1 # 起始下标为0,结束下标为-1
1) "3"
2) "2"
3) "1"
- RPUSH命令用来向列表右边增加元素,返回值表示增加元素后列表的长度
127.0.0.1:6379> RPUSH numbers 0 -1
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "3"
2) "2"
3) "1"
4) "0"
5) "-1"
- 从列表两端弹出元素
127.0.0.1:6379> LPOP numbers
"3"
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
4) "-1"
127.0.0.1:6379> RPOP numbers
"-1"
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
- 获取列表中元素的个数
127.0.0.1:6379> LLEN numbers
(integer) 3
- 删除列表中指定的值
# 语法
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的元素。
127.0.0.1:6379> LPUSH numbers 0 1 2 0 1 2 0 1 2
(integer) 12
127.0.0.1:6379> RPUSH numbers 2 1 0 2 1 0 2 1 0
(integer) 21
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "1"
3) "0"
4) "2"
5) "1"
6) "0"
7) "2"
8) "1"
9) "0"
10) "2"
11) "1"
12) "0"
13) "2"
14) "1"
15) "0"
16) "2"
17) "1"
18) "0"
19) "2"
20) "1"
21) "0"
#
127.0.0.1:6379> LREM numbers 2 1 # 从左侧开始删除2个1
(integer) 2
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "0"
3) "2"
4) "0"
5) "2"
6) "1"
7) "0"
8) "2"
9) "1"
10) "0"
11) "2"
12) "1"
13) "0"
14) "2"
15) "1"
16) "0"
17) "2"
18) "1"
19) "0"
# 从右侧开始删除2个0
127.0.0.1:6379> LREM numbers -2 0
(integer) 2
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "0"
3) "2"
4) "0"
5) "2"
6) "1"
7) "0"
8) "2"
9) "1"
10) "0"
11) "2"
12) "1"
13) "0"
14) "2"
15) "1"
16) "2"
17) "1"
# 删除所有的0
127.0.0.1:6379> LREM numbers 0 0
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "2"
3) "2"
4) "1"
5) "2"
6) "1"
7) "2"
8) "1"
9) "2"
10) "1"
11) "2"
12) "1"
- 获得/设置指定索引的元素值
# 获取numbers列表中下标为0的值
127.0.0.1:6379> LINDEX numbers 0
"2"
# 设置下标为1的值为10
127.0.0.1:6379> LSET numbers 1 10
OK
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "10"
3) "2"
4) "1"
5) "2"
6) "1"
7) "2"
8) "1"
9) "2"
10) "1"
11) "2"
12) "1"
- 删除指定范围之外的所有元素
127.0.0.1:6379> LTRIM numbers 0 2
OK
127.0.0.1:6379> LRANGE numbers 0 -1
1) "2"
2) "10"
3) "2"
- 插入元素
# 在2的前面插入20
127.0.0.1:6379> LINSERT numbers BEFORE 2 20
(integer) 4
127.0.0.1:6379> LRANGE numbers 0 -1
1) "20"
2) "2"
3) "10"
4) "2"
# 在2的后面挺入30
127.0.0.1:6379> LINSERT numbers AFTER 2 30
(integer) 5
127.0.0.1:6379> LRANGE numbers 0 -1
1) "20"
2) "2"
3) "30"
4) "10"
5) "2"
列表类型实践
- 例:记录最新的10篇博文
127.0.0.1:6379> LPUSH posts:list 11 12 13
(integer) 3
127.0.0.1:6379> LRANGE posts:list 0 -1
1) "13"
2) "12"
3) "11"
- 集合类型
-
集合中的每个元素都是不同的,且没有顺序
-
增加/删除元素
127.0.0.1:6379> SADD letters a b c
(integer) 3
127.0.0.1:6379> SADD letters b c d
(integer) 1
127.0.0.1:6379> SMEMBERS letters
1) "d"
2) "b"
3) "a"
4) "c"
127.0.0.1:6379> SREM letters a c
(integer) 2
127.0.0.1:6379> SMEMBERS letters
1) "d"
2) "b"
- 判断元素是否在集合中
127.0.0.1:6379> SISMEMBER letters a
(integer) 0
127.0.0.1:6379> SISMEMBER letters b
(integer) 1
- 集合运算
127.0.0.1:6379> SADD s1 a b c
(integer) 3
127.0.0.1:6379> SADD s2 b c d
(integer) 3
127.0.0.1:6379> SINTER s1 s2
1) "b"
2) "c"
127.0.0.1:6379> SUNION s1 s2
1) "a"
2) "c"
3) "b"
4) "d"
127.0.0.1:6379> SDIFF s1 s2
1) "a"
- 获得集合中元素个数
127.0.0.1:6379> SCARD letters
(integer) 2
- 随机获得集合中的元素
# 在集合s1中随机取出两个不同元素。
127.0.0.1:6379> SRANDMEMBER s1 2
1) "b"
2) "c"
# 在集合s1中随机取出两个有可能相同元素。
127.0.0.1:6379> SRANDMEMBER s1 -2
1) "c"
2) "c"
127.0.0.1:6379> SRANDMEMBER s1 -2
1) "a"
2) "b"
- 集合中随机弹出一个元素
127.0.0.1:6379> SPOP s1
"a"
127.0.0.1:6379> SMEMBERS s1
1) "b"
2) "c"
集合实践
- 例:为文章号为10的博客文章添加标签
127.0.0.1:6379> SADD post:10:tags python redis nginx
(integer) 3
127.0.0.1:6379> SMEMBERS post:10:tags
1) "python"
2) "nginx"
3) "redis"
- 有序集合类型
-
在集合类型的基础上有序集合类型为集合中的每个元素都关联了一个分数
-
这使得我们不仅可以完成插入、删除和判断元素是否存在等集合类型支持的操作,还能够获得分数最高(或最低)的前N个元素、获得指定分数范围内的元素等与分数有关的操作
-
虽然集合中每个元素都是不同的,但是它们的分数却可以相同。
-
有序集合类型在某些方面和列表类型有些相似
- 二者都是有序的
- 二者都可以获得某一范围的元素
-
有序集合类型和列表也有着很大的区别,这使得它们的应用场景也是不同的
- 列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,所以它更加适合实现如“新鲜事”或“日志”这样很少访问中间元素的应用
- 有序集合类型是使用散列表和跳跃表(Skip list)实现的,所以即使读取位于中间部分的数据速度也很快
- 列表中不能简单地调整某个元素的位置,但是有序集合可以(通过更改这个元素的分数)
- 有序集合要比列表类型更耗费内存
有序集合类型操作
- ZADD 命令用来向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。ZADD命令的返回值是新加入到集合中的元素个数
127.0.0.1:6379> ZADD scores 88 tom 90 jerry 75 bob 92 alice
(integer) 4
127.0.0.1:6379> ZRANGE scores 0 -1
1) "bob"
2) "tom"
3) "jerry"
4) "alice"
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "bob"
2) "75"
3) "tom"
4) "88"
5) "jerry"
6) "90"
7) "alice"
8) "92"
127.0.0.1:6379> ZADD scores 85 jerry
(integer) 0
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "bob"
2) "75"
3) "jerry"
4) "85"
5) "tom"
6) "88"
7) "alice"
8) "92"
- 获得元素的分数
127.0.0.1:6379> ZSCORE scores tom
"88"
- 获得指定分数范围的元素
127.0.0.1:6379> ZRANGEBYSCORE scores 80 90 WITHSCORES
1) "jerry"
2) "85"
3) "tom"
4) "88"
- 增加某个元素的分数
127.0.0.1:6379> ZINCRBY scores 3 bob
"78"
127.0.0.1:6379> ZSCORE scores bob
"78"
- 获得集合中元素的数量
127.0.0.1:6379> ZCARD scores
(integer) 4
- 获得指定分数范围内的元素个数
127.0.0.1:6379> ZCOUNT scores 80 90
(integer) 2
- 删除元素
127.0.0.1:6379> ZREM scores bob
(integer) 1
- 获得元素的排名
127.0.0.1:6379> ZRANK scores tom # 获取tom的排名
(integer) 1 # 升序排列,从0开始计数
127.0.0.1:6379> ZREVRANK scores alice # 获取alice的排名
(integer) 0 # 降序排列,从0开始计数
有序集合类型实践
- 例:将博客文章按照点击量排序
127.0.0.1:6379> ZADD posts:page.view 0 post:10:page.view
(integer) 1
127.0.0.1:6379> ZINCRBY posts:page.view 1 post:10:page.view
"1"
127.0.0.1:6379> ZRANGE posts:page.view 0 -1 WITHSCORES
1) "post:10:page.view"
2) "1"
网友评论