什么是Redis

为什么要用Nosql

​ 在请求量小的情况下,使用mysql不会有任何问题,但是一旦同时有成千上万个请求同时来访问系统时,就会出现卡顿甚至系统崩溃的情况。最典型的例子就是早期的12306购票网站,一旦到了购票高峰期,12306肯定崩溃。造成这个原因的罪魁祸首就是关系型数据库

​ 关系型数据库存在两个问题:

  1. 性能:磁盘IO性能低下
  2. 扩展性:数据关系复杂,扩展性差,不利于大规模集群

为了解决这两个问题,非关系类型数据库出现了,非关系类型数据库有两个特点:

  1. 内存存储 :解决磁盘IO性能低的问题
  2. 不存储关系,只存储数据 : 解决数据关系复杂的问题

​ NoSQL的常见产品:redis、mongdb

redis介绍

​ Redis-Remote Dictionary Server。是用C语言开发的一个开源的高性能键值对(key-value)数据库,是一种内存数据库。支持内存运行并支持持久化的NoSQL数据库,有如下几个特征:

  • 数据间没有必然的联系
  • 内部采用单线程机制工作
  • 性能高,支持每秒十几万次的读写操作
  • 多数据类型支持:字符串类型(string)、列表类型(list)、散列类型(hash)、集合类型(set)、有序集合类型(sorted_set)
  • 持久化支持

redis的应用场合

  • 缓存处理
  • 任务队列(秒杀,抢购,抢票等)
  • 应用排行榜,热点
  • 访问统计
  • 数据过期处理
  • 分布式集群中的session共享

Redis基本操作

数据库的选择

redis中一共有16个数据库,序号0~15,默认数据库为0。可以通过select命令选择数据库

1
2
3
4
5
redis-cli

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

String类型

添加/修改数据

1
2
127.0.0.1:6379[1]> set user_info zhangshan
OK

获取数据(若为空,则返回nil)

1
2
3
4
127.0.0.1:6379[1]> get user_info
"zhangshan"
127.0.0.1:6379[1]> get user
(nil)

删除数据(返回1代表成功,0代表失败)

1
2
127.0.0.1:6379[1]> del user_info
(integer) 1

添加/修改多个数据

1
2
127.0.0.1:6379[1]> mset user_name zhangshan user_sex male
OK

获取多个数据

1
2
3
127.0.0.1:6379[1]> mget user_name user_sex
1) "zhangshan"
2) "male"

获取字符串长度

1
2
3
4
127.0.0.1:6379[1]> STRLEN user_name
(integer) 9
127.0.0.1:6379[1]> STRLEN user_sex
(integer) 4

追加信息到原始信息之后

1
2
3
4
127.0.0.1:6379[1]> append user_name lisi
(integer) 13
127.0.0.1:6379[1]> get user_name
"zhangshanlisi"

替换指定偏移量后的内容

1
2
3
4
5
6
127.0.0.1:6379[1]> get user_name
"zhangshanlisi"
127.0.0.1:6379[1]> SETRANGE user_name 9 123
(integer) 13
127.0.0.1:6379[1]> get user_name
"zhangshan123i"

多操作指令看上去似乎是对单操作指令的简单相加,但其实不然。一条指令执行有三个地方需要耗时:发送指令、处理指令、返回结果。当使用多操作指令的时候,发送和返回都只执行一次,相比较多次只从单操作指令减少了大笔时间。

设置数值增加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
127.0.0.1:6379[1]> INCR user_name
(error) ERR value is not an integer or out of range

127.0.0.1:6379[1]> set user_num 1
OK
127.0.0.1:6379[1]> INCR user_num
(integer) 2
127.0.0.1:6379[1]> get user_num
"2"
127.0.0.1:6379[1]> INCRBY user_num 100
(integer) 101
127.0.0.1:6379[1]> get user_num
"101"
127.0.0.1:6379[1]> INCRBYFLOAT user_num 1.1415926
"3.14159260000000007"
127.0.0.1:6379[1]> get user_num
"3.14159260000000007"

设置数值减少

1
2
3
4
5
6
7
8
127.0.0.1:6379[1]> DECR user_num
(integer) 1
127.0.0.1:6379[1]> get user_num
"1"
127.0.0.1:6379[1]> DECRBY user_num 99
(integer) 2
127.0.0.1:6379[1]> get user_num
"2"

设置数据具有制定的生命周期(验证码、秒杀、注册等有时间限制的场景)

1
2
3
4
5
6
7
8
9
10
11
12
13
127.0.0.1:6379[1]> SETEX user_num 10 99 # 10s后过期
OK
127.0.0.1:6379[1]> get user_num
"99"
127.0.0.1:6379[1]> get user_num # 10s后获取
(nil)

127.0.0.1:6379[1]> PSETEX user_num 5000 199 # Psetex 命令以毫秒为单位设置 key 的生存时间。
OK
127.0.0.1:6379[1]> get user_num
"199"
127.0.0.1:6379[1]> get user_num
(nil)

查看生命周期剩余时长(大于0表示所剩时长,-1表示永久,-2表示生命周期已结束)

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379[1]> SETEX money 20 100
OK

127.0.0.1:6379[1]> PTTL money # pttl查看的是毫秒
(integer) 15349
127.0.0.1:6379[1]> TTL money # ttl查看的是秒
(integer) 10
127.0.0.1:6379[1]> TTL money
(integer) 8

127.0.0.1:6379[1]> TTL user_name # 未设置过期时间
(integer) -1

Redis 字符串(String) 命令

命令 描述
Redis Setnx 命令 只有在 key 不存在时设置 key 的值。
Redis Getrange 命令 返回 key 中字符串值的子字符
Redis Mset 命令 同时设置一个或多个 key-value 对。
Redis Setex 命令 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
Redis SET 命令 设置指定 key 的值
Redis Get 命令 获取指定 key 的值。
Redis Getbit 命令 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
Redis Setbit 命令 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
Redis Decr 命令 将 key 中储存的数字值减一。
Redis Decrby 命令 key 所储存的值减去给定的减量值(decrement) 。
Redis Strlen 命令 返回 key 所储存的字符串值的长度。
Redis Msetnx 命令 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
Redis Incrby 命令 将 key 所储存的值加上给定的增量值(increment) 。
Redis Incrbyfloat 命令 将 key 所储存的值加上给定的浮点增量值(increment) 。
Redis Setrange 命令 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
Redis Psetex 命令 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
Redis Append 命令 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。
Redis Getset 命令 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
Redis Mget 命令 获取所有(一个或多个)给定 key 的值。
Redis Incr 命令 将 key 中储存的数字值增一。

Hash类型

Hash(哈希散列)是 Redis 基本数据类型,值value 中存储的是 hash 表。Hash 特别适合用于存储对象。

添加/修改数据

1
2
127.0.0.1:6379[1]> hset list name zs,li,ww age 18
(integer) 2

获取数据

1
2
3
4
5
6
7
127.0.0.1:6379[1]> HGET list name
"zs,li,ww"
127.0.0.1:6379[1]> HGETALL list
1) "name"
2) "zs,li,ww"
3) "age"
4) "18"

删除数据

1
2
3
4
5
127.0.0.1:6379[1]> HDEL list age
(integer) 1
127.0.0.1:6379[1]> HGETALL list
1) "name"
2) "zs,li,ww"

获取哈希表中字段的数量

1
2
127.0.0.1:6379[1]> HLEN list
(integer) 1

获取哈希表中是否存在指定的字段(0否1是)

1
2
127.0.0.1:6379[1]> HEXISTS list age
(integer) 0

设置指定字段的数值增加

1
2
3
4
127.0.0.1:6379[1]> HINCRBY list age 10
(integer) 20
127.0.0.1:6379[1]> HINCRBYFLOAT list age .5
"20.5"

Redis 哈希(Hash) 命令

命令 说明
HDEL 用于删除哈希表中一个或多个字段
HEXISTS 用于判断哈希表中字段是否存在
HGET 获取存储在哈希表中指定字段的值
HGETALL 获取在哈希表中指定 key 的所有字段和值
HINCRBY 为存储在 key 中的哈希表指定字段做整数增量运算
HKEYS 获取存储在 key 中的哈希表的所有字段
HLEN 获取存储在 key 中的哈希表的字段数量
HSET 用于设置存储在 key 中的哈希表字段的值
HVALS 用于获取哈希表中的所有值

需要注意的是,hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。每个hash可以存储2^32-1个键值对。

List类型

list类型数据用于存储多个数据,并对数据进入存储空间的顺序进行区分,值value 中存储的是列表。list类型的数据可以保存多个数据,底层使用双向链表存储结构实现。

既然是双向链表的方式实现,那么就可以从左右两边添加和修改数据,在头和尾增和删除数据的效率较高,中间比较低,按照插入顺序进行排序,数据可以重复。应用场景:点赞、最新消息。下面是具体操作:

添加/修改数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
127.0.0.1:6379[1]> LPUSH list 1 2 3 4 # 将一个或多个值插入到列表头部
(integer) 4
127.0.0.1:6379[1]> LRANGE list 0 4
1) "4"
2) "3"
3) "2"
4) "1"
127.0.0.1:6379[1]> RPUSH list 1 2 3 4 # 在列表中添加一个或多个值
(integer) 8
127.0.0.1:6379[1]> LRANGE list 0 8
1) "4"
2) "3"
3) "2"
4) "1"
5) "1"
6) "2"
7) "3"
8) "4

获取数据

1
2
3
lrange key start stop (stop=-1时表示最后一个元素)
lindex key index
llen key

获取并删除数据

1
2
lpop key # 移出并获取列表的第一个元素
rpop key # 移除并获取列表最后一个元素

移除数据指定数据

从列表 key 中删除前 count 个值等于 element 的元素。 这个 count 参数通过下面几种方式影响这个操作:

  • count > 0: 从头到尾删除值为 value 的元素。
  • count < 0: 从尾到头删除值为 value 的元素。
  • count = 0: 移除所有值为 value 的元素。

比如, LREM list -2 “hello” 会从列表key中删除最后两个出现的 “hello”。

1
2
3
4
5
6
7
8
9
10
11
12
127.0.0.1:6379[1]> LRANGE list 0 -1
1) "1"
2) "1"
3) "2"
4) "3"
5) "4"
127.0.0.1:6379[1]> LREM list 2 1
(integer) 2
127.0.0.1:6379[1]> LRANGE list 0 -1
1) "2"
2) "3"
3) "4"

需要注意的是,不存在key会被当作空list处理,所以当 key 不存在的时候,这个命令会返回 0。

返回值

整数: 删除元素个数。

Redis List 命令

命令 描述
BLPOP 移出并获取列表的第一个元素
BRPOP 移出并获取列表的最后一个元素
BRPOPLPUSH 从列表中弹出一个值,并将该值插入到另外一个列表中并返回它
LINDEX 通过索引获取列表中的元素
LINSERT 在列表的元素前或者后插入元素
LLEN 获取列表长度
LPOP 移出并获取列表的第一个元素
LPUSH 将一个或多个值插入到列表头部
LPUSHX 将一个值插入到已存在的列表头部
LRANGE 获取列表指定范围内的元素
LREM 移除列表元素
LSET 通过索引设置列表元素的值
LTRIM 对一个列表进行修剪(trim)
RPOP 移除并获取列表最后一个元素
RPOPLPUSH 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
RPUSH 在列表中添加一个或多个值
RPUSHX 为已存在的列表添加值

Set类型

set类型与hash存储结构完全相同,不同点在于,set仅存储键,不存储值,并且值不允许为空,元素不重复

set类型可以存储大量数据,在查询方面提供更高的效率。

应用场合:利用唯一性,统计地区新生儿状况,统计驾驶证

添加/修改数据

1
2
3
4
5
6
127.0.0.1:6379[1]> SADD arr 1 2 3 4
(integer) 4
127.0.0.1:6379[1]> SADD arr 1 # 元素不重复
(integer) 0
127.0.0.1:6379[1]> SADD arr 5
(integer) 1

获取全部数据

1
2
3
4
5
6
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"

删除数据

1
2
3
4
5
6
127.0.0.1:6379[1]> SREM arr 5 4
(integer) 2
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"

获取集合的成员数

1
2
3
4
5
6
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
127.0.0.1:6379[1]> SCARD arr
(integer) 3

判断集合中是否包含指定数据(0否1是)

1
2
3
4
5
6
7
8
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
127.0.0.1:6379[1]> SISMEMBER arr 5
(integer) 0
127.0.0.1:6379[1]> SISMEMBER arr 1
(integer) 1

随机获取集合中指定数量的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
127.0.0.1:6379[1]> SRANDMEMBER arr 3
1) "8"
2) "5"
3) "1"
127.0.0.1:6379[1]> SRANDMEMBER arr 3
1) "5"
2) "6"
3) "9"

移除并返回集合中的n个随机元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
127.0.0.1:6379[1]> SPOP arr 2
1) "3"
2) "4"
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "5"
4) "6"
5) "7"
6) "8"
7) "9"

返回给定所有集合的交集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "5"
4) "6"
5) "7"
6) "8"
7) "9"
127.0.0.1:6379[1]> SMEMBERS arr1
1) "1"
2) "2"
3) "11"
4) "12"
127.0.0.1:6379[1]> SINTER arr arr1
1) "1"
2) "2"

返回给定所有集合的差集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "5"
4) "6"
5) "7"
6) "8"
7) "9"
127.0.0.1:6379[1]> SMEMBERS arr1
1) "1"
2) "2"
3) "11"
4) "12"
127.0.0.1:6379[1]> SDIFF arr arr1
1) "5"
2) "6"
3) "7"
4) "8"
5) "9"

返回所有给定集合的并集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "5"
4) "6"
5) "7"
6) "8"
7) "9"
127.0.0.1:6379[1]> SMEMBERS arr1
1) "1"
2) "2"
3) "11"
4) "12"
127.0.0.1:6379[1]> SUNION arr arr1
1) "1"
2) "2"
3) "5"
4) "6"
5) "7"
6) "8"
7) "9"
8) "11"
9) "12"

返回给定所有集合的交集、并集、差集并存储在 destination 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
127.0.0.1:6379[1]> SMEMBERS arr1
1) "1"
2) "2"
3) "12"
4) "13"
127.0.0.1:6379[1]> SDIFFSTORE new_arr arr arr1 # 差集
(integer) 6
127.0.0.1:6379[1]> SMEMBERS new_arr
1) "3"
2) "4"
3) "5"
4) "6"
5) "7"
6) "8"

127.0.0.1:6379[1]> SUNIONSTORE new_arr1 arr arr1 # 并集
(integer) 10
127.0.0.1:6379[1]> SMEMBERS new_arr1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "12"
10) "13"

127.0.0.1:6379[1]> SINTERSTORE new_arr2 arr arr1 # 交集
(integer) 2
127.0.0.1:6379[1]> SMEMBERS new_arr2
1) "1"
2) "2"

将 member 元素从 source 集合移动到 destination 集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
127.0.0.1:6379[1]> SADD num 9
(integer) 1
127.0.0.1:6379[1]> SMOVE arr num 2
(integer) 1
127.0.0.1:6379[1]> SMEMBERS arr
1) "1"
2) "3"
3) "4"
4) "5"
5) "6"
6) "7"
7) "8"
127.0.0.1:6379[1]> SMEMBERS num
1) "2"
2) "9"

Redis Set命令

命令 描述
SADD 向集合添加一个或多个成员
SCARD 获取集合的成员数
SDIFF 返回给定所有集合的差集
SDIFFSTORE 返回给定所有集合的差集并存储在 destination 中
SINTER 返回给定所有集合的交集
SINTERSTORE 返回给定所有集合的交集并存储在 destination 中
SISMEMBER 判断 member 元素是否是集合 key 的成员
SMEMBERS 返回集合中的所有成员
SMOVE 将 member 元素从 source 集合移动到 destination 集合
SPOP 移除并返回集合中的一个随机元素
SRANDMEMBER 返回集合中一个或多个随机数
SREM 移除集合中一个或多个成员
SUNION 返回所有给定集合的并集
SUNIONSTORE 所有给定集合的并集存储在 destination 集合中
SSCAN 迭代集合中的元素

Zset类型

每个元素都会有一个权重值,元素会自动按照权重排序,元素不能重复,但是权重可以重复

应用场合:排行榜

待更新…