redis总结

《我们一起进大厂》系列-Redis常见面试题(带答案) - 掘金 (juejin.cn)

redis为什么这么快

  • 基于内存
  • 单线程模型
  • 非阻塞IO
  • 优化过的数据结构和底层模型

基本的数据结构

String

hash

list

朋友圈的点赞的人的显示是有顺序的,可以使用list来实现顺序;如果有人点赞rpush;如果有人取消点赞lrem

set

Zset

  • 跳跃表

  • 哈希表

​ 充分利用 跳跃表的快速查找和插入操作,同时通过哈希表来快速查找元素与分数之间的映射关系

redis的持久化

RDB

RDB是把内存中的数据集以快照的形式写入磁盘,实际操作是fork子进程执行,采用二进制压缩存储;

redis默认使用RDB来持久化,在redis.conf配置文件中默认由此配置

1
2
3
4
5
6
save 900 1           #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发bgsave命令创建快照。

save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发bgsave命令创建快照。

save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发bgsave命令创建快照。

Redis 提供了两个命令来生成 RDB 快照文件:

  • save : 同步保存操作,会阻塞 Redis 主线程;
  • bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。

AOF

AOF是以文本日志的形式记录redis处理的写入和删除操作

AOF(append only file)的实时性更好。默认情况下,reids没有开启AOF,可以使用一下指令开启

1
appendonly yes
AOF的流程

AOF 持久化功能的实现可以简单分为 5 步:

  • **append:**所有的写命令会追加到AOF缓冲区
  • write: 将AOF缓冲区的数据写到AOF文件中。这步 调用write函数(系统调用),write将数据写到系统内核缓冲区
  • fsync:fsycn向磁盘做同步操作
  • rewrite:随着AOF文件越来越大,需要定期对AOF文件进行重写,压缩
  • load: 当redis重启时,可以加载AOF文件进行数据恢复
AOF持久化的方式
  • appendfsync always:主线程调用 write 执行写操作后,后台线程( aof_fsync 线程)立即会调用 fsync 函数同步 AOF 文件(刷盘),fsync 完成后线程返回,这样会严重降低 Redis 的性能(write + fsync)。
  • appendfsync everysec:主线程调用 write 执行写操作后立即返回,由后台线程( aof_fsync 线程)每秒钟调用 fsync 函数(系统调用)同步一次 AOF 文件(write+fsyncfsync间隔为 1 秒)
  • appendfsync no:主线程调用 write 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(write但不fsyncfsync 的时机由操作系统决定)

RDB比AOF优秀的地方

  • RDB文件是一个紧凑的二进制文件,占用空间小,传输速度快,适合做备份和灾难恢复
  • RDB文件恢复数据的速度比AOF快,因为只需要加载一次文件即可
  • RDB持久化对Redis服务器的性能影响较小,因为大部分工作由子进程完成

AOF比RDB优秀的地方

  • AOF文件可以实时或者近实时地记录Redis内存中的数据,因为它是每次写命令或者每秒钟同步一次。如果在同步之间发生故障,可能会丢失一部分数据,但是数据丢失的概率比RDB小。
  • AOF文件是一个文本文件,可以方便地查看和编辑。AOF文件中的命令是Redis协议格式的,可以直接用Redis客户端来执行。
  • AOF文件可以自动进行重写,以减少冗余命令和文件体积。重写过程不影响Redis服务器的正常服务,也不会丢失任何数据。

考虑角度

  • 数据的完整性
  • 数据恢复的速度
  • 磁盘的占用空间
  • 数据的可读性

具体的 建议:

  • 数据完整性要求不高,可以使用RDB或者是将AOF的同步频率设置为每秒一次
  • 如果要数据尽可能不丢失,可只使用

使用RDB做镜像全量持久化,AOF做增量持久化。RDB耗时比较严重,实时性不够好,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。

在redis示例重启时,会使用RDB持久化文件重新构建内存,再使用AOF重放近期的操作指令来实现完整的数据恢复。

过期数据的删除策略

  1. 惰性删除:只有在取key的时候才对数据进行过期检查。这样对CPU友好,但可能造成太多key没有被删除。
  2. 定期删除:每隔一段时间,抽取一批key进行过期检查。

redis采取惰性删除+定期删除的策略

redis的事务

redis提供的事务不是严格的事务,redis保证串行执行命令,但能保证全部执行;若其中有一条命令执行失败,此时不会回滚,而是继续执行下去

redis生成的问题

缓存穿透 缓存击穿 缓存雪崩
数据在cache是否存在 no no yes(但是过期了)
数据在DB是否存在 no yes yes

缓存穿透

大量不合理的key:缓存和数据库中都不存在。这导致大量请求直接达到了数据库上。

  1. 接口限流:根据用户或者IP对接口进行限流,对于异常频繁的访问采取黑名单机制
  2. 布隆过滤器:不存在就不存在;存在不一定存在

缓存击穿

请求的key为热点数据,数据不在缓存中,数据库中存在

  1. 延长过期时间
  2. 提前预热数据,将数据存入缓存中,设置合理的过期时间,保证在秒杀结束前,数据不会过期

缓存雪崩

大量缓存同时失效,大量请求访问数据库

  • 服务宕机
  1. 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
  2. 服务熔断请求限流
  • 大量缓存过期
  1. 多级缓存,例如本地缓存+Redis 缓存的组合,当 Redis 缓存出现问题时,还可以从本地缓存中获取到部分数据。
  2. 互斥锁
  3. 设置随机过期时间

针对热点缓存失效的情况:

  1. 设置不同的失效时间比如随机设置缓存的失效时间。
  2. 缓存永不失效(不太推荐,实用性太差)。
  3. 缓存预热,也就是在程序启动后或运行过程中,主动将热点数据加载到缓存中。

缓存预热如何实现?

常见的缓存预热方式有两种:

  1. 使用定时任务,比如 xxl-job,来定时触发缓存预热的逻辑,将数据库中的热点数据查询出来并存入缓存中。
  2. 使用消息队列,比如 Kafka,来异步地进行缓存预热,将数据库中的热点数据的主键或者 ID 发送到消息队列中,然后由缓存服务消费消息队列中的数据,根据主键或者 ID 查询数据库并更新缓存

分布式锁

redis的回滚机制

redis不支持事务

大概的意思是,作者不支持事务回滚的原因有以下两个:

  • 他认为 Redis 事务的执行时,错误通常都是编程错误造成的,这种错误通常只会出现在开发环境中,而很少会在实际的生产环境中出现,所以他认为没有必要为 Redis 开发事务回滚功能;
  • 不支持事务回滚是因为这种复杂的功能和 Redis 追求的简单高效的设计主旨不符合。

这里指的不支持事务的运行回滚是指 运行时错误的事务回滚

1
2
3
muti # 开始事务

EXEC #执行事务

主从数据同步

启动一台slave的时候,发送psycn命令给master,触发全量复制。slave将master的RDB写入本地磁盘,加载进内存

redis的分布式锁

缓存不一致问题

[常见的缓存更新策略剖析 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/86396877#:~:text=常见的缓存更新策略剖析 1 一、先删缓存再更新数据库 2 二、先更新数据库,再删缓存 3,三、先更新数据库,再更新缓存 4 四、read%2Fwrite through 缓存代理 5 五、写回)

百度后端 春招 24届一二三面_牛客网 (nowcoder.com)

数据库和缓存如何保证一致性? | 小林coding (xiaolincoding.com)


redis总结
http://example.com/2024/01/29/redis总结/
作者
Forrest
发布于
2024年1月29日
许可协议