Redis核心知识点(突出重点+深度细化)

Redis核心知识点(突出重点+深度细化)

一、高性能底层逻辑(Redis核心竞争力)

1. 纯内存存储(性能基石)

  • 核心优势:内存读写速度(约100ns级)远高于磁盘(ms级),Redis将所有数据驻留内存,彻底规避磁盘I/O瓶颈。
  • 细节 :内存数据并非无限制存储,需配合内存淘汰策略 (如LRU)和持久化机制(RDB/AOF)平衡性能与数据安全。
  • 场景:高频访问数据(如商品详情、用户会话)全内存存储,支撑每秒10万+TPS。

2. 单线程模型(并发处理精髓)

  • 核心设计 :主线程串行处理所有命令(网络I/O+数据操作),避免多线程的锁竞争线程切换开销(上下文切换成本约1-10μs)。
  • 关键细节
    • 仅核心命令执行单线程,Redis 6.0+引入多线程I/O (默认4线程)处理网络读写,进一步提升并发连接能力(通过io-threads配置)。
    • 单线程不卡顿的前提:命令执行时间极短(微秒级),若存在耗时命令(如KEYS *)会阻塞全库,需禁用或用SCAN替代。
  • 场景:高并发读场景(如秒杀库存查询),单线程无锁机制可高效处理。

3. IO多路复用(高并发连接支撑)

  • 核心机制 :通过epoll模型 (Linux默认)实现单线程同时监听数万客户端连接,事件驱动式处理I/O请求。

  • 细节对比

    模型 缺陷 epoll优势
    select 最多监听1024个连接,轮询效率低 无连接数限制,事件驱动(O(1)复杂度)
    poll 无连接数限制,但轮询效率低 仅处理触发事件的连接,无需遍历全量
  • 流程epoll_create创建实例 → epoll_ctl注册连接事件 → epoll_wait阻塞等待事件 → 处理触发的读写请求。

4. 优化的数据结构(操作效率保障)

Redis每种数据结构均为"场景化设计",底层优化直击性能痛点:

数据结构 底层实现 核心优化点 典型命令效率
字符串(String) 简单动态字符串(SDS) 预分配空间(减少内存重分配)、惰性释放(避免频繁回收)、O(1)获取长度 SET/GET:O(1)
哈希(Hash) 压缩列表→哈希表 小数据用压缩列表(紧凑存储),大数据自动转哈希表(O(1)查找) HGET:O(1)
有序集合(ZSet) 压缩列表→跳跃表 跳跃表通过多层指针实现O(logN)查找,支持范围查询(如排行榜Top10) ZADD/ZRANGE:O(logN)
列表(List) 双端链表→压缩列表 两端插入/删除O(1),支持阻塞操作(如消息队列BLPOP LPUSH/RPOP:O(1)
集合(Set) 整数集合→哈希表 整数元素用整数集合(紧凑存储),其他用哈希表(去重+O(1)查找) SADD/SISMEMBER:O(1)
  • 示例 :SDS预分配机制
    执行APPEND key "xyz"时,若当前剩余空间足够,直接拼接(O(1));否则按"当前长度*2"扩容,减少后续分配次数。

二、缓存三大核心问题(生产必避坑)

1. 缓存穿透(查不到的数据攻击)

  • 定义:请求查询"缓存+数据库均不存在的数据",导致每次请求穿透到数据库,可能压垮DB。
  • 原因:恶意攻击(伪造不存在的ID)、业务逻辑漏洞(如误查无效参数)。
  • 解决方案(细化实现)
    • 缓存空值 :数据库查不到时,缓存key→null(过期时间设短,如5分钟),避免重复穿透。

      java 复制代码
      // 伪代码
      Object data = db.query(id);
      if (data == null) {
          redis.set(id, null, 300, TimeUnit.SECONDS); // 缓存空值,5分钟过期
      } else {
          redis.set(id, data, 3600, TimeUnit.SECONDS);
      }
    • 布隆过滤器 :提前将所有有效ID存入布隆过滤器,请求先过过滤器,不存在则直接返回。

      • 优点:空间效率极高(100万ID约占12KB),查询O(1)。
      • 注意:存在误判率(可通过调整位数和哈希函数降低,如0.1%误判),需配合缓存空值兜底。

2. 缓存击穿(热点key失效瞬间雪崩)

  • 定义:某个热点key(如热门商品ID)过期瞬间,大量并发请求直接冲击数据库。
  • 原因:热点数据缓存过期,且并发量极高(如秒杀商品库存查询)。
  • 解决方案(细化实现)
    • 互斥锁 :缓存失效时,仅允许一个线程查DB并重建缓存,其他线程等待重试。

      java 复制代码
      // 伪代码:用SETNX实现互斥锁
      String lockKey = "lock:" + id;
      Boolean locked = redis.setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS); // 锁10秒过期
      if (locked) {
          try {
              Object data = db.query(id); // 查DB
              redis.set(id, data, 3600, TimeUnit.SECONDS); // 重建缓存
          } finally {
              redis.delete(lockKey); // 释放锁
          }
      } else {
          Thread.sleep(100); // 等待100ms后重试
          return queryCache(id); // 重新查缓存
      }
    • 热点数据永不过期 :缓存不设过期时间,通过异步更新(如消息队列)同步DB变更,避免过期瞬间冲击。

3. 缓存雪崩(大量key同时失效)

  • 定义:大量缓存key在同一时间过期,导致请求批量穿透到数据库,引发DB崩溃。
  • 原因:缓存过期时间设置过于集中(如全量设置1小时过期)。
  • 解决方案(细化实现)
    • 随机过期时间 :给每个key的过期时间加随机偏移(如1小时±10分钟),分散过期时间。

      java 复制代码
      int baseExpire = 3600; // 基础3600秒
      int random = new Random().nextInt(600); // 0-600秒随机
      redis.set(key, value, baseExpire + random, TimeUnit.SECONDS);
    • 二级缓存:本地缓存(如Caffeine)+ Redis,Redis失效时先查本地缓存,兜底防穿透。

三、持久化机制(数据不丢失的保障)

Redis是内存数据库,需通过持久化将数据落地磁盘,避免宕机丢失。核心有两种机制:

1. RDB(快照持久化)

  • 原理 :按配置时机(如save 60 10000:60秒内1万次写操作)触发,通过bgsavefork子进程生成全量数据快照(.rdb文件)。
  • 优点:文件小、恢复快(适合备份),fork子进程不阻塞主线程。
  • 缺点:快照间隔内数据可能丢失(如宕机),fork子进程时会短暂阻塞(内存越大阻塞越久)。
  • 适用场景:冷备(每天凌晨生成RDB备份)、数据容忍分钟级丢失的场景。

2. AOF(日志持久化)

  • 原理 :记录所有写命令(如SET key value)到.aof文件,重启时重放命令恢复数据。
  • 关键配置
    • appendfsync always:每条命令刷盘(最安全,性能最差);
    • appendfsync everysec:每秒刷盘(平衡安全与性能,默认);
    • appendfsync no:由OS决定刷盘(最快,数据丢失风险高)。
  • 优化 :AOF重写(bgrewriteaof)→ 合并冗余命令(如INCR key100次→SET key 100),减少文件体积。
  • 优点:数据丢失少(最多丢1秒),适合对数据安全性要求高的场景(如金融交易)。
  • 缺点:文件大、恢复慢。

3. 混合持久化(Redis 4.0+默认)

  • 原理:RDB+AOF结合,AOF文件头部存RDB快照,尾部存增量命令,兼顾恢复速度(RDB)和数据安全性(AOF)。

四、主从复制与高可用(集群核心)

1. 主从复制(读写分离+容灾)

  • 核心作用:主库(Master)写数据,从库(Slave)读数据,分担主库压力;主库宕机时从库可切换为主库。
  • 同步流程
    1. 全量同步:从库首次连接主库,主库生成RDB并发送,从库加载RDB初始化数据;
    2. 增量同步 :主库后续写命令通过复制缓冲区实时发送给从库,从库执行命令保持一致。
  • 关键细节
    • 主库用复制偏移量 (offset)记录同步进度,从库通过PSYNC命令请求增量数据;
    • 网络中断后,从库重连时通过偏移量+复制缓冲区(默认1MB)实现部分同步,避免全量重传。

2. 哨兵(Sentinel):自动故障转移

  • 功能:监控主从库状态,主库宕机时自动从从库中选新主库,并更新其他从库的主库地址。
  • 核心流程
    • 监控:每秒向所有节点发送PING,判断节点是否存活;
    • 选主:通过"主观下线+客观下线"判断主库故障,再按"从库优先级→复制偏移量→runid"选新主库;
    • 通知:更新客户端连接的主库地址。

3. 集群(Cluster):水平扩容

  • 核心设计 :将16384个哈希槽(slot)分配给多个节点,每个key通过CRC16(key) % 16384映射到对应槽,实现数据分片。
  • 扩容缩容 :通过cluster add-node/cluster del-node操作,迁移槽和数据(自动平衡),不中断服务。
  • 高可用:每个主节点至少1个从节点,主节点宕机时从节点自动切换为主节点。

五、事务与原子操作(数据一致性)

1. 事务

  • 命令MULTI(开启事务)→ 批量命令 → EXEC(执行)/DISCARD(放弃)。
  • 特性:批量命令串行执行(不被其他命令打断),但不支持回滚(错误命令仅当前命令失败,其他继续执行)。
  • 乐观锁WATCH key监控key,若事务执行前key被修改,事务取消(防止并发修改)。

2. 原子命令与Lua脚本

  • 原子命令 :如INCR(自增)、HSETNX(哈希表不存在时设置),单命令天然原子性,适合简单场景。

  • Lua脚本 :复杂逻辑(如"查+改+写")用Lua脚本包裹,通过EVAL执行,保证原子性(脚本内命令不可中断)。
    示例:库存扣减(防止超卖)

    lua 复制代码
    -- 若库存>0则扣减1,返回1;否则返回0
    local stock = redis.call('get', KEYS[1])
    if stock and tonumber(stock) > 0 then
        return redis.call('decr', KEYS[1])
    end
    return 0

总结

Redis的核心竞争力在于**"高性能+高可用+灵活的数据模型"**:

  • 底层通过"内存存储+单线程+epoll"支撑超高并发;
  • 缓存问题需针对性解决(穿透用布隆过滤器/空值,击穿用锁/永不过期,雪崩用随机过期);
  • 持久化(RDB/AOF)和集群(主从/哨兵/Cluster)保障数据安全和水平扩展;
  • 事务与Lua脚本确保复杂操作的原子性。

掌握这些知识点,可应对90%以上的Redis生产场景。

相关推荐
大佐不会说日语~7 小时前
Redis高可用架构演进面试笔记
redis·面试·架构
鼠鼠我捏,要死了捏9 小时前
Redis集群高可用与性能优化实战指南
redis·performance-optimization·high-availability
野蛮人6号10 小时前
黑马点评系列问题之p44实战篇商户查询缓存 jmeter如何整
java·redis·jmeter·黑马点评
hzk的学习笔记14 小时前
Redis 5.0中的 Stream是什么?
数据库·redis·缓存
Themberfue15 小时前
Redis ①⑦-分布式锁
数据库·redis·分布式·adb·缓存
就改了16 小时前
Redis Lua脚本语法详解
redis
Warren981 天前
Redis 八股面试题
java·数据库·redis·spring·缓存·面试·eclipse
茫茫人海一粒沙2 天前
如何用 Kafka + Redis + 线程池搭建高吞吐异步消息处理架构
redis·架构·kafka
是阿建吖!2 天前
【Redis】在Ubentu环境下安装Redis
数据库·redis·缓存