Redis 面试知识点提纲

219 阅读3分钟

1. 数据类型

1.1 字符串SDS

struct sdshdr {
  //字符串末尾为一个空字节
  int len;
  //空间预分配:每一次扩容时,如果小于1M就分配len大小的空间给free,大于1M就分配1M
  //惰性空间释放:截断时,不释放buf空间,将空白的交给free
  int free;
  //buf保存二进制数据,二进制安全
  char[] buf;
}

1.2 链表

列表键的底层实现之一,此外,发布订阅,慢查询,监视器也会使用链表。

Quickest:压缩列表+指针。

1.3 字典

Redis的字典由两个哈希表组成,采用渐进式rehash

typedef struct dict {
  //针对不同类型的键值对,为创建多态字典使用
  dictType *type;
  void *privdata;
  //两个哈希表,用于渐进式rehash
  dictht ht[2];
  int trehashidx;//-1表示没有rehash
}

typedef struct dictht {
  dictEntry **table;//指向哈希节点
  unsigned long size;//表大小
  unsigned long sizemask;//用于计算索引值,size-1
  unsigned long used;//已有节点数量
}

typedef struct dictEntry {
  void *key;
  union {
    void *val;
    uint64_t u64;
    int64_t s64;
  }
  struct dictEntry *next;//解决哈希冲突
}

1.4 跳表

跳表层高为1-32之间的随机数。

1.5 整数集合

按照从小到大有序排列,且保证不重复。

typedef struct intset {
  uint32_t encoding;//有升级机制
  uint32_t length;
  int8_t contents[];
}

1.6 压缩列表

存个数,尾部,每个节点纪录上个节点的长度。

2. 单机数据库

2.1 过期设置

  1. setnx适用于字符串,赋值+设置过期时间;
  2. 通过过期字典来维护过期数据,可以采取定期删除与惰性删除相结合的方式,定期取一部分,判断是否需要删除,用的时候惰性判断;
  3. RDB存储,写入或者AOF重写都会检查过期键,AOF存储不会检查;

2.2 持久化

  1. RDB以压缩的二进制文件的方式快照存储,恢复迅速,但是会有间隔不一致性,快照存储过程中运用了多线程的cow技术;
  2. AOF以指令追加的形式即时存储,恢复慢,一致性更高,但是也会有丢失,因为AOF是先存储在内存中的。

2.3 主从同步

  1. 完整同步过程:从服务器发送SYNC命令,主服务器发送最新的RDB文件,并且发送缓存区保存的写命令;
  2. 部分同步过程:维护一个偏移量与一个循环队列;
  3. 无盘复制:主库不进行文件IO,而是在遍历过程中将快照直接同步给从库,从库存在自己的硬盘上,之后刷进自己的内存;
  4. 心跳机制每秒向主服务器发一个偏移量,检测服务器连接状态以及丢失情况。

2.4 哨兵模式

  1. 选举,拜占庭容错,投票选举;
  2. 选出新的主库;
  3. 哨兵机制也不能保证完全的一致性,除非牺牲可用性。

2.5 节点与分槽

  1. 节点只能用0号数据库;
  2. 节点靠位图记录自己分到的槽;
  3. slot数组维护每一个槽指向的节点对应的数据结构的指针;
  4. 节点会用跳跃表保存槽与键之间的关系;
  5. 槽迁移与ASK错误重定位;
  6. MOVED错误是将请求定向槽对应的节点;

2.6 缓存问题

缓存穿透;缓存击穿;缓存雪崩。

2.7 线程模型(略)

3. 应用设计

3.1 分布式锁

set key val ex time nx #实现原子性操作
#val可以设计为random,但是要注意,判断val是否符合与del锁不是原子性的,要用lua脚本
#分布式锁保证一致性是靠redlock算法,过半更新原则

3.2 限流算法

  1. 漏斗算法
  2. 令牌桶算法