Redis 02

发布于:2025-04-02 ⋅ 阅读:(38) ⋅ 点赞:(0)

  今天是2025/04/01 20:13 day 16

总路线请移步主页Java大纲相关文章

今天进行Redis 3,4,5 个模块的归纳

首先是Redis的相关内容概括的思维导图


3. 持久化机制(深度解析)

3.1 RDB(快照)

  • 核心机制

    • 触发条件

      • 手动触发:SAVE(阻塞主线程)或BGSAVE(后台fork子进程生成快照)。

      • 自动触发:根据配置规则(如save 900 1表示900秒内至少1次修改)。

    • 文件生成:生成二进制文件dump.rdb,包含某一时刻的数据全集。

    • 内存优化:子进程通过写时复制(Copy-On-Write)技术避免全量内存拷贝。

  • 优缺点

    • 优点

      • 文件紧凑,恢复速度快。

      • 适合冷备和灾难恢复。

    • 缺点

      • 可能丢失最后一次快照后的数据(取决于触发频率)。

      • 大数据量时BGSAVE的fork操作可能阻塞主线程(内存越大阻塞时间越长)。

  • 配置优化

    # redis.conf
    dbfilename dump.rdb        # RDB文件名
    dir /var/lib/redis         # 存储路径
    stop-writes-on-bgsave-error yes  # 磁盘满时禁止写入
    rdbcompression yes         # 启用压缩

3.2 AOF(追加日志)

  • 核心机制

    • 日志记录:以文本格式记录所有写操作命令(如SETHSET)。

    • 重写机制:通过BGREWRITEAOF压缩日志,删除冗余命令(如多次INCR合并为最终值)。

    • 同步策略

      • appendfsync always:每次写操作同步到磁盘(数据最安全,性能最低)。

      • appendfsync everysec:每秒同步(默认,平衡安全与性能)。

      • appendfsync no:由操作系统决定(性能最高,可能丢失最多数据)。

  • 优缺点

    • 优点:数据丢失风险低(最多丢失1秒数据)。

    • 缺点

      • 文件体积大,恢复速度慢。

      • 频繁写入可能影响性能(尤其是always模式)。

  • 配置优化

    # redis.conf
    appendonly yes             # 启用AOF
    appendfilename "appendonly.aof"
    auto-aof-rewrite-percentage 100  # 文件增长100%后触发重写
    auto-aof-rewrite-min-size 64mb   # 最小重写文件大小

3.3 混合持久化(Redis 4.0+)

  • 工作机制

    • 快照数据(RDB格式) + 增量AOF日志,保存在同一个AOF文件中。

    • 重启时先加载RDB快照,再重放后续AOF命令。

  • 优势

    • 结合RDB的快速恢复和AOF的低数据丢失风险。

    • AOF文件可读性增强(RDB头部 + 文本日志)。

  • 启用方式

    aof-use-rdb-preamble yes  # 在redis.conf中配置

4. 高可用与集群(深度解析)

4.1 主从复制

  • 核心流程

    1. 全量同步

    • Slave发送PSYNC命令请求同步。

    • Master fork子进程生成RDB文件并发送给Slave。

    • Slave清空旧数据,加载RDB文件。

    1. 增量同步

    • Master将后续写命令存入复制缓冲区(Replication Buffer)。

    • Slave持续接收并执行缓冲区中的命令。

  • 配置示例

    # Slave节点配置
    replicaof 192.168.1.100 6379  # 指定Master地址
    replica-read-only yes         # Slave只读
  • 常见问题

    • 复制延迟:网络波动或Master写入量过大导致缓冲区溢出(需监控repl_backlog)。

    • 脑裂问题:网络分区时出现多个Master(需结合哨兵解决)。


4.2 哨兵(Sentinel)

  • 核心功能

    • 监控:定期检查Master/Slave健康状态。

    • 故障转移:Master宕机时,自动选举新Master。

    • 通知:通过Pub/Sub频道向客户端发送故障事件。

  • 选举机制

    1. Sentinel通过Raft协议选举Leader。

    2. Leader Sentinel从Slave中选出新Master(优先级 + 复制偏移量)。

  • 配置示例

    # sentinel.conf
    sentinel monitor mymaster 192.168.1.100 6379 2  # 监控名为mymaster的集群,2表示至少2个Sentinel同意故障判定
    sentinel down-after-milliseconds mymaster 5000   # 5秒无响应判定为宕机
    sentinel failover-timeout mymaster 60000         # 故障转移超时时间

4.3 Cluster集群

  • 数据分片

    • 哈希槽分配:16384个槽,通过CRC16(key) % 16384计算所属槽位。

    • 节点管理:每个节点负责部分槽位,支持动态迁移(CLUSTER ADDSLOTS)。

  • 节点通信

    • Gossip协议:节点间交换槽位、状态信息,最终一致性。

    • 重定向机制:客户端访问错误节点时,返回MOVEDASK错误引导重试。

  • 故障转移

    • 从节点通过选举升级为主节点(类似哨兵机制)。

    • 集群需至少包含3主3从以保证高可用。

  • 操作命令

    CLUSTER NODES                  # 查看集群节点信息
    CLUSTER FAILOVER [FORCE]       # 手动触发故障转移
    CLUSTER RESET HARD/SOFT        # 重置集群节点

5. 事务与Lua脚本(深度解析)

5.1 事务

  • 执行流程

    1. MULTI开启事务。

    2. 缓存命令(命令不会立即执行)。

    3. EXEC提交事务(原子性执行所有命令)。

    4. DISCARD取消事务。

  • 特性与限制

    • 非原子性:单条命令原子执行,但事务可能部分失败(如语法错误)。

    • 无回滚机制:需开发者自行处理错误(如通过WATCH实现乐观锁)。

  • 乐观锁示例

    WATCH balance               # 监控balance键
    MULTI
    DECRBY balance 100         # 扣减余额
    EXEC                       # 如果balance被其他客户端修改,此处返回nil

5.2 Lua脚本

  • 核心优势

    • 原子性:脚本执行期间不会被其他命令打断。

    • 减少网络开销:复杂逻辑单次提交,避免多次RTT(Round-Trip Time)。

  • 典型场景

    • 分布式锁续期

      -- KEYS[1]=锁名称,ARGV[1]=线程标识,ARGV[2]=过期时间
      if redis.call("GET", KEYS[1]) == ARGV[1] then
          return redis.call("EXPIRE", KEYS[1], ARGV[2])
      else
          return 0
      end
    • 限流算法(令牌桶)

      -- KEYS[1]=限流key,ARGV[1]=令牌容量,ARGV[2]=填充速率(秒)
      local tokens = tonumber(redis.call("HGET", KEYS[1], "tokens") or ARGV[1])
      local last_time = tonumber(redis.call("HGET", KEYS[1], "last_time") or os.time())
      local now = os.time()
      local new_tokens = math.min(ARGV[1], tokens + (now - last_time) * ARGV[2])
      if new_tokens < 1 then
          return 0  # 无可用令牌
      else
          redis.call("HSET", KEYS[1], "tokens", new_tokens - 1)
          redis.call("HSET", KEYS[1], "last_time", now)
          return 1
      end
      
  • 注意事项

    • 脚本复杂度:避免长耗时操作(如KEYS命令),防止阻塞主线程。

    • 沙盒安全:Lua脚本无法直接调用系统命令或文件操作。



网站公告

今日签到

点亮在社区的每一天
去签到