面试必备——Redis

Redis 概念
  • redis 是一个开源的、支持网络交互的、可基于内存的、也可持久化的高性能Key-Value数据库

  • 与传统数据库相比, Redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。

  • 与本地缓存相比使用自带的 map 或者 guava 实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着 jvm 的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。

    使用 redis 之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。(缺点:较为复杂)

Redis 特征
  • 支持数据持久化,可以将数据保存在磁盘中,重启后再次加载到内存使用
  • 支持多种数据类型
  • 支持 master-slave 模式的数据备份
Redis 为什么快
  • 完全基于内存,绝大部分请求是内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
  • 数据结构简单,对数据操作也简单
  • Redis 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁、释放锁操作,不会因为可能出现死锁而导致的性能消耗;
  • 使用多路 I/O 复用模型,非阻塞 IO;
Redis 应用场景(为满足高性能和高并发)
  • 热点数据加速查询(高性能),如热点商品或信息等访问量较高的数据
  • 即时信息查询(高性能),如在线人数查询
  • 时效性信息控制,如验证码控制
  • 分布式数据分享(高并发),如分布式集群架构中 session 分离队列
  • 备注:**高性能:**用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。可以将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。**高并发:**直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。
Redis 基础知识
  • redis 采用单线程机制工作
  • redis 默认拥有16个数据库,数据库编号从0开始
  • redis 中所有数据库使用同一个密码,默认没有密码,redis 认为安全层面应该由Linux来保证
Redis 部分指令
  • 使用select 数据库编号 可以切换使用的数据库
  • dbsize 命令 查看当前数据库key的数量
  • keys * 命令 查看当前数据库所有的key
  • flushdb 命令 清空当前数据库
  • flushall 命令 清空所有数据库
Redis 的数据结构(Key-Value)
  • Key的特点

    • Key都是string类型
    • 不超过1024字节(影响查找效率)
    • 不能太短(可读性降低)
  • Value支持五种数据结构

    • 字符串(strings)
      • 底层用简单动态字符串实现,对定义SDS对象,此对象中包含三个属性:
        • len buf中已经占有的长度(表示此字符串的实际长度)
        • free buf中未使用的缓冲区长度
        • buf[] 实际保存字符串数据的地方
      • 所以取字符串的长度的时间复杂度为O(1),redis为字符分配空间的次数是小于等于字符串的长度N
    • 字符串列表(lists)
      • list 的底层是linkedlist的结构,是一个双向链表,每个节点包含向前向后的指针,当插入或删除元素的时候,只需要对此元素前后指针操作即可。所以插入和删除效率很高。但查询的效率却是O(n)[n为元素的个数]。
    • 字符串集合(sets)
      • 集合通过使用散列表保证自已存储的每个字符串都是各不相同的,这些散列表只有键,但没有与键相关联的值,redis中的集合是无序的
    • 有序字符串集合(sorted sets)
      • 有序集合的键被称为成员,每个成员都是各不相同的。有序集合的值则被称为分值(score),分值必须为浮点数。有序集合是redis 里面唯一一个既可以根据成员访问元素(这一点和散列一样),又可以根据分值以及分值的排列顺序访问元素的结构。
    • 哈希(hashes)
      • 一种是ziplist,当存储的数据超过配置的阀值时就是转用hashtable的结构。这种转换比较消耗性能,所以应该尽量避免这种转换操作。同时满足以下两个条件时才会使用这种结构:
        • 当键的个数小于hash-max-ziplist-entries(默认512)
        • 当所有值都小于hash-max-ziplist-value(默认64)
      • 另一种就是hashtable。这种结构的时间复杂度为O(1),但是会消耗比较多的内存空间。
    数据类型 可存储的值 应用场景 应用
    String 字符串、整数、浮点数 做简单的键值对缓存 验证码
    List 列表 存储一些列表型的数据结构,比如文章的评论列表 省市区表
    Set 无序集合 交集、并集、差集的操作 查找共同好友数
    Hash 包含键值对的无序散列表 结构化的数据,比如一个对象 商品ID和详情
    Zset 有序集合 去重但可以排序,如获取排名前几名的用户 根据score值进行排序
什么是 Redis 的持久化
  • Redis 提供两种持久化机制 RDB(默认) 和 AOF 机制

  • RDB:是Redis DataBase缩写快照

    • RDB 是 Redis 默认的持久化方式。按照一定的时间把内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。
    • 优点
      • 只有一个文件 dump.rdb,方便持久化。
      • 容灾性好,一个文件可以保存到安全的磁盘。
      • 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
      • 相对于数据集大时,比 AOF 的启动效率更高。
    • 缺点
      • 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。
  • AOF:持久化

    • AOF 持久化(Append Only File),则是将 Redis 执行的每次写命令记录到单独的日志文件中,当重启 Redis 会重新将持久化的日志中文件恢复数据。
    • 当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
    • 优点:
      • 数据安全,AOF 持久化可以配置 appendfsync 属性,有 always,每进行一次命令操作就记录到 AOF 文件中一次。
      • 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
      • AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))
    • 缺点:
      • AOF 文件比 RDB 文件大,且恢复速度慢。
      • 数据集大的时候,比 rdb 启动效率低。
  • RDB 和 AOF 对比:

    • AOF 文件比 RDB 更新频率高,优先使用 AOF 还原数据。
    • AOF 比 RDB 更安全也更大
    • RDB 性能比 AOF 好
    • 如果两个都配置了优先加载AOF
  • 如何选择持久化方式:

    一般来说,同时使用两种持久化功能,当 Redis 重启的时候会优先载入 AOF 文件来恢复原始的数据,因为在通常情况下 AOF 文件保存的数据集要比 RDB 文件保存的数据集要完整。

缓存异常
  • 缓存雪崩:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

    • 解决方法:
      • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
      • 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
      • 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。
  • 缓存穿透:缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

    • 解决方法:
      • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
      • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  • 缓存击穿:缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

    • 设置热点数据永远不过期。
    • 加互斥锁,互斥锁

你可能感兴趣的:(后端,java,面试)