Redis面试总结一

Redis为什么这么快

  1. 完全基于内存
  2. 数据结构简单
  3. 采用单线程,避免了不必要的上下文切换和竞争条件,不会因为锁的问题,造成额外的开销
  4. 使用IO多路复用,非阻塞IO
    - 新版Redis开始采用多线程
  5. redis直接构建了自己的VM机制

数据类型

  1. Redis 有哪些数据类型
    - String--适合最简单的k-v存储,类似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。
    - Hash--一般key为ID或者唯一标示,value对应的就是详情了。如商品详情,个人信息详情,新闻详情等。
    - List--因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。
    - Set--可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set最牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人共同的好友等
    - Sorted set-- set的增强版本,增加了一个score参数,自动会根据score的值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据
  2. 使用场景
    - 计数器:可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量
    - 缓存:将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率
    - 消息队列(发布/订阅功能):List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。
    - 分布式锁实现:在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现

持久化

  1. 什么是Redis持久化
    - 持久化就是把内存中的数据写入到磁盘中去,防止服务器宕机了内存数据丢失
  2. Redis提供的持久化机制有哪些
    • RDB:这个是默认的持久化方式,按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件是dump.rdb,通过配置文件中的save参数来定义快照的周期
      • 优点
        1. 只有一个dump.rdb文件
        2. 容灾性好,一个文件可以保存到安全的磁盘上
        3. 性能最大化:fork子进程来完成写操作,让主进程继续处理命令,实现IO最大化,使用单独子进程来进行持久化,主进程不会进行任何的IO操作,保证了redis的性能
        4. 在应对大数据集合的时候,表现好于AOF
      • 缺点
        1. 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
    • AOF:持久化
      - AOF持久化是将redis每次执行的命令单独的记录到文件汇总,当重启redis的时候,会将重新通过日志的记录来恢复文件
      - 当两种持久化方法都开启的时候,数据恢复Redis会优先选择AOF恢复
      • 优点
        1. 数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次
          1. 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
          2. AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))
      • 缺点:
        1. AOF文件比RDB文件要大,恢复较慢
        2. 数据集大的时候,启动较慢
    • 如何选择
      - 如果非常关心数据,但是可以忍受数分钟以内的数据丢失,可以使用RDB
      - 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式
      - 如果想达到足以媲美PostgreSQL的数据安全性,你应该同时使用两种持久化功能。在这种情况下,当 Redis 重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
    • redis 持久化数据和缓存如何扩容
      - 如果是缓存使用,使用哈希一致性实现动态扩容
      - 如果是用于持久化存储,必须固定好key-to-node的映射关系,节点数量一旦确定就不能变化

过期删除策略

   1. 过期键的删除策略
          - 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量
          - 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存
          - 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
   2. Redis key的过期时间和永久有效分别怎么设置
          - expire  过期时间
          - persist  永久有效

内存相关

   1. redis的内存淘汰策略
          - Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。
         - 全局的键空间选择性的移除
               - Noeviction:当内存不足以容纳新的写入数据的时候,新的写入操作会报错
               - Alleys-lru:当内存不足以容纳新的数据的时候,在键空间中会删除最近很少使用的key
               - Alleys-random:当内存不足的时候,随机移除某个key
      - 设置过期时间的键空间选择性移除
            - **volatile-lru**:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
            - **volatile-random:**当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
            - **volatile-ttl:**当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
   2. 如何做内存优化
          - 充分利用hash, list,sorted set,set等集合类型数据,通常很小的key-value可以用更紧凑的方式比如散列表进行存储

线程模型

   1. Redis 线程模型
         - redis 基于 reactor的模式开发了网络事件处理器,这个处理器被称为文件事件处理器,整个处理器由四部分组成:多个套接字,IO多路复用,文件事件分派器,事件处理器。
               - 文件处理器,使用 IO多路复用程序来监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同事件的处理器
               - 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。

事务

   1. 什么是事务
          - 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
          - 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
   2. redis事务的概念
          - Redis 事务的本质是通过MULTI、EXEC、WATCH等一组命令的集合。事务支持一次执行多个命令
          - 一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
          - redis的事务就是一次性的,顺序性的,排他性的执行一个队列中的一系列命令
3. redis事务开启的三个阶段
       - 事务开始
       - 命令入队
       - 事务执行
4. Redis事务相关命令
       - Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的。
      - Redis会将一个事务中的所有命令序列化,然后按顺序执行。
            - watch 是一个乐观锁,可以为redis事务提供给check-and-set行为,可以监控一个或是多个键,一旦其中一个键被修改,之后的事务就不会执行,监控一直持续到EXEC命令。
            - MULTI命令用于开启一个事务,它总是返回OK。MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。
            - EXEC:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回空值 nil 。
            - 通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。
5. 事务管理
       - 原子性
       - 隔离性
       - 持久性
       - 隔离性

集群方案

   1. 哨兵模式
          - 集群监控:负责监控redis master 和slave进程是否正常工作
          - 消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
          - 故障转移:如果master node 挂掉了,会自动转移slave node
          - 配置中心:如果故障转移了,通知client客户端新的master地址上
         - 哨兵核心点
               - 哨兵至少需要 3 个实例,来保证自己的健壮性。
               - 哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。
               - 对于哨兵 + redis 主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。
   2. 官方Redis-cluster模式
          - Redis Cluster是一种服务端Sharding技术,3.0版本开始正式提供。Redis  Cluster并没有使用一致性hash,而是采用slot(槽)的概念,一共分成16384个槽。将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行
         - 方案说明
               - 通过hash的方式,将数据分片,每个节点均分存储一定哈希槽的区间数据,默认分配了16384个槽位
               - 每份数据分片会存储在多个互为主从的多节点上
               - 数据先写主节点在同步到从节点
               - 同一分片多个节点间的数据不保持一致性
               - 读取数据的时候,当客户端操作的key没有分配到该节点的时候,redis会返回转向指令,指向正确的节点
               - 扩容时需要把旧的节点的数据迁移到新的节点
               - 在 redis cluster 架构下,每个 redis 要放开两个端口号,比如一个是 6379,另外一个就是 加1w 的端口号,比如 16379。16379 端口号是用来进行节点间通信的,也就是 cluster bus 的东西,cluster bus  的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus 用了另外一种二进制的协议,gossip  协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。
      - 节点之间内部通信
            - 集群元数据的维护有两种方式:集中式、Gossip 协议。redis cluster 节点间采用 gossip 协议进行通信。
      - 分布式寻址法
            - Hash 算法
            - 一致性hash算法 + 虚拟节点
            - Redis clustor 的hash slot 算法
      - 优点
            - 无中心架构,支持动态扩容,对业务透明
            - 具备Sentinel的监控和自动Failover(故障转移)能力
            - 客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
            - 高性能,客户端直连redis服务,免去了proxy代理的损耗
      - 缺点
            -  不支持批量操作
            - 分布式逻辑和存储模块耦合

你可能感兴趣的:(Redis面试总结一)