运作
Redis 的内存模型¶
事实上,内存中有一块位置存储了 String 的字符内容,如上图中 dict 中其实存储的是指向 String 的指针,每个这个 String 指针会对应一个 timpstamp
redis 线程¶
核心执行流程是单线程的
为什么使用单线程¶
- 上下文切换的时间成本
- 同步机制(加锁等)会有一定的开销
- 节省内存
redis 的性能瓶颈在于 IO 而不是 CPU
为什么 redis 快¶
redis 可以达到 8 ~ 10w/s
- 内存数据库,内存访问快
- 数据结构设计得很高效
- IO 多路复用,网络IO操作中可以提高吞吐量
哪里用到了多线程¶
工作流程如下:
在 IO 多路复用模型中,还是主线程去监听(遍历)所有的 fd 事件,随后再将具体的读取和写回操作交给多个线程执行
- 当客户端发送请求时,I/O 线程从 Socket 读取数据并将其存储在 queryBuf 中。
- I/O 线程从客户端的 Socket 中读取数据。
- 将读取的数据存储到客户端的输入缓冲区(
queryBuf
)中
- 主线程从 queryBuf 中获取请求并执行相应的命令。
- 执行结果存储在 reply 中,然后由 I/O 线程将响应发送回客户端。
- I/O 线程从客户端的输出缓冲区(
reply
)中获取数据。 - 将数据通过 Socket 发送给客户端。
- I/O 线程从客户端的输出缓冲区(
Redis 持久化¶
为什么需要持久化¶
持久化就是将内存数据存入磁盘
- Redis 在很多场景下作为缓存使用,但如果碰到重启情况之后缓存都不在了,这样请求会一下都打到存储上
- Redis 本身也可以作为存储使用,这个时候对于数据保存的安全性要求较高
RDB 和 AOF 的本质区别是什么¶
RDB 是全量的二进制快照保存,而 AOF 则是追加日志文件进行记录
- 文件类型:RDB 生成的都是二进制文件(快照),AOF 生成的是文本文件(追加日志)
- 安全性:缓存宕机时,RDB 会损失较多的数据,AOF 则会根据配置的刷盘策略(比如1s刷一次)决定
- 文件恢复速度:由于 RDB 是二进制文件,所以其恢复速率比 AOF 更快
- 操作开销:如果以每一次的操作作为单位,RDB 每次的保存都是全量保存,而 AOF 刷盘是一次追加操作
RDB 和 AOF 选谁¶
- 如果能接受分钟级别的丢失,选 RDB(这也是官方的默认选择)
- 如果选择 AOF ,则开启每秒刷盘一次的 AOF
二者同时开启时,使用哪种载入策略¶
同时开启时,无论 AOF 日志是否丢失,都只会使用 AOF,因为既然选择一定要开启 AOF ,说明对于数据的可靠性要求较高,此时如果发生异常需要即时暴露出来进行处理
RDB 详解¶
RDB 开启¶
定时持久化¶
前一个参数表示每过多久检查一次;后一个参数表示这段时间内的更新数达到多少才能快照(这些命令不是需要手动执行的)
手动持久化¶
RDB 的写入方式¶
后台持久化时:
- Redis 首先调用 fork 开启一个子进程
- 子进程开始将所有数据写入到 临时 RDB 文件中
- 当子进程写入完成后,替换掉原有的 RDB 文件
这里的 fork 使用 copy on write ,并且注意到随后进行数据更新操作的必定是父进程(子进程不会接受命令)
- 在写入的过程中新来的数据是父进程新开了的内存接收的
- 复制的是快照一瞬间的数据
面试问题¶
RDB 的本质是什么¶
RDB 的本质是二进制形式的快照
如何开启 RDB¶
- 定时,使用后台持久化
- 主动命令 save / bgsave(实际生产中少)
RDB 对主流程有什么影响¶
- 阻塞式持久化时,由主进程进行快照保存,会阻塞主进程
- 后台持久化时,由 fork 出来的子进程来执行快照
- 特别地,当数据量比较大时,会导致 fork 子进程这个操作比较耗时,从而阻塞主进程
- 和阻塞相比,如果子进程执行拷贝时又有新的数据改写,会由主进程执行
AOF 详解¶
如何开启 AOF¶
找到 redis 配置文件 redis.conf
默认的配置为 appendonly no
,改为 yes 即可
刷盘策略¶
- always 每次请求都刷入 AOF
- everysec 每秒刷一次盘(崩溃时会丢失 1s 的数据)
- no 不主动刷盘,让操作系统自己刷(linux 一般是 30s 刷一次盘,这里是只从内核缓存中写入磁盘)
AOF 落盘¶
先写入缓冲,再根据策略刷盘
AOF 面试¶
AOF 重写是解决什么问题的¶
重写用于解决 AOF 不断膨胀的问题,随着命令越来越多,AOF 文件越来越大,但是记录的指令中存在指令的覆盖,此时前面的命令就没有记录的必要了。
简述 AOF 重写的流程¶
- 主进程 fork() 出来一个子进程,然后这个子进程读取 RedisDB 中的数据,以字符串的形式写入到新的 AOF 文件中
-
当新的 AOF 文件重建完毕,主进程会把重写缓冲区的内容追加到新的 AOF 文件中
注意,重写缓冲区专门为重写服务,普通缓冲区使用相应的刷盘策略进行刷盘。在重写的过程中,主进程会同时向普通缓冲区的重写缓冲区追加数据
AOF 对主流程有什么影响¶
- always 需要阻塞主线程,每次主线程都需要等待从缓冲区写入磁盘
- everysec 一般不会阻塞主线程,主线程会使用 fork 创建子线程刷盘
- no 依赖操作系统将缓冲区的内容写入磁盘