面试知识库

Redis数据结构 → 单线程 → 集群 追问链#

追问路径#

涉及知识点#

核心串联逻辑#

  1. 类型与编码:同一类型按数据量自动切换底层编码(如Hash小用listpack、大转hashtable),省内存又保性能
  2. ZSet用跳表:范围查询友好、实现比红黑树简单、便于并发,配合hashtable实现O(1)按成员查分值
  3. 单线程快的本质:瓶颈是网络IO不是CPU,纯内存+epoll已够快;6.0多线程只优化网络IO,命令执行仍单线程保原子性
  4. 高可用三段演进:主从(读扩展)→哨兵(自动故障转移)→Cluster(分片突破单机内存与写瓶颈)
  5. Cluster路由:CRC16(key)%16384定位槽,客户端缓存映射,错节点返回MOVED;多key需同槽用hash tag
  6. 代码示例
    # hash tag 强制多key落同一槽,才能用MGET/事务/Lua
    MSET {user:1001}:name Tom {user:1001}:age 20   # {}内相同→同槽
    # 渐进式遍历,避免KEYS阻塞
    SCAN 0 MATCH user:* COUNT 100
    bash

面试回答串联#

30秒速答#

“Redis五种基础类型底层是SDS、listpack、quicklist、跳表等,ZSet用跳表是因为范围查询友好且实现简单。单线程快是因为纯内存加epoll多路复用,瓶颈在IO不在CPU,6.0只把网络IO多线程化。高可用上主从复制做读扩展,哨兵做自动故障转移,Cluster用16384个槽分片做水平扩展,CRC16取模定位槽,错节点返回MOVED重定向。“

2分钟展开答#

“Redis有String、Hash、List、Set、ZSet五种基础类型,加上Bitmap、HyperLogLog、GEO、Stream扩展。底层会根据数据量自动切换编码,比如Hash元素少用listpack省内存、超阈值转hashtable。ZSet底层是跳表加哈希表,用跳表而不是红黑树是因为范围查询ZRANGE更友好、实现更简单、并发改造也容易,哈希表则提供O(1)按成员查分值。Redis单线程还快的原因是数据全在内存、单线程避免了锁和上下文切换、用epoll做IO多路复用、加上高效的数据结构,瓶颈其实在网络IO不在CPU。6.0引入多线程也只是把网络IO的读写和协议解析多线程化,命令执行仍是单线程保证原子性。单线程的风险是慢命令会阻塞所有请求,所以要用SCAN代替KEYS、用UNLINK异步删大Key。高可用是三段演进:主从复制做读写分离和数据冗余,首次全量同步靠主库bgsave生成RDB,之后增量靠repl_backlog环形缓冲按offset续传;哨兵在主从基础上做自动故障转移,多个哨兵确认主库客观下线后用Raft选出领头哨兵来选新主并通知客户端;数据量再大就上Cluster分片,把16384个槽分给各主节点,CRC16(key)对16384取模定位槽,客户端缓存槽映射、访问错节点会返回MOVED重定向,多key操作要求落同一个槽可以用hash tag强制。“

相关追问链#