Redis随手记(二)原理篇

date
Feb 13, 2021
slug
redis-fundamentals
status
Published
tags
Programming
Redis
summary
type
Page
Year
2021

Redis是个单线程程序

  • redis所有的数据都在内存中, 所有运算都是内存级别的运算
    • 因此对于时间复杂度为O(n)的指令, 需要小心使用redis, 否则会造成redis卡顿
  • redis使用非阻塞IO
  • 使用事件轮询(a.k.a 多路复用)来获取剩余数据
    • 最简单的事件轮询API是select
      • notion image
  • 指令队列
    • redis为每个客户端socket都关联一个指令队列
    • 客户端的指令通过队列来排队进行顺序处理, 先到先服务
  • 响应队列
    • redis为每个客户端socket都关联一个响应队列
    • redis服务器通过响应队列将指令的返回结果回复给客户端
    • 如果队列为空, 则目前不需要write, 会将当前客户端描述符从write_fds中移出来
      • 避免select系统调用立即返回写
  • 定时任务
    • redis的定时任务会记录在MinHeap上
      • 最快要执行的任务排在上方
    • 在每个循环周期里redis都会对最小堆里已经到时间点的任务进行处理
      • 处理完后将下一个最快要执行的任务的所需时间记录下来
        • 这个时间就是select系统调用中的timeout参数

通信协议

  • RESP (short for Redis Serialization Protocol)
    • 将传输的结构数据分为5种最小单元类型
      • 单行字符串1以“+”符号开头
      • 多行字符串以“$"开头, 后面跟字符串长度
        • $11\r\nhello world\r\n
        • $-1\r\n -> 代表NULL
        • $0\r\n\r\n -> 代表空字符串
      • 整数值以“:”符号开头, 后面跟整数的字符串形式
      • 错误信息以“-”符号开头
      • 数组以“*”开头, 后跟数组的长度
  • Client -> Server
    • 发送指令只有一种格式, 多行字符串数据
  • Server -> Client
    • 包含五种格式

持久化

  • 有两种, Snapshot是全量备份, AOF log是增量备份
  • snapshot
    • 内存快照必须使用文件IO操作, 但是文件IO操作不能使用多路复用API
    • 为了不阻塞线上业务, redis使用Multiprocessing Copy-On-Write
      • 在持久化的时候, redis调用gblic函数fork产生一个子进程
        • 父进程继续处理线上业务, 子进程负责持久化
          • 子进程不会修改现有的内存数据结构, 只是对数据结构进行遍历读取, 然后序列化写到磁盘中
          • 父进程持续服务客户端请求, 对内存数据结构进行不间断的修改
            • 此时使用COW, 当父进程需要对数据段某页进行修改时, 就会复制一份共享页面出来, 父进程对其进行修改, 子进程相应的页面没有变化
  • AOF log
    • 记录的是Redis服务器顺序指令序列
      • AOF log只记录对内存进行修改的指令记录
      • 这样, 通过对一个空的redis实例replay, 可以恢复redis当前实例的内存数据结构的状态
      • 当redis收到客户端修改指令时, 先进行参数校验、逻辑处理, 再将此指令存放到log里, 是属于先执行再存盘;
        • 与leveldb, hbase相反
    • AOF重写
      • redis提供了bgrewriteaof指令
        • 原理是fork一个子进程对内存进行遍历, 转换成一系列Redis操作指令, 序列化到新的AOF log file
          • 序列化完毕后再将此操作期间发生的增量AOF log 追加到新的log file中
            • 追加完毕后立即代替旧的AOF log file
    • fsync
      • AOF log以文件形式存在, 因此当程序对AOF log file进行写操作时, 实际上是将内容写到了内核为文件描述符分配的一个内存缓存中, 然后内核会将异步地将数据刷回到磁盘中
      • 强制将在内核中的AOF log刷回到磁盘的AOF log file中, 实际生产环境中一秒一次的频率比较好

管道

  • redis的管道本质上是改变客户端读/写顺序以更好地使用read/wirte buffer, 从而达到
    • 减少远程通信次数
    • 减少read/write的等待数据到来 /等待buffer清空以继续写入的耗时

© wongchihaul 2021 - 2022