redis rdb 和 aof 机制

rdb: redis database

在指定时间内将内存中的数据集快照写入磁盘,实际操作过程就是一个 fork 一个子进程,先将数据写入临时文件,写入成功 后再替换之前的文件,用二进制压缩存储。

为什么Redis进行RDB持久化数据时,新起一个进程而不是在原进程中起一个线程来持久化数据

答案:主要是出于Redis性能的考虑,(1)Redis RDB持久化机制会阻塞主进程,这样主进程就无法响应客户端请求。(2)我们知道Redis对客户端响应请求的工作模型是单进程和单线程的,如果在主进程内启动一个线程,这样会造成对数据的竞争条件,为了避免使用锁降低性能。基于以上两点这就是为什么Redis通过启动一个进程来执行RDB了

优点:

  1. 整个redis 数据库只包含一个文件 dump.rdb, 方便持久化
  2. 容灾性 好,方便备份
  3. 性能最大化,子进程执行 写操作,主进程继续处理,所以 IO最大化,单独使用子进程处理持久化,主进程无IO操作,保证redis 高性能
  4. 数据量比较大 比 AOF 启动效率要更高
AOF 原理

缺点:

1. AOF 文件比 RDB文件大,恢复速度慢
2. 数据集大的时候 ,比 rdb启动效率低
3. 运行效率没RDB 高

优点:

  1. 以文本的方式写入命令,可以打开文件看详细的操作记录
  2. 比较实时,
  3. 策略:
    1. 每秒同步
    2. 每修改同步
    3. 不同步

==子进程只执行保存操作(只保存 开始 到 子进程触发保存时间点的数据),不接受客户端的请求。即:在子进程执行持久化保存数据的时候,来自客户端的新数据子进程不会保存==

redis 为什么单线程这么快

redis 持久化可以 fork一个多进程来处理 【不一定严格说是单线程】

  1. redis 纯内存操作
  2. 单线程处理,没有线程上下文切换的代价
  3. redis 实现了一个队列, 通过一个事件循环, epoll 监听多个 文件描述符,注册个 回调进去,如果 有IO 事件了,就出发回调 执行。 【reactor模式】
    1. redis 网络事件处理器 是 一个单线程的, file event handler

https://gitee.com/workingonescape/typora_images/raw/master/image-20210917160156402.png

多个 socket 并发产生不同的事件,多路复用程序要监听多个 socket,会先将 socket 放入一个队列,每次从队列有序,同步取出一个 socket 给事件分派器,事件分派器把 socket 给对应的事件处理器。 然后 socket 处理完成后, IO 多路复用 程序才将队列中的下一个 socket 给事件分派器。 文件时间分派器 会根据每个 socket 当前的事件, 来选择对应的事件处理器来处理。

https://images2018.cnblogs.com/blog/463402/201807/463402-20180730224920013-771808979.png

https://upload-images.jianshu.io/upload_images/16056711-d65d7b837511aedf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/876/format/webp

https://upload-images.jianshu.io/upload_images/16056711-010ea11b5575f352.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/942/format/webp

多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。对于文件来讲,就是监听一堆文件,某个文件写满则返回。对于redis来讲,就是用了上述技术去监听多个连接,当连接完成写入的时候,会监听到并返回:)

redis 过期键删除策略

  • 惰性删除
    • get 的时候再删除
  • 定期删除
    • 过段时间删除

redis 同时使用2种策略

redis 分布式锁 如何实现

  1. redis 高可用
  2. setnx + lua脚本 , 如果key 存在就获取不到锁
  3. 利用lua脚本 保证多个 redis 操作的原子性
  4. 考虑锁过期,需要用一个看门狗机制,定时任务定时去监听是否需要续约
  5. 同时还要考虑 redis 节点挂掉之后 是否需要采用红锁的方式, 向 N/2 + 1 个节点申请锁, 都申请到了才证明锁获取从, 这样就算某个redis 节点挂掉,锁也不能被其他客户端获取。

红锁

分布式锁,当我们请求一个分布式锁的时候,成功了,但是这时候slave还没有复制我们的锁,masterDown了,我们的应用继续请求锁的时候,会从继任了master的原slave上申请,也会成功。

这就会导致,同一个锁被获取了不止一次。

  1. 只有在大多数节点上获取到了锁,而且总的获取时间小于锁的超时时间的情况下,认为锁获取成功了。