个人Redis八股

71 阅读3分钟

Redis

数据类型

String字符串:因为C语言字符串的限制(没有扩容机制,获取长度速度太慢,特殊字符无法处理)

List链表:双向链表

Hash哈希表:拉链法

Set集合:1.普通集合(利用Hash) 2.整数集合(数组实现,所以添加扩容,删除缩容,查找二分)

ZSet有序集合:跳表

跳表:
    构建:随机n/2作为一级索引,n/4作为二级索引
    插入:1/2概率无索引,1/4概率为一级索引,1/8概率为二级索引
利用redis实现微博热搜TopK
    1. Hash哈希表,键存储热搜标题,值存储热度,排序,选取TopK,复杂度O(nlogn)
    2. Zset,复杂度O(k)

缓存穿透

查询大量不存在的数据

解决方案:

  1. 空结果缓存
  2. 布隆过滤器

缓存击穿

热点请求的key过期了,并发请求压垮数据库

解决方案:

  1. 互斥锁(强一致性、性能差)
  2. 逻辑过期(高可用、性能优、不能保证数据绝对一致)

缓存雪崩

同一时段大量缓存key同时失效或者Redis宕机,导致大量请求到达数据库

解决方案:

  1. 给不同的Key的TTL添加随机值
  2. 利用Redis集群提高服务的可用性(哨兵模式、集群模式)
  3. 给缓存业务添加降级限流策略(nginx, gateway)
  4. 给业务添加多级缓存

注:降级限流策略可以作为缓存穿透、缓存击穿、缓存雪崩的保底策略。

双写一致性

当修改了数据库的数据,同时更新缓存数据,缓存数据和数据库的数据要保持一致

延迟双删

删除缓存 -> 操作数据库 -> 延时删除缓存
无法强一致性
为什么要延迟?
    数据库是主从模式,等待数据同步到从节点

分布式锁

强一致性,性能低
缓存的数据一般是读多写少
添加共享锁(读)与排他锁(写)

异步通知

异步通知保证数据的最终一致性
写入数据库 -> 发布MQ消息 -> 监听MQ消息 -> 更新缓存

持久化

RDB: Redis数据备份文件

原理:
    开启子进程,子进程共享主进程内存数据(页表),将数据写入RDB文件
    copy-on-write解决脏写:
        - 当主进程执行读操作,访问共享内存
        - 当主进程执行写操作,拷贝一份数据,执行写操作

AOF: 记录每一个写命令,默认关闭

Always:
    同步刷盘,性能影响大,可靠性高
everysec:
    每秒刷盘,性能适中,可能丢1s数据
no:
    操作系统自动控制,性能最好,可能丢大量的数据
    
通过设置bgrewriteaof可以重写AOF,只保留最后一次写操作

数据过期策略

惰性删除:需要key的时候检查,如果过期就删除。CPU友好,内存不友好

定期删除:每隔一段时间检查,删除过期的key

Redis过期策略是这两种方法配合使用

数据淘汰策略

noeviction:不淘汰任何key,满了不允许写入

volatile-ttl:对设置了TTL的key,淘汰剩余TTL最小的key

allkeys-random: 对全体的key进行随机淘汰

volatile-random:对设置了TTL的key,随机进行淘汰

allkeys-lru:对全体key,基于LRU算法进行淘汰

volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰

allkeys-lfu:对全体key,基于LFU算法进行淘汰

volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰

选择方法:

0. 优先使用allkeys-lru
1. 数据访问频率差别不大,没有明显的冷热数据,allkeys-random
2. 置顶需求,置顶数据不设置过期时间,volatile-lru
3. 短时高频访问,allkeys-lfu、volatile-lfu

分布式锁

setnx

主从复制

主从全量同步:

主从增量同步:

哨兵模式

  • 监控
  • 自动故障恢复:选一个slave提升为master
  • 服务发现来源

分片集群