画布 1
Redis 内存
  内存消耗
    主进程内存消耗
      内存消耗统计
        used_memory Redis 分配器（allocator分配的内存总量，也就是内部存储的所有数据内存占用量-实际上等于被实际使用的不包含内存碎片的物理内存和物理内存）
          自身内存
          对象内存
            key
              string
            value
              string
                bimap
                hyperloglog
              list
              hash
              set
              zset
                geo
          缓冲内存
            输入缓冲区
              每个客户端有一个，无法控制大小，最多 1g
            输出缓冲区
              客户端 buffer
                normal 客户端
                  client-output-buffer-limit normal 0 0 0 没有硬限制和软限制，不会自动关闭连接
                  提防 monitory 命令，导致镜像输出
                replica 客户端
                  每个 client 独占一个 connection，一个 buffer
                  client-output-buffer-limit replica 256mb 64mb 60，256mb 是硬限制，只要一到达连接就关闭。64mb是软限制，只要达到并持续 60s，则连接被关闭。
                pubsub 客户端
                  可能 client 和 server 之间只有一个 per each 的 connection 和 buffer。
                  client-output-buffer-limit pubsub 256mb 64mb 60
                解决方案
                  maxclients
                  调整 client-output-buffer-limit
              复制积压缓冲区（repli-backlog）
                所有的从节点共用一个复制积压缓冲区，这个复制积压缓冲区还可以被重用
                大小默认只有 1mb，可以调整到 100mb。这样有了更大的应付网络闪断的内存余量。
              AOF 缓冲区
                这部分无法被定制，如果 buffer 满了可能阻塞全流程
        used_memory_human 以可读的形式返回的 used_memory
        used_memory_rss 以操作系统角度显示 Redis 进程占用的物理内存总量
          used_memory_rss -used_memory = 内存碎片（memory fragmentation）
            凡是分配 fixed-size chunk 的 allocator 都会有内存碎片问题
            Redis 使用 jemalloc
              小、大、巨大
            容易引起内存碎片的操作
              频繁更新（使 value 忽短忽长）
              大批键过期（被删除）而内存无法被重用
              解决方案
                利用集群方案（Sentinel/Redis Cluster）切换主从后，安全重启有内存碎片的机器
                value 尽量设计成定长的-很难做到
        used_memory_peak 内存使用的最大值
used_memory_peak_human 以可读的格式返回的 used_memory_peak
        used_memory_lua lua 引擎锁消耗的内存大小
used_memory_lua_human 以可读的格式返回的 used_memory_lua
        mem_fragmentation_ratio used_memory_rss/used_memory 的比值，这个值越高，物理内存碎片越高-有时候和内存页对齐有关。这个比值越小，证明有很多内存被调度到了 swap 空间里。
    子进程内存消耗
      AOF/RDB 重写时会导致子进程内存消耗
        COW 可以规避一定的内存消耗，但是发生写时复制的内存是以页为单位的。THP 会造成大页复制。
          先触发 swap
          再被 OOM Killer 杀掉
          解决方案
            THP 是另一种内存碎片
            禁用 THP
            vm.overcommit_memory=1
  内存管理
    内存管理的上限是 maxmemory，这个阈值是为了保护 memory exhausted，触发各种 policy 准备的 - 缓存场景下特别重要。
    config set maxmemory
    内存回收
      删除 expired keys
        单线程架构下维护一个定时任务
          1s 运行 10次
          基于采样和反馈启动和暂停
      执行任何命令前，都要检查 maxmemory， 触发maxmemory-policy。可以主动触发内存回收。
        这也就意味着不设置 expire 也能区分出 lru 的键来。
在缓存场景下特别重要，因为限制最少，但也最危险。
        noeviction：默认策略。拒绝写入任何数据而报错。
        volatile-lru：根据 LRU 算法删除设置了 expire 的键，直到腾出空间为止。如果没有可删除的对象（了），回退到 noeviction。
        allkeys-lru：对全 key 进行 lru 删除，直到腾出空间为止，这也意味着 Redis 可以当做准成的 lru cache 用。
        volatile-random：随机删除过期键，直到腾出空间为止。
        volatile-ttl：根据键值对的 ttl 属性，删除最近将过期的数据。如果（要有 expire 才有 ttl）没有，回退到 noeviction。