【Redis】入门与应用

文章目录

1. Redis的技术全景

Redis一个开源的基于键值对(Key-Value)NoSQL数据库。使用ANSI C语言编写、支持网络、基于内存但支持持久化。性能优秀,并提供多种语言的API。

2. Redis的启动

Redis编译完成后,会生成几个可执行文件,这些文件各有各的作用。

在这里插入图片描述
一般来说redis-server和redis-cli这些平时用得最多。

Redis有三种方法启动Redis:默认配置、带参数启动、配置文件启动。

  • 默认配置
./redis-server
  • 带参数启动
./redis-server --port 6389
  • 配置文件启动
./redis-server ../conf/redis.conf

3. Redis的停止

Redis提供了shutdown命令来停止Redis服务,例如我们目前已经启动的Redis服务,可以执行:

./redis-cli -p 6379 shutdown

redis服务端将会显示:
在这里插入图片描述
除了可以通过shutdown命令关闭Redis服务以外,还可以通过kill进程号的方式关闭掉Redis,但是强烈不建议使用kill -9强制杀死Redis服务,不但不会做持久化操作,还会造成缓冲区等资源不能被优雅关闭,极端情况会造成AOF和复制丢失数据的情况。如果是集群,还容易丢失数据。

同样还可以在命令行中执行shutdown指令:
在这里插入图片描述
shutdown还有一个参数,代表是否在关闭Redis前,生成持久化文件,如果是save,生成持久化文件,如果是nosave则不生成持久化文件

4. Redis的常用全局命令

4.1 keys 命令

查看所有键(支持通配符):

keys *
keys L*

在这里插入图片描述

但是这个命令请慎用,因为keys命令要把所有的key-value对全部拉出去,如果生产环境的键值对特别多的话,会对Redis的性能有很大的影响,推荐使用dbsize。

keys命令会遍历所有键,所以它的时间复杂度是o(n),当Redis保存了大量键时线上环境禁止使用keys命令。

4.2 dbsize 命令

dbsize命令会返回当前数据库中键的总数。
在这里插入图片描述

dbsize命令在计算键总数时不会遍历所有键,而是直接获取 Redis内置的键总数变量,所以dbsize命令的时间复杂度是O(1)。

4.3 exists 命令

检查键是否存在,存在返回1,不存在返回0。】

4.4 del 命令

删除键,无论值是什么数据结构类型,del命令都可以将其删除。返回删除键个数,删除不存在键返回0。同时del命令可以支持删除多个键。

4.5 expire 命令

设置 key 的过期时间,key 过期后将不再可用。单位以秒计。

ttl命令会返回键的剩余过期时间,它有3种返回值:

大于等于0的整数:键剩余的过期时间。

-1:键没设置过期时间。

-2:键不存在

4.6 expireat 命令

用于以 UNIX 时间戳(unix timestamp)格式设置 key 的过期时间,可以指定几时几分几秒过期。

4.7 pexpire 命令

设置 key 的过期时间,key 过期后将不再可用。单位以毫秒计。

4.8 pexpireat 命令

设置 key 的过期时间,key 过期后将不再可用。单位以毫秒(timestamp类型)计。

注意:

  • 如果expire key 的键不存在,返回结果为0。
  • 如果过期时间为负值,键会立即被删除,犹如使用del命令一样。
  • persist命令可以将键的过期时间清除。
  • 对于字符串类型键,执行set命令会去掉过期时间,这个问题很容易在开发中被忽视。
  • Redis不支持二级数据结构(例如哈希、列表)内部元素的过期功能,不能对二级数据结构做过期时间设置,说白了不能设置value过期时间。

4.9 type 命令

返回键的数据结构类型。

4.10 randomkey 命令

随机返回一个键。

4.11 rename 命令

命令用于修改 key 的名称 。

但是要注意,如果在rename之前,新键已经存在,那么它的值也将被覆盖。

为了防止被强行rename,Redis提供了renamenx命令,确保只有newKey不存在时候才被覆盖。
在这里插入图片描述
从上面我们可以看出,由于重命名键期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性。

4.12 key的命名推荐

Redis没有命令空间,而且也没有对键名有强制要求。但设计合理的键名,有利于防止键冲突和项目的可维护性,比较推荐的方式是使用“业务名:对象名: id : [属性]”作为键名(也可以不是分号)。

5. Redis常用的数据结构

Redis提供了一些数据结构供我们往Redis中存取数据,最常用的的有5种,字符串(String)、哈希(Hash)、列表(list)、集合(set)、有序集合(ZSET)。
在这里插入图片描述

5.1 字符串(String)

字符串类型是Redis最基础的数据结构。首先键都是字符串类型,而且其他几种数据结构都是在字符串类型基础上构建的,所以字符串类型能为其他四种数据结构的学习奠定基础。字符串类型的值实际可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。

(虽然Redis是C写的,C里面有字符串<本质使用char数组来实现>,但是处于种种考虑,Redis还是自己实现了字符串类型)

5.1.1 操作命令

5.1.1.1 set 设置值
redis 127.0.0.1:6379> SET KEY_NAME VALUE

set命令有几个选项:

ex seconds: 为键设置秒级过期时间。

px milliseconds: 为键设置毫秒级过期时间。

nx: 键必须不存在,才可以设置成功,用于添加(分布式锁常用)。

xx: 与nx相反,键必须存在,才可以设置成功,用于更新。

5.1.1.2 get 获取值

Redis Get 命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。如果key 储存的值不是字符串类型,返回一个错误。

redis 127.0.0.1:6379> GET KEY_NAME
5.1.1.3 mset 批量设置值

用于同时设置一个或多个 key-value 对。

redis 127.0.0.1:6379> MSET key1 value1 key2 value2 .. keyN valueN 
5.1.1.4 mget 批量获取值

返回所有(一个或多个)给定 key 的值。 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil 。

redis 127.0.0.1:6379> MGET KEY1 KEY2 .. KEYN
5.1.1.5 Incr 数字运算

将 key 中储存的数字值增一。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

除了incr命令,Redis提供了decr(自减)、 incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数),具体效果自行尝试。

5.1.1.6 append追加指令

命令用于为指定的 key 追加值。

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

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

5.1.1.7 strlen 字符串长度

用于获取指定 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。
注意:每个中文占3个字节

5.1.1.8 getset 设置并返回原值

命令用于设置指定 key 的值,并返回 key 的旧值。

5.1.1.9 setrange 设置指定位置的字符

用指定的字符串覆盖给定 key 所储存的字符串值,下标从0开始计算。

5.1.1.10 getrange 截取字符串

用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。

5.1.2 应用场景

字符串类型的使用场景很广泛:

  • 缓存功能:
    Redis 作为缓存层,MySQL作为存储层,绝大部分请求的数据都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。

  • 限速:
    很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率,例如一分钟不能超过5次。一些网站限制一个IP地址不能在一秒钟之内方问超过n次也可以采用类似的思路。

  • 共享Session:
    一个分布式Web服务将用户的Session信息(例如用户登录信息)保存在各自服务器中,这样会造成一个问题,出于负载均衡的考虑,分布式服务会将用户的访问均衡到不同服务器上,用户刷新一次访问可能会发现需要重新登录,这个问题是用户无法容忍的。为了解决这个问题,可以使用Redis将用户的Session进行集中管理,,在这种模式下只要保证Redis是高可用和扩展性的,每次用户更新或者查询登录信息都直接从Redis中集中获取。

  • 计数:
    使用Redis 作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源。

  • 限速:
    比如,很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率,例如一分钟不能超过5次。一些网站限制一个IP地址不能在一秒钟之内方问超过n次也可以采用类似的思路。

5.2 哈希(Hash)

Java里提供了HashMap,Redis中也有类似的数据结构,就是哈希类型。但是要注意,哈希类型中的映射关系叫作field-value,注意这里的value是指field对应的值,不是键对应的值。

5.2.1 操作命令

5.2.1.1 hset 设值

命令用于为哈希表中的字段赋值 。如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。如果字段已经存在于哈希表中,旧值将被覆盖。
此外Redis提供了hsetnx命令,它们的关系就像set和setnx命令一样,只不过作用域由键变为field。

5.2.1.2 hget 取值

用于返回哈希表中指定字段的值。

5.2.1.3 hdel 删除field

会删除一个或多个field,返回结果为成功删除field的个数。

5.2.1.4 hlen 计算field个数

命令用于获取哈希表中字段的数量。

5.2.1.5 hmset 批量设值

命令用于同时将多个 field-value (字段-值)对设置到哈希表中。此命令会覆盖哈希表中已存在的字段。如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。

5.2.1.6 hmget 批量取值

命令用于返回哈希表中,一个或多个给定字段的值。如果指定的字段不存在于哈希表,那么返回一个 nil 值。

5.2.1.7 hexists判断field是否存在

若存在返回1,不存在返回0。

5.2.1.8 hkeys获取所有field

它返回指定哈希键所有的field。

5.2.1.9 hvals获取所有value

它返回指定哈希键所有的field的value。

5.2.1.10 hgetall获取所有field与value

在使用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能。如果只需要获取部分field,可以使用hmget,如果一定要获取全部field-value,可以使用hscan命令,该命令会渐进式遍历哈希类型。

5.2.1.11 hscan

迭代哈希表中的键值对。

HSCAN key cursor [MATCH pattern] [COUNT count]
  • cursor - 游标。
  • pattern - 匹配的模式。
  • count - 指定从数据集里返回多少元素,默认值为 10 。

在这里插入图片描述

5.2.1.12 hincrby 增加

命令用于为哈希表中的字段值加上指定增量值。如果哈希表的 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。
在这里插入图片描述

5.2.1.13 hstrlen 计算value的字符串长度

在这里插入图片描述

5.2.2 使用场景

哈希类型比较适宜存放对象类型的数据,如果我们要将一个数据库表存入Redis。

  • 使用String类型

需要一条条的去插入。例如

set user:1:name yangbinghao //user表的ID唯一的数据name值为:yangbinghao
set user:1:age 26
set user:1:sex nan

优点: 简单直观,通过Key就知道这条数据的意思。
缺点: Key会很多,占用内存多,用户信息过于分散。

  • 将对象序列化存入Redis

例如使用各种JSON工具
优点: 编程简单,存取方便。
缺点: 序列化与反序列化有一定开销,更新属性时需要把数据全取出来进行反序列化,更新后再序列化到redis

  • 使用哈希类型

hmset user:1 name yangbinghao age 26 //user表ID为1的数据name=yangbinghao age=26
hmset user:2 name xiaoming age 18

优点: 简单直观,使用合理可减少内存空间消耗
缺点: 要控制内部编码格式,不恰当的格式会消耗更多内存。

5.3 列表(list)

列表( list)类型是用来存储多个有序的字符串,a、b、c、c、b四个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素(element),一个列表最多可以存储(2^32-1)个元素(4294967295)。

在这里插入图片描述

在Redis 中,可以对列表两端插入( push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。

5.3.1 操作命令

5.3.1.1 lrange 获取指定范围内的元素列表(不会删除元素)

返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

5.3.1.2 rpush 向右插入

命令用于将一个或多个值插入到列表的尾部(最右边)。如果列表不存在,一个空列表会被创建并执行 RPUSH 操作。

5.3.1.3 lpush 向左插入

命令用于将一个或多个值插入到列表的首部(最左边)。如果列表不存在,一个空列表会被创建并执行 RPUSH 操作。

5.3.1.4 linsert 在某个元素前或后插入新元素

命令用于在列表的元素前或者后插入元素。当指定元素不存在于列表中时,不执行任何操作。

LINSERT key BEFORE|AFTER pivot value  //将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
5.3.1.5 lpop 从列表左侧弹出(会删除元素)

命令用于移除并返回列表的第一个元素。

5.3.1.6 rpop 从列表右侧弹出

命令用于移除并返回列表的最后一个元素。

5.3.1.7 lrem 对指定元素进行删除

根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。

COUNT 的值可以是以下几种:

  • count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
  • count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
  • count = 0 : 移除表中所有与 VALUE 相等的值。
5.3.1.8 ltrim 按照索引范围修剪列表

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

5.3.1.9 lset 修改指定索引下标的元素

通过索引来设置元素的值。

5.3.1.10 lindex 获取列表指定索引下标的元素

命令用于通过索引获取列表中的元素。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

5.3.1.11 llen 获取列表长度

命令用于返回列表的长度。 如果列表 key 不存在,则 key 被解释为一个空列表,返回 0 。 如果 key 不是列表类型,返回一个错误。

5.3.1.12 blpop和brpop阻塞式弹出元素

blpop和brpop是lpop和rpop的阻塞版本,除此之外还支持多个列表类型,也支持设定阻塞时间,单位秒,如果阻塞时间为0,表示一直阻塞下去。

A客户端阻塞了(因为没有元素就会阻塞)
在这里插入图片描述

A客户端一直处于阻塞状态。此时我们从另一个客户端B执行
在这里插入图片描述
A客户端则输出
在这里插入图片描述

注意:brpop后面如果是多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端立即返回。

5.3.2 使用场景

列表类型可以用于比如:

消息队列,Redis 的 lpush+brpop命令组合即可实现阻塞队列,生产者客户端使用lrpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。

实现其他数据结构:

lpush+lpop =Stack(栈)

lpush +rpop =Queue(队列)

lpush+ ltrim =Capped Collection(有限集合)

lpush+brpop=Message Queue(消息队列)

5.4 集合(set)

集合( set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。

一个集合最多可以存储2的32次方-1个元素。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多实际问题。

image.png

5.4.1 操作命令

5.4.1.1 sadd 添加元素

允许添加多个,返回结果为添加成功的元素个数。

5.4.1.2 srem 删除元素

允许删除多个,返回结果为成功删除元素个数。

5.4.1.3 scard 计算元素个数

命令返回集合中元素的数量。

5.4.1.4 sismember 判断元素是否在集合中

如果给定元素element在集合内返回1,反之返回0。

5.4.1.5 srandmember 随机从集合返回指定个数元素

指定个数如果不写默认为1。
image.png

5.4.1.6 spop 从集合随机弹出元素

同样可以指定个数,如果不写默认为1,注意,既然是弹出,spop命令执行后,元素会从集合中删除,而srandmember不会。

5.4.1.7 smembers 获取所有元素(不会弹出元素)

返回结果是无序的。

5.4.1.8 sinter 求多个集合的交集

image.png

5.4.1.9 sunion 求多个集合的并集

在这里插入图片描述

5.4.1.10 sdiff 求多个集合的差集

命令返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。不存在的集合 key 将视为空集。
在这里插入图片描述

5.4.1.11 将交集、并集、差集的结果保存

sinterstore destination key [key …]
suionstore destination key [key …]
sdiffstore destination key [key …]

集合间的运算在元素较多的情况下会比较耗时,所以 Redis提供了上面三个命令(原命令+store)将集合间交集、并集、差集的结果保存在destination key中

5.4.2 使用场景

集合类型比较典型的使用场景是标签(tag)。例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签,这些数据对于用户体验以及增强用户黏度比较重要。

例如一个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产品,通常会为网站带来更多的利益。

除此之外,集合还可以通过生成随机数进行比如抽奖活动,以及社交图谱等等。

5.5 有序集合(ZSET)

image.png

有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数( score)作为排序的依据。

有序集合中的元素不能重复,但是score可以重复,就和一个班里的同学学号不能重复,但是考试成绩可以相同。

有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能,合理的利用有序集合,能帮助我们在实际开发中解决很多问题。

5.5.1 操作命令

5.5.1.1 zadd添加成员

image.png

返回结果代表成功添加成员的个数

要注意:

image.png

zadd命令还有四个选项nx、xx、ch、incr 四个选项

nx: member必须不存在,才可以设置成功,用于添加。

xx: member必须存在,才可以设置成功,用于更新。

ch: 返回此次操作后,有序集合元素和分数发生变化的个数

incr: 对score做增加,相当于后面介绍的zincrby

5.5.1.2 zcard 计算成员个数

image.png

5.5.1.3 zscore 计算某个成员的分数

image.png

如果成员不存在则返回nil

5.5.1.4 zrank计算成员的排名

image.png

zrank是从分数从低到高返回排名

zrevrank反之

很明显,排名从0开始计算。

5.5.1.5 zrem 删除成员

image.png

允许一次删除多个成员。

返回结果为成功删除的个数。

5.5.1.6 zincrby 增加成员的分数

image.png

5.5.1.7 zrange和zrevrange返回指定排名范围的成员

有序集合是按照分值排名的,zrange是从低到高返回,zrevrange反之。如果加上
withscores选项,同时会返回成员的分数

image.png

image.png

5.5.1.8 zrangebyscore返回指定分数范围的成员
zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores][limit offset count]

其中zrangebyscore按照分数从低到高返回,zrevrangebyscore反之。例如下面操作从低到高返回200到221分的成员,withscores选项会同时返回每个成员的分数。

同时min和max还支持开区间(小括号)和闭区间(中括号),-inf和+inf分别代表无限小和无限大:

image.png

image.png

image.png

5.5.1.9 zcount 返回指定分数范围成员个数

zcount key min max

image.png

5.5.1.10 zremrangebyrank 按升序删除指定排名内的元素

zremrangebyrank key start end

5.5.1.11 zremrangebyscore 删除指定分数范围的成员

zremrangebyscore key min max

5.5.1.12 集合间操作命令
  • zinterstore 交集

zinterstoreimage.png

这个命令参数较多,下面分别进行说明

destination:交集计算结果保存到这个键。

numkeys:需要做交集计算键的个数。

key [key …]:需要做交集计算的键。

weights weight
[weight …]:每个键的权重,在做交集计算时,每个键中的每个member 会将自己分数乘以这个权重,每个键的权重默认是1。

aggregate sum/
min |max:计算成员交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做汇总,默认值是sum。

不太好理解,我们用一个例子来说明。(算平均分)

image.png

image.png

  • zunionstore 并集

该命令的所有参数和zinterstore是一致的,只不过是做并集计算。

5.5.2 使用场景

有序集合比较典型的使用场景就是排行榜系统。例如视频网站需要对用户上传的视频做排行榜,榜单的维度可能是多个方面的:按照时间、按照播放数量、按照获得的赞数。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨洋阳和羊羊羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值