Redis快速学习

1、进入Redis客户端

  1. 首先我们要进入redis里,输入命令cd /usr/local/bin,然后输入命令ls查看里面的文件

    在这里插入图片描述

  2. 输入命令redis-server myredisconfig/redis.conf ,启动服务

    在这里插入图片描述

  3. 然后输入命令redis-cli -p 6379命令,进入redis里

  4. 可以输入ping命令,查看是否成功

    在这里插入图片描述

2、键命令

2.1、String类型

1、set命令

创建key-value值

在这里插入图片描述

如果设置的字符串中间有空格,需要带上""双引号,否则会把空格后面的字符当作参数对待

在这里插入图片描述

2、get命令

根据key得到value的值

在这里插入图片描述

3、keys *命令

获取数据库里存放的所有键

在这里插入图片描述

4、type命令

根据key获取它存放的数据类型

在这里插入图片描述

5、exists命令

判断键是否存在,存在则为1,不存在则为0

在这里插入图片描述

6、expire命令

设置一个键在指定秒数后过期

在这里插入图片描述

7、ttl命令

可以看到键还有多少存活时间,如果死亡则为-2

在这里插入图片描述

再次输入get stuname可以看到,已经为空了

在这里插入图片描述

8、append命令

根据key在字符串类型后面追加内容,返回类型为字符串长度

在这里插入图片描述

如果上面使用ttl命令使这个键过期后,再次添加会报错,第三部分为解决方案

在这里插入图片描述

9、getrange命令

根据自己设定的起始值与结束值,获取字符串,如果输入0 -1,那么就是获取全部内容

在这里插入图片描述

10、setrange命令

根据key,从指定下标开始,替换成指定的字符,返回值为修改后的字符串长度

在这里插入图片描述

这个的意思是,从下标3开始,依次替换为指定字符(字符下标从0开始)

11、setex命令

设置过期时间,在执行set命令的时候,设置键存在时长

在这里插入图片描述

这个命令的意思为,设置键key1 值为value1,存在时长为10秒

12、setnx命令

如果key不存在,就新建,如果存在,就不新建

在这里插入图片描述

13、mset命令

批量添加

在这里插入图片描述

14、mget命令

批量获得

在这里插入图片描述

15、msetnx命令

批量添加并且key是否存在,如果存在,则全部都添加失败

在这里插入图片描述

可以看到,报错了。

我们去除RDB报错以后,再执行,可以看到返回值为0,添加了0条

在这里插入图片描述

16、getset命令

先根据key获得,然后再设置

在这里插入图片描述

因为我们原本没有key为name的键值所以返回为nil,但是同时也set了name值为lisi,所以我们根据name可以得到lisi

2.1、List类型

1、lrange命令

根据key,查看list类型的key的值,查看其他类型的会报错 参数为0 -1

在这里插入图片描述

2、lpush命令

左推入,给数组里添加内容

在这里插入图片描述

可以看到,我们添加的顺序为redis->oracle->mysql,显示出来顺序刚好相反,这是因为我们这个命令是左推入,就是把数据从左侧推入数组中。

3、rpush命令

右推入,从数组右侧给数组添加内容

在这里插入图片描述

可以看到,我们刚添加的数据,在数组的最后面(也就是最右侧)

4、lpop命令

从左侧移除一个值

在这里插入图片描述

可以看到,最左侧的mysql被移出去了

5、rpop命令

从右侧移除一个值

在这里插入图片描述

可以看到,最右侧的mongodb被移出去了

6、lindex命令

根据下标获取数组内容,下标从0开始

在这里插入图片描述

7、llen命令

获取list的长度

在这里插入图片描述

8、lrem命令

移除指定数量的值

  1. 先创建一个数组,添加多个重复值

  2. 在这里插入图片描述

  3. 执行命令进行删除测试

    在这里插入图片描述

    可以发现,移除了一个lisi

  4. 在这里插入图片描述

    可以发现,移除了两个zhangsan

9、ltrim命令

截取数组的内容,对原来数组有影响

  1. 创建示例集合

    在这里插入图片描述

  2. 截取数组内下标从1-3的内容

    在这里插入图片描述

  3. 可以发现下标为0的数组和下标在3以后的数组都没了,只留下了下标从1-3的内容

10、rpoplpush命令

组合命令,先弹出,后添加

  1. 先把原数组最右侧的值弹出去,然后添加到新的数组中

    在这里插入图片描述

  2. 可以看到原数组中的hello2被弹出去了,然后被添加到新的数组mynewlist中去了

11、lset命令

根据下标进行替换

在这里插入图片描述

可以看到第一个值(下标为0)被替换为nihao4

12、linsert命令

在指定值的指定位置插入值

在这里插入图片描述

这个命令的意思是:在mylist集合中,把hello2插入到hello3之前

在这里插入图片描述

如果设为after,则是在指定值之后添加指定内容了。

2.3、Set类型

无序,不可重复的集合

1、sadd命令

给集合添加内容

在这里插入图片描述

2、smembers命令

查看set里面所有内容

在这里插入图片描述

3、sismember命令

判断值是否在集合里面 0:不在,1:在

在这里插入图片描述

4、scard命令

获取数组的个数

在这里插入图片描述

5、srem命令

移除一个元素

在这里插入图片描述

6、srandmember命令

随机获取一个元素,可以指定获取的元素个数

在这里插入图片描述

7、spop命令

随机弹出元素(移除)

在这里插入图片描述

8、smove命令

移动元素

  1. 创建两个集合,一个抽奖的姓名,一个是中奖的姓名

    在这里插入图片描述

  2. 移动抽奖人lisi到中奖人名单中,并查看中奖人集合

    在这里插入图片描述

9、sdiff命令

求两个集合的差集,以第一个集合为准

在这里插入图片描述

以第一个集合为准,只求第一个集合中的差异

在这里插入图片描述

以第二个集合为准,只求第二个集合中的差异

10、sinter命令

求两个集合的交集

在这里插入图片描述

11、sunion命令

求两个集合的并集

在这里插入图片描述

因为set不允许重复,所以里面只有一个c

2.4、Hash类型

本身是键值对,但是值也是键值对

1、hset命令

创建Hash类型的集合

在这里插入图片描述

在这里插入图片描述

2、hget命令

根据hash值的键,得到值

在这里插入图片描述

3、hmget命令

批量获得

在这里插入图片描述

4、hgetall命令

根据键获取里面的所有值(值也是键值)

在这里插入图片描述

5、hdel命令

根据值的键,删除对应的值

在这里插入图片描述

6、hlen命令

获取长度

在这里插入图片描述

7、hexists命令

判断键是否存在 0:不存在,1:存在

在这里插入图片描述

8、hkeys命令

获得所有键

在这里插入图片描述

9、hvals命令

获取所有的值

在这里插入图片描述

2.5、Zset类型

  • Redis的zSetset一样也是String类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。Redis正是通过分数来为集合中的成员进行从小到大的排序。
  • Zset的成员是唯一的,但分数(score)却可以重复。当你需要一个有序的并且不重复的集合列表时,那么可以选择sortedset数据结构。

应用举例:

  • 存储全班同学的成绩,其集合value可以是同学的学号,而score就可以是成绩。
  • 排行榜应用,根据得分列出topN的用户等。
1、zadd命令

添加

在这里插入图片描述

在这里插入图片描述

2、zrange命令

获得所有值

在这里插入图片描述

3、zrangebyscore命令

根据分数进行排序 参数-inf +inf inf为无穷的意思 默认降序

在这里插入图片描述

上面这个看排名的时候,还得看看分数是否对应,是否排名正确,下面带着分数一起查出来

  • 根据分数排序并且显示对应的分数

在这里插入图片描述

  • 只查询分数在60以下的人

    在这里插入图片描述

4、zrevrangebyscore命令

降序排序

5、zrem命令

移除

在这里插入图片描述

6、zcard命令

获取数据个数

在这里插入图片描述

7、zcount命令

获取统计指定分数区间的数据条数

在这里插入图片描述

3、RDB报错

使用命令config set stop-writes-on-bgsave-error no

在这里插入图片描述

4、清空数据库

使用命令flushdb即可清空数据库(操作不可逆,慎重!)

在这里插入图片描述

5、Redis事务

Redis单个命令可以保证原子性,但是事务里面的命令没有原子性,事务里单个命令执行失败不影响其他命令的执行。

Redis事务可以理解为:可以批量执行命令的一组命令

  • 开启事务命令:multi
  • 执行事务命令:exec
  • 取消事务命令:discard
  1. 任务一:开启事务,创建set类型集合,里面添加三条数据,一条添加重复的执行失败,查看结果

    在这里插入图片描述

    可以看到,第二条命令执行失败,但是不影响其他命令执行

  2. 任务二:取消事务

    在这里插入图片描述

6、乐观锁

  • 悲观锁,正如其名,具有强烈的独占和排他特性,即数据任何时候都会被使用,无论做什么都应该加锁。
  • 乐观锁机制采取了更加宽松的加锁机制,即数据任何时候都不会被使用。
  • 乐观锁是相对悲观锁而言,也是为了避免数据库幻读、业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性。但是由于悲观锁意味着在任何时候都需要加锁,所以会极大影响数据库性能,所以我们一般都会使用乐观锁。
  1. 任务一:以转账为例,用乐观锁举例事务类型的操作

    1. 创建两个变量,money和out。money代表转入变量,out代表被转入变量

      在这里插入图片描述

    2. 开启事务,money转出20到out里面

      在这里插入图片描述

    3. 我们这时候再开启一个终端,模拟多线程操作

      在这里插入图片描述

    4. 左边的使用watch命令,监视money变量,当money变量被修改,那么事务失败

    5. 左边继续重复上面的操作,只不过不执行

      在这里插入图片描述

    6. 这是我我们在右边的终端中修改变量money的值

      在这里插入图片描述

    7. 然后我们左边执行事务,可以发现事务执行失败

      在这里插入图片描述

    8. 执行失败,当我们事务执行失败的时候,我们可以使用unwatch接触监视,再使用watch重新监视并打开事务来重新操作即可。

      在这里插入图片描述

    9. 注意:当使用exec或discard命令时,会自动解除监视。

7、持久化之RDB

  • Redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失。幸好Redis 还为我们提供了持久化的机制,分别是RDB(Redis DataBase)AOF(Append Only File)

  • RDB其实就是把数据以快照的形式保存在磁盘上。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB0的缺点是最后一次持久化后的数据可能丢失。

  • 默认使用RDB

  1. 执行exit命令,退出redis,然后输入命令su root进入root账号

  2. 进入之前复制过来的redis.cfg配置文件,命令vim /usr/local/bin/myredisconfig/redis.conf

  3. 进入以后,往下翻,可以看到如下设置

    在这里插入图片描述

  4. 这个意思为:如果在900秒内,至少有1个key发生了变化,那么900秒以后就会把内存中的内容保存到硬盘中,其他含义的以此类推。

  5. 可以自行更改,但是不建议。

  6. redis会自动在主目录下自动生成dump.rdb文件

  7. 可以使用rm -rf dump.rdb命令进行删除文件

  • RDB优点
    • 这种文件非常适合用于进行备份:比如说,你可以在最近的24小时内,每小时备份一次 RDB文件,并且在每个月的每一天,也备份一个RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB非常适用于灾难恢复。
  • RDB缺点
    • 如果你需要尽量避免在服务器故障时丢失数据,那么RDB不适合你。虽然 Redis 允许你设置不同的保存点(save point)来控制保存RDB文件的频率,但是,因为RDB文件需要保存整个数据集的状态,所以它并不是一个轻松的操作。因此你可能会至少5分钟才保存一次 RDB文件。在这种情况下,一旦发生故障停机,你就可能会丢失好几分钟的数据。

8、持久化之AOF

  • AOF的全称为Append Only File,机制是将所有命令都记录在一份文件中(只记录写命令),一旦数据丢失,将备份文件中的命令依次执行一次即可恢复数据。
  • AOF保存的文件是appendonly.aof,可以在配置文件中进行配置。
  • 在这里插入图片描述
  1. 还是和上面一样的操作,我们输入vim /usr/local/bin/myredisconfig/redis.conf命令,编辑我们的配置文件,我们往下翻,找到如下配置

    在这里插入图片描述

  2. 我们输入i进入编辑模式,然后把no改为yes,然后按esc键退出编辑模式,再输入:wq进行保存退出

  3. 这时候我们进入redis

    在这里插入图片描述

  4. 进入以后,我们添加几条数据

    在这里插入图片描述

  5. 添加完成后,我们输入exit退出redis,然后输入ls命令,查看bin目录下的redis文件

    在这里插入图片描述

  6. 这时候可以发现我们多了一个文件,我们输入vim命令查看文件

    在这里插入图片描述

  7. 里面其实就放着一个一个的我们执行的命令

  • AOF优点
    • 使用AOF持久化会让Redis变得非常耐久:你可以设置不同的fsync策略,比如无fsync,每秒钟一次fsync,或者每次执行写入命令时fsync。AOF的默认策略为每秒钟fsync一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据(fsync会在后台线程执行,所以主线程可以继续努力地处理命令请求)。
  • AOF缺点
    • 对于相同的数据集来说,AOF 文件的体积通常要大于RDB文件的体积。根据所使用的fsync策略,AOF的速度可能会慢于RDB。在一般情况下,每秒fsync的性能依然非常高,而关闭fsync可以让AOF的速度和RDB一样快,即使在高负荷之下也是如此。不过在处理巨大的写入载入时,RDB可以提供更有保证的最大延迟时间。

9、Redis订阅和发布

  • Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
  • Redis客户端可以订阅任意数量的频道。
  • 简单来说就像我们很多人订阅了某个微信公众号,一旦公号发布了消息,那么大家都可以接收到。
    • 订阅命令:subscribe xxx
    • 发布命令:publish xxx "message"
  • 在这里插入图片描述

举例演示:

  1. 我们需要打开两个终端,并且都使用root账号,进入redis

    在这里插入图片描述

  2. 然后在左边终端中执行命令subscribe dingyueyvfabu订阅名为dingyueyvfabu的频道

    在这里插入图片描述

  3. 然后我们在右边终端执行publish dingyueyvfabu "hello world!"命令,在名为dingyueyvfabu的频道上发布内容

    在这里插入图片描述

  4. 发布完后,我们可以观察左边的相应,多了三条,对应就是频道做出的响应

    在这里插入图片描述

  • Pub/Sub从字面上理解就是发布( Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后所有订阅它的客户端都会收到相应的消息
  • 这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊,关注等功能。

10、Redis主从复制概念

  • 主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。
  • Master以写为主,Slave以读为主。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用

  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。

  • 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。

  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由h机点在时应用连接从节点),分担服应用连接主节点,读Redis数据切号下,通过多个从节点分务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

  • 高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

  • 一般来说,要将Redis运用于工程项目中,只使用一台Redis是万万不能的,原因如下:

    • 从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;
    • 从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不能将所有内存用作Redis存储内存,一般来说,单台Redis最大使用内存不应该超过20G。
    • 所以一般都是如下图所示的集群结构,一台主机多台从机主机负责写,从机负责读;因为一般的读取压力稍微大一些,写入压力稍微小一些。

在这里插入图片描述

搭建一个”一主二从的Redis集群环境“

  1. 开启四个终端,使用root账号,然后最后一个终端进入/usr/local/bin路径下

    在这里插入图片描述

  2. 然后我们复制redis.conf配置文件,分别命名为redis79.conf、redis80.conf、redis81.conf

    在这里插入图片描述

  3. 然后我们依次修改配置文件的以下地方,端口号分别改成6379、6380、6381

    1. 在这里插入图片描述

    2. 在这里插入图片描述

    3. 在这里插入图片描述

    4. 在这里插入图片描述

  4. 修改完四个配置文件后,我们在第一个终端上以redis79.conf配置文件启动,然后第二个为redis80.conf配置文件启动,第三个以redis81.conf配置文件启动

    在这里插入图片描述

  5. 全部开启成功后,我们可以输入info replication命令,查看当前端口状态

    在这里插入图片描述

  6. 在端口为6380的服务上输入命令slaveof 127.0.0.1 6379连接主服务

    在这里插入图片描述

  7. 这时候我们在分别6379、6380的服务上输入info replication命令查看服务情况

    在这里插入图片描述

  8. 我们再把6381的端口也连接上6379,这样就形成了一主二从的结构

    在这里插入图片描述

测试

  • 一主二从是主库用来执行写入操作,从库用来执行读取操作

    • 我们在主库添加一条数据,然后在从库分别读取

      在这里插入图片描述

    • 我们再试试,在从库执行写入操作会发生什么

      在这里插入图片描述

    • 可以发现,会报错,写入失败。

  • 从机宕机后,不影响主机的写入和其他从机的读取,但是从机再次启动后,需要手动连接主机

  • 主机宕机后,不可以执行写入操作,只能使用从机执行读取操作,等待主机手动开机

    在这里插入图片描述

  • 主机手动开机后

    在这里插入图片描述

当从机宕机重启之后,又变为了主机,所以需要重新配置,原因是我们之前是使用“命令”的方式来配置从机,重启之后命令失效,需要重新配置。除了“命令”配置之外还有“配置文件”配置的方法,可以在配置文件中写死本机身份、主机id和端口号等信息。但是这种方式也不是很好,所以我们略过不讲。真正好的解决方案是使用“哨兵模式”。

11、Redis哨兵模式

  • 为什么要有哨兵模式?
    • 主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
  • 哨兵模式能够后台监视主机是否故障,如果故障了根据投票数自动将从库转换为主库,可以有效提高Redis服务的可用性。
  • 哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行多个Redis实例。
  • 在这里插入图片描述
  1. 在最后一个终端中输入cd /usr/local/bin/myredisconfig进入到配置文件夹里

  2. 输入命令vim sentinel.conf,新建哨兵配置文件

  3. 输入内容sentinel monitor myredis 127.0.0.1 6379 1,并保存配置内容

    1. sentinel monitor 被监控的名称 主机地址 端口号 1代表当有1个哨兵发现主机死亡则开启投票
    2. 1台哨兵模式有可能会出现哨兵宕机的情况,所以有可能会部署为哨兵集群,当是集群的时候,可以将最后的数字进行修改,如果修改为2,则代表有2个哨兵发现主机死亡则开启投票。

    在这里插入图片描述

  4. 开启哨兵,进入到cd /usr/local/bin目录下

  5. 使用哨兵文件开启哨兵模式,执行命令redis-sentinel myredisconfig/sentinel.conf

    在这里插入图片描述

  6. 可以发现,目前有一个主机(6379)和两个从机(6380和6381)

测试

  1. 我们关闭主机,看看第四个哨兵什么时候可以发现并且再次选举出一个从机作为主机

  2. 大概过了几十米后,第四个终端开始打印东西

    在这里插入图片描述

  3. 发现了6379宕机了,并且选举6380为主机。

  4. 我们在6380上输入info replication命令查看状态

    在这里插入图片描述

  5. 可以发现,主机已经转移到6379上面,并且有一个从机为6381

  6. 这时候我们再让6379连接上,查看是否还是主机

    在这里插入图片描述

  7. 可以看到,主机位已经丢失,变为从机了,并且在第四个终端里可以看到,哨兵发现6379回来了,但是变为从机,连接上端口为6380的主机了。

    在这里插入图片描述

1、优点

  • 哨兵集群基于主从复制模式,所有的主从配置优点都会被继承
  • 主从可以切换,故障可以转移,系统的可用性更高。
  • 哨兵模式就是主从模式的升级版。

2、缺点

  • Redis难以在线扩容,集群容量一旦达到上限,在线扩容十分麻烦。
  • 实现哨兵模式的配置非常麻烦,其中配置选项巨多。

此处分享完整的Redis哨兵配置,以后在工作中可以直接根据情况使用。

# Example sentinel.conf

# 哨兵sentinel实例运行的端口 默认 26379
port 26379

# 哨兵sentinel的工作目录
dir /tmp

# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127 .0.0.1 6379 2

# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供
密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认 30 秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000

# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1

# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那
里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,
slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>

12、缓存击穿和雪崩

​ Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一 些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据 的一致性要求很高,那么就不能使用缓存。

​ 另外的一些典型问题就是,缓存穿透、缓存雪崩和缓存击穿。目前,业界也都有比较流行的解决方案。

1、缓存穿透

概念

​ 缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于 是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了 缓存穿透。

解决方案

1、布隆过滤器

​ 隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则 丢弃,从而避免了对底层存储系统的查询压力;

在这里插入图片描述

2、缓存空对象

​ 当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数 据将会从缓存中获取,保护了后端数据源;

在这里插入图片描述

​ 但是这种方法会存在两个问题: 1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多 的空值的键; 2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于 需要保持一致性的业务会有影响。

2、缓存击穿

概念

​ 这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中 对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

​ 当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访 问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。

解决方案

1、设置热点数据永不过期

从缓存层面来看,没有设置过期时间,所以不会出现热点 key 过期后产生的问题。

2、加互斥锁

​ 分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考 验很大。

3、缓存雪崩

概念

缓存雪崩,是指在某一个时间段,缓存集中过期失效。Redis 宕机!

​ 产生雪崩的原因之一,比如双十一凌晨0点,大量商品数据会比较集中的放入缓存中,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都 过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

​ 其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是可以顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。

解决方案

1、Redis高可用

​ 这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续 工作,其实就是搭建的集群。

2、限流降级

​ 这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待!

3、数据预热

​ 数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数 据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让 缓存失效的时间点尽量均匀。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值