redis知识总结

一、什么是Redis

Redis是一个开源的内存数据存储系统,也是一个高性能的键值存储数据库。它支持多种数据结构,包括字符串、哈希表、列表、集合以及有序集合。Redis的特点是快速、灵活和可扩展。

首先,Redis是一个内存数据存储系统,这意味着它将所有数据存储在内存中,因此具有非常快的读写速度。相比于传统的磁盘存储系统,Redis可以提供非常低的读写延迟,使得它非常适合需要快速响应的应用场景,如缓存、实时计算等。

其次,Redis支持多种数据结构。除了最基本的字符串类型,Redis还支持哈希表、列表、集合和有序集合等数据结构。这使得开发者可以根据自己的需求选择最适合的数据结构,并可以利用这些数据结构来实现更复杂的功能。例如,哈希表可以用来存储对象,列表可以用来实现队列和栈,集合可以用来存储唯一值,有序集合可以用来实现排行榜等。

此外,Redis还具有一些特殊的功能。它可以通过持久化机制将数据存储到硬盘上,以防止内存数据丢失。它还支持发布-订阅模式,使得不同的客户端可以通过订阅频道来接收消息。此外,Redis还提供了事务和 Lua 脚本功能,使得开发者可以执行一系列操作来保证数据的一致性。

另外,Redis还具有良好的可扩展性。它支持主从复制,可以将数据复制到多个节点上,提高数据的可用性和容错性。此外,Redis还支持集群模式,可以将数据分布在多个节点上,提供更高的性能和容量。

总而言之,Redis是一个快速、灵活和可扩展的内存数据存储系统,广泛应用于各种场景,包括缓存、实时计算、消息队列等。它的简单易用和高性能使得它成为许多开发者和企业的首选。

二、什么是缓存穿透

缓存穿透是指在使用缓存系统时,某个请求查询的数据在缓存中不存在,也不在后端存储系统中,导致每次请求都要访问后端存储系统,从而增加了系统的负载压力,严重影响系统的性能。

缓存系统的设计初衷是为了提高系统的性能和响应速度。当一个请求到达系统时,系统首先会查询缓存,如果缓存中存在该数据,则直接返回给用户,减少了对后端存储系统的访问。但是,当请求查询的数据不存在于缓存中时,系统仍然需要从后端存储系统中获取数据,并将其存入缓存,供后续请求使用。这就是缓存的正常流程。

然而,如果恶意攻击者针对系统中不存在的数据进行大量请求,这些请求会绕过缓存直接访问后端存储系统,导致后端存储系统承受巨大的负载压力。这种情况下就发生了缓存穿透。

缓存穿透可能会造成以下问题:

性能问题:由于每次请求都要访问后端存储系统,系统的响应时间变慢,影响用户体验。

资源浪费:大量无效的请求会占用系统的计算资源和网络带宽,浪费了宝贵的系统资源。

为了解决缓存穿透问题,可以采取以下几种措施:

布隆过滤器:使用布隆过滤器来过滤掉一部分恶意请求。布隆过滤器是一种概率型数据结构,可以判断一个元素是否在集合中,被广泛用于缓存穿透的解决方案中。

缓存空值:当后端存储系统查询不到数据时,也将空值存入缓存。这样,在下一次请求查询相同数据时,就可以直接从缓存中获取空值,而不需要再次访问后端存储系统。

设置短暂的过期时间:对于缓存中不存在的数据,可以给其设置一个较短的过期时间。这样,在过期时间内,即使有大量请求查询该数据,也能够直接从缓存中获取,而不需要访问后端存储系统。

异步加载数据:当发现某个请求查询的数据不存在于缓存中时,可以异步地去后端存储系统中加载数据,并将其存入缓存。这样可以避免在查询时阻塞请求线程,提高系统的并发性能。

综上所述,缓存穿透是指恶意请求查询缓存中不存在的数据,导致每次请求都需要访问后端存储系统,造成系统性能下降和资源浪费。为了解决这个问题,可以采取布隆过滤器、缓存空值、短暂过期时间和异步加载数据等措施来提升系统的性能和稳定性。

三、什么是缓存击穿

缓存击穿是指在使用缓存系统时,某个热点数据过期或被删除,而此时又有大量并发请求同时访问该数据,导致缓存系统无法命中并且每个请求都要访问后端存储系统,从而造成后端存储系统的压力过大,严重影响系统的性能。缓存的设计初衷是为了提高系统的性能和响应速度。当一个请求到达系统时,首先会查询缓存,如果缓存中存在该数据,就可以直接返回给用户,避免了访问后端存储系统的开销。然而,当某个热点数据过期或被删除时,如果此时有大量并发请求同时访问该数据,这些请求会绕过缓存直接访问后端存储系统,导致后端存储系统承受巨大的负载压力,而且每个请求都要进行独立的查询和加载数据,重复的工作浪费了系统资源。

缓存击穿可能会造成以下问题:

性能问题:由于每个请求都要访问后端存储系统,系统的响应时间变慢,影响用户体验。
资源浪费:大量无效的请求会占用后端存储系统的计算资源和网络带宽,浪费了宝贵的系统资源。
为了解决缓存击穿问题,可以采取以下几种措施:

加锁机制:通过在缓存查询的关键代码段加锁,使得只有一个线程可以从后端存储系统加载数据,并将加载的结果存入缓存。其他并发请求在等待锁释放后,直接从缓存获取数据。
预加载数据:在热点数据过期前主动加载数据并存入缓存,避免数据过期时出现大量并发请求同时访问。
使用互斥锁:在缓存失效时,只允许一个线程从后端存储系统加载数据,并将结果存入缓存。其他线程在等待期间直接从缓存获取数据,避免重复的查询操作。
降低数据过期时间:合理设置缓存数据的过期时间,避免过长的过期时间导致数据过期后出现缓存击穿的情况。
综上所述,缓存击穿是指热点数据过期或被删除,而此时有大量并发请求同时访问该数据,导致缓存系统无法命中并且每个请求都要访问后端存储系统,从而造成后端存储系统的压力过大。为了解决这个问题,可以采取加锁机制、预加载数据、使用互斥锁和降低数据过期时间等措施来提升系统的性能和稳定性。

四、什么是缓存雪崩

缓存雪崩是指在使用缓存系统时,大量的缓存数据同时失效或被删除,导致多个请求同时访问后端存储系统,从而使得后端存储系统无法承受如此大的负载压力,严重影响系统的性能和可用性。缓存的设计初衷是为了提高系统的性能和响应速度。当一个请求到达系统时,首先会查询缓存,如果缓存中存在该数据,就可以直接返回给用户,避免了访问后端存储系统的开销。然而,当大量的缓存数据同时失效或被删除时,如果此时有大量并发请求同时访问后端存储系统,后端存储系统会受到巨大的负载压力,可能导致系统崩溃或严重延迟。

缓存雪崩可能会造成以下问题:

1.性能问题:由于大量请求同时访问后端存储系统,系统的响应时间变慢,影响用户体验。

2.可用性问题:过多的请求访问后端存储系统可能导致系统崩溃或严重延迟,使得整个系统不可用。

为了解决缓存雪崩问题,可以采取以下几种措施:

1.设置合理的缓存过期时间:合理设置缓存数据的过期时间,避免大量缓存数据在同一时间失效。可以通过为不同的数据设置不同的过期时间,使得缓存数据的过期时间分散开来,减少缓存失效的集中发生。

2.缓存数据异步刷新:在缓存数据即将过期时,异步地从后端存储系统加载数据并刷新到缓存中,避免过多请求同时访问后端存储系统。

3.多级缓存策略:引入多级缓存,如本地缓存和分布式缓存,可以在本地缓存失效时从分布式缓存中获取数据,减少直接访问后端存储系统的频率。

4.限流和熔断机制:通过限制并发请求的数量或采取熔断机制,当请求过多时暂停或拒绝一部分请求,保护后端存储系统免受过大的负载压力。

综上所述,缓存雪崩是指大量的缓存数据同时失效或被删除,导致多个请求同时访问后端存储系统,使得后端存储系统无法承受如此大的负载压力。为了解决这个问题,可以采取设置合理的缓存过期时间、缓存数据异步刷新、多级缓存策略和限流熔断机制等措施来提升系统的性能和可用性。

五、Redis持久化

Redis 的持久化机制有两种,一种是快照(RDB),另一种是 AOF 日志。RDB是一次全量备份,AOF 日志是连续的增量备份。快照是内存数据的二进制序列化形式,在存储上非常紧凑,而 AOF 日志记录的是内存数据修改的指令记录文本。

RDB快照

RDB快照持久化是Redis默认开启的,它会根据配置策略将内存数据保存在一个名为dmp.rdb的二进制文件中。

在redis.conf配置文件中,可以配置RDB的持久化策略,系统默认是有三个保存策略(三个同时生效),如下:

  • save 900 1 900秒内有1个键发生改变
  • save 300 10 30秒内有10个键发生改变
  • save 60 10000 60秒内有10000个键发生改变

我们也可以根据我们自己生产环境的具体情况进行配置。如果我们要关闭RDB快照,直接将配置文件中上述三个save注释掉即可。

写时复制机制(COW)

Redis提供了save命令进行快照生成,但是save命令要阻塞主进程(执行客户端命令的线程),当需要生成快照的内存特别大时(几百个G),需要的时间也会很长,甚至十几秒,所以这个时候如果阻塞主进程,会导致整个服务不可用,就得不偿失了。

针对这种情况,Redis借助操作系统提供的写时复制技术,提供了bgsave命令,basave命令可以在主进程的基础上,fork一个子进程,子进程会共享主进程的代码段和数据段,相当于是在后台生成快照。

在bgsave子进程写入RDB数据时,如果主进程对这些数据也都是读操作,那么,主进程和 bgsave 子进程相互不影响。但是,如果主进程要修改一块数据,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入RDB,而在这个过程中,主进程仍然可以直接修改原来的数据。

演示

bgsave会进行后台操作,不阻塞流程。 保存后会生成一个dump.rdb文件。因为二进制文件打开也是乱码,所以我们就不打开了。

优点
  • Redis宕机后数据恢复快
  • 二进制文件体积小
缺点
  • 持久化策略可能会导致在宕机时数据丢失量较多

AOF(append-only file)

AOF持久化可以通过redis.conf文件中的appendonly参数控制是否开启。

  • appendonly no 默认情况下是no, 将no改为yes即可开启AOF持久化方式,Redis会将修改的每一条指令先记录到系统缓存,默认每隔一秒钟就把缓存刷新到appendonly.aof磁盘文件中 当 Redis 重新启动时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
演示

小编直接修改redis.conf文件中的appendonly参数,然后重启redis,set了几个键值对,等了好几秒,发现当前目录下并没有生成appendonly.aof文件。

后来通过直接在redis-cli执行config set appendonly yes命令,当前目录下才生成appendonly.aof文件。

接下来我们打开appendonly.aof文件就能看到我们之前写入的键值对。

 

bash

复制代码

*2 $6 SELECT $1 0 *3 $3 SET $1 1 $1 2 *3 $3 SET $4 key1 $4 val1 *3 $3 SET $4 3124 $3 124 *3 $3 SET $5 key14 $4 key2

这是一种resp协议格式数据,星号后面的数字代表命令有多少个参数,$号后面的数字代表这个参数有几个字符。

AOF持久化策略
  • appendfsync always:每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全,不建议用,本身Redis就是借助的内存快的优势,要是每次操作都访问磁盘这个优势就没了。
  • appendfsync everysec:每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据,AOF默认会走在这个配置。
  • appendfsync no:从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择,发生宕机时,丢失的数据最多。
AOF重写

假设我们执行了两个命令 set key1 1set key1 2,在开启AOF持久化的情况下,这两个命令都会被记录到AOF文件中,但是我们在宕机后重启恢复数据的时候是不是就只需要执行set key1 2就可以了,之前的set key1 1在恢复数据的时候忽略掉也没有任何影响,并且因为AOF文件随着时间的推移,体积会越来越大,重写AOF就显得尤为重要。

手动触发后台重写,redis客户端执行命令:bgrewriteaof

Redis提供了两个配置参数控制AOF自动重写频率(redis.conf)。

  • auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就 很快
  • auto‐aof‐rewrite‐percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写

触发重写时 Redis 会通过fork主进程,生成一个子进程去做,这么做的原因是因为重写一般意味着要有大量的I/O操作,非常耗时,如果用主进程去重写会导致主进程长时间的阻塞,影响Redis执行客户端命令,甚至导致服务长时间不可用,但是子进程去重写就意味着主进程仍然可以接收、处理客户端指令,就会导致重写后的AOF文件和服务器当前的数据库状态不一致。

例如:子进程fork主进程时,内存中只有key1这个键,但是当开始重写后,客户端又多set了key2、key3,这就导致了重写的AOF文件和数据库不一致。

所以Redis在AOF重写时加了一个AOF重写缓冲区,当有新命令执行的时候,Redis会将命令发送到AOF缓冲区和AOF重写缓冲区。

执行完重写任务后,子进程会向主进程发送一个信号,主进程收到信号后会执行下面两个操作(以下两个操作会阻塞主进程):

  • 将 AOF 重写缓冲区中的所有内容写入到新的 AOF 文件中,保证新 AOF 文件保存的数据库状态和服务器当前状态一致。
  • 对新的 AOF 文件进行改名,原子的覆盖现有 AOF 文件,完成新旧文件的替换

虽然只有上面两个操作会阻塞Redis主进程,但是很显然它已经将重写对性能的影响降到了最低。但是如果你想再对其进行优化,这里有两个解决方案。

  1. 服务低峰期定时重写
  2. 使用ssd,提升持久化效率

注意:AOF在重写时,为了避免执行命令时造成的客户端缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这四种可能会有多个元素的键时,会先检查键所包含的元素数量,如果元素的数量超过了redis.h/REDIS_AOF_REWRITe_ITeMS_PER_CMD常量的值(默认64个元素),那么重写程序将会使用多条命令来记录键的值,而不是单单只用一条命令。

优点
  • 数据完整性要高于RDB,默认情况下,最多丢失1秒钟的数据。
缺点
  • Redis宕机后数据恢复慢
  • 文件体积大

混合持久化(sence redis4.0)

Redis宕机恢复时,为了提高数据的完整程度,我们通常使用 AOF 日志进行恢复,但是使用 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis4.0 为了解决这个问题,推出了混合持久化,说白了,混合持久化就是结合了RDB与AOF两种持久化方式的优势。

启混合模式后,AOF在重写时会将AOF文件中的数据以RDB文件的二进制格式写入当前AOF文件中,之后的新的写操作继续以AOF文件的格式进行追加。当redis宕机重启的时候,加载 AOF 文件进行恢复数据:先加载 RDB 的部分再加载剩余的 AOF内容,因此重启效率大幅得到提升。

通过修改redis.conf文件中的以下配置开启混合持久化(必须先开启AOF持久化):

  • aof‐use‐rdb‐preamble yes

总结

  • RDB文件会保存Redis中所有的键值对数据
  • save生成RDB文件会阻塞主进程
  • bgsave命令后台生成RDB,不会阻塞主进程
  • RDB文件体积小,保存的是二进制数据
  • RDB通过配置策略执行,可能会丢失部分数据
  • RDB文件在Redis宕机后恢复快

  • AOF文件保存的是客户端执行的命令
  • AOF文件体积大,恢复慢,但是默认配置下数据比RDB要全很多
  • Redis宕机重启后默认是用AOF方式进行恢复
  • AOF文件中的命令是以Resp协议格式保存的
  • 命令会先保存到缓冲区,再定期同步到AOF文件
  • AOF会根据配置策略自动的对AOF文件进行重写,以降低文件体积
  • AOF重写时会fork一个子进程去执行,同时会有一个重写缓冲区,用来保存重写时主进程修改的键
  • AOF重写时,最后会生成一个新的AOF文件,覆盖原有的文件
  • 将重写缓冲区的内容写入到AOF与替换新旧AOF文件时会阻塞主进程

  • 混合持久化是RDB与AOF的优势结合所产生的
  • 混合持久化本质还是用的AOF文件
  • 混合持久化使用的前提是开启AOF持久化
  • 混合持久化在重写AOF文件时会将数据直接写成RDB的二进制格式,之后新的命令还是以AOF文件Resp协议格式进行保存

fsync

为了提高文件的写入效率,linux系统在做持久化时,会调用write函数,先将要写入文件的数据保存在一个内存缓冲区里就会直接返回,等到缓冲区被填满,或者超过了指定的时限(一般是30秒)后,才会将缓冲区的数据写入到磁盘。

这种做法虽然提高了写入效率,但是如果发生宕机,就有可能会导致缓冲区中还未写入磁盘的数据丢失。

为此,linux提供了fsync函数,它会强制并阻塞等待系统将数据写入到磁盘,从而保证数据的安全性

子进程

为什么Redis会fork一个子进程而不用子线程,是因为子进程可以携带主进程的数据副本,可以避免在不使用锁的情况下,保证数据安全。

注:子进程在重写期间,主进程还是会接收并处理客户端命令,会导致子进程与主进程数据不一致。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值