1、单线程的为什么快?

    1. 纯内存操作
    2. 基于非阻塞的IO多路复用
    3. 避免了多线程下的频繁上下文切换带来的性能问题

    2、redis分布式锁
    setnx (set if not exist) return 0 失败;return 1成功;

    3、过期key的删除策略

    1. 惰性过期:每次用的时候检查是否过期,可能造成积攒大量无用key,造成内存溢出
    2. 定期过期:每隔一段时间自动将过期的key删除, 可以缓解服务器内存和cpu的压力,但是要合理设置操作的执行时长和操作频率
    3. 定时过期:内部创建定时器,影响性能

    4、redis的持久化机制

    1. RDB:Redis DataBase将每一时刻的内存快照,以二进制的方式写入磁盘
      1. 手动触发
        1. save:会使redis处于阻塞状态,直到RDB持久化结束
        2. bgsave:fork出子进程进行持久化,主进程只有短暂的阻塞 (关键技术:copy on write,防止子进程读取到脏数据 )
      2. 自动触发
        1. save m n :在m秒内,如果有n个键发生改变,则触发持久化
        2. flushall:
        3. 主从同步:全量同步的时候会触发bgsave命令,方便持久化

    优点:fork子进程进行持久化,效率高,不会阻塞主进程
    缺点:数据安全性较低,会发生数据丢失;数据集较大时,会占用较大cpu资源;

    1. AOF :append only file 以日志的形式记录服务器处理的每一个写、删除操作,再调操作系统命令将日志文件进程刷盘

    同步策略:
    每秒同步
    每修改同步
    不同步
    优点:数据安全
    缺点:AOF文件比RDB大,恢复速度慢;数据集大的时候,比rdb启动效率低

    如果RDB和AOF都开启,默认使用AOF

    5、集群方案

    1. 主从
    2. 哨兵
    3. redis cluster 服务端分片
    4. redis sharding 客户端进行分片

    6、数据结构

    1. 字符串
    2. 哈希表:存储对象
    3. 列表:可以当做栈或队列
    4. 集合:元素不能重复
    5. 有序集合:可以设置顺序 ,score,设置顺序

    7、布隆过滤器
    作用: 用于判断元素在集合中是否存在,可以当做缓存的索引,用来保存缓存服务器,防止缓存击穿
    BloomFilter 是由一个固定大小的二进制向量或者位图(bitmap)和一系列映射函数组成的。
    优点:速度快,占用内存小;可以表示全集;
    缺点:可能误判为存在(存在Hash冲突);删除元素比较困难;

    8、常见的缓存淘汰算法

    1. FIFO(先进先出)
    2. LRU(最近最少使用)
    3. LFU(最不经常使用):在一段时间内,缓存数据被使用次数最少的会被淘汰

    9、什么事缓存穿透、缓存击穿、缓存雪崩
    问题:缓存穿透:缓存中查不到,数据库中也查不到,容易被攻击
    解决方案:

    1. 参数合法性校验
    2. 将数据库中没有查到结果的数据也写入到缓存,但是需要防止redis被撑满,需要设置过期时间较短
    3. 布隆过滤器

    问题:缓存击穿:缓存中没有,数据库中有。可能数据key过期或者正在保存redis数据。问题在于重新写入缓存需要一定时间
    解决方案:

    1. 设置热点缓存永不过期,定期重建缓存
    2. 数据库写入到缓存的时候,防止并发,添加锁

    问题:缓存雪崩:由于缓存失效,缓存大面积没有,瞬间进入数据库
    解决方案:

    1. 把缓存的失效时间分散,在原有的统一失效时间的基础上,增加随机值
    2. 将热点数据设置永不过期

    10、redis事务实现
    MULTI 开启事务——》
    命令入队——》
    EXEC 执行事务(不支持回滚机制,但是会检查每一个事务中的命令是否错误,不支持运行时错误)

    11、如果保证redis与数据库的数据一致性
    数据更新的时候, 先删缓存,再写数据库?
    解决方案:

    1. 延时双删(先删缓存,再删数据库,等待一小会,再次删除缓存)
    2. 先修改缓存为特殊值,客户端读取到特殊值后,等待一小会再重试

    先写数据库,再删缓存?
    总结:没有啥好办法