Files
Hui-s-notebook/Java-Interview/数据库/Redis.md
Lostecho c8f11d0488 update
2024-03-03 16:38:06 +08:00

7.1 KiB
Raw Blame History

  1. redis 为什么这么快
  • 基于内存来存储数据的,所以读写访问速度可以做到特别快
  • 单线程的,可以避免多线程上下文切换带来的开销,同时加入了多路 IO 复用
  • 内置了优化过的数据类型,性能高
  1. 分布式缓存常见的技术选型方案

  2. 为什么使用 redis/缓存

  • 高性能,频繁访问的数据,访问数据更快
  • 高并发,加大 QPS 访问量
  1. redis 的应用场景
  • 分布式锁
  • 限流,通过 redis 加 Lua 脚本实现,令牌桶
  • 消息队列
  • 延时队列
  • 分布式 Session
  • 复杂业务场景,通过 bitmap 统计用户活跃量,通过或 soted set 实现排行榜
  1. 常见缓存读写分类策略
  2. 如何实现分布式锁

set NX key valuedel NX key value

  1. redis 数据结构
  • String
  • List
  • Set
  • Zset
  • Hash
  • HyperLogLogs
  • Bitmap
  • GeoSptial
  1. String 的应用场景

String 是一种二进制安全的数据结构可以用来存储任何类型数据字符串浮点数图片base 64 或地址),序列化

  1. String 还是 Hash 存储对象更好

String 性能上比 Hash 节省内存并且在存储多层嵌套的整个对象通过序列化也很方便Hash 则是可以单独修改或者添加部分字段信息,如果是经常修改对象中的部分信息,就使用 Hash否则用String

  1. String 的底层实现

C 语言字符串是以\0 结尾的字符数组,但是 redis 自己编写了 SDC简单动态字符串作为底层实现

  1. 购物车使用 String 还是 Hash

使用 Hash用户修改时就只是修改内部的 key 和 value 值即可

  1. 如何实现排行榜

使用 Zset 实现

  1. Set 的使用场景

存储不能重复的数据,例如网站的 UV 统计,点赞的统计 计算交集并集差集,共同好友 需要随机获取数据中的元素的场景,抽奖,随机点名

  1. 使用 Set 实现抽奖系统

添加元素,随机移除并获取其中一个(不重复),随机获取一个元素(可重复)

  1. 使用 Bitmap 统计活跃用户

将用户 ID 作为 offset如果用户活跃过就将该 bit 位设为 1

  1. 使用 HyperLogLog 统计页面 UV

添加一个或多个元素到 HyperLogLog 中, 获取一个或多个 HyperLogLog 的唯一计数

  1. Redis 持久化机制

  2. Redis 线程模型

Redis 在 6.0 引入多线程来提供网络请求处理 IO 的性能Redis 中的事件处理模型基于 Reacotor 模型对应其中的文件时间处理器这个是单线程运行的Redis 利用 IO 多路复用程序来监听来自客户端的大量链接,无需创建多余的线程来监听,降低资源消耗

  1. Redis 6.0 之前为什么不使用多线程6.0 为何应用多线程

为了提高网络 IO 的读写性能Redis 瓶颈主要在于内存网络

  1. Redis 后台线程

三个后台线程:

  • close_file
  • aof_fsync
  • lazy_free
  1. Rdis 缓存过期时间,如何判断数据是否过期,过期数据删除策略

redis 内存有限,因此要给缓存设置一定的过期时间,防止 OOM同时可以实现某些需要一定时间后过期的业务 通过一个过期字典(一个 hash 表)来保存数据过期的时间,过期字典的 key 指向 redis 中的 keyvalue 是一个 long 类型的整数,存储时间戳

过期数据删除策略

  • 惰性删除:只有在数据取出时判断是否过期,对 cpu 友好
  • 定期删除:定期取出一批的 key 删除过期的 key通过限制删除操作执行时长和频率来减少对 CPU 的影响,对内存友好

redis 使用的是定期删除+惰性删除的方式

  1. 内存淘汰机制
  • volatile-lru:从已设置过期时间的数据集中挑选最少使用的进行删除
  • volatile-ttl:从已设置过期时间的数据集中挑选将要过期的删除
  • volatile-random:从已设置过期时间的数据集中随机选择数据删除
  • allkeys-lru:内存不足时,移除最近最少使用的 key
  • allkeys-random:从数据中随机选择数据淘汰
  • no-eviction:禁止删除,新写入的操作报错
  • volatile-lfu:从已设置过期时间的数据集中挑选最不经常使用的数据删除
  • allkeys-lfu:从键空间中移除最不经常使用的数据
  1. 什么是 Rdis 事务

redis 事务将多个命令打包后顺序执行,通过 MULTI EXEC DISCARD WATCH 命令实现

  1. Redis 事务支持原子性吗,支持持久性吗

不支持,运行错误时也不支持回滚,除了出现错误的命令其他命令都会执行,无法保证持久性

  1. 如何解决 Redis 事务缺陷

利用 Lua 脚本来批量执行,一段 Lua 脚本可以看成一条命令,执行过程中不会有其他命令执行,但是出错的命令之后的命令也不会执行

  1. Redis 性能优化
    1. 使用批量操作减少网络传输 一个 redis 命令执行分为以下四部
      • 发送命令
      • 命令排队
      • 命令执行
      • 返回结果 1 和 4 的耗时为 RTT就时网络延时通过批量操作可以减少网络传输次数减少网络开销
    2. pipeline MGETHMGETSADD,原生支持批量操作
    3. 通过pipeline
    4. Lua 脚本
  2. 大量 key 集中过期问题
  • 给 key 设置随机过期时间
  • 设置 lazy-free惰性删除/延迟释放)
  1. bigkey 分析及处理

String 类型超过 10kb复合类型超过 5000 个元素, 使用 redis 的--bigkey 获取,借助开源工具分析,借助公有云的 Redis 分析服务

  • 分割 BigKey
  • 手动清理
  • 采用合适的数据结构HyperLogLog 统计页面 UV
  • 开启 lazy-free
  1. hotkey 危害及处理

频繁访问的 key 使用--hotkey使用 MONITOR,使用开源项目京东 hotkey根据业务提前预估业务代码中记录借助公有云分析

  • 读写分离
  • 使用 Redis Cluster
  • 二级缓存,将 hotkey 存放一份到 JVM 本地内存中使用Caffeine
  1. 慢查询命令

设置慢查询时间,通过查询慢查询日志获取

  1. 内存碎片

不可用的内存空间

  • redis 存储数据时申请的空间大于实际需要空间
  • 频繁修改 redis 中的数据

通过 redis 的内存整理功能清理碎片

  1. 生产问题

    1. 缓存穿透

      请求的 key 时不存在于缓存,也不存在于数据库中,从而大量请求到数据库中查找,

      • 缓存无效 key
      • 布隆过滤器
    2. 缓存击穿

    请求热点数据,但是热点 key过期请求大量到数据库
    	- 设置热点key永不过期
    	- 热点数据提前预热
    	- 请求数据到达数据库前获取互斥锁,保证只有一个请求到达数据库
    
    1. 缓存雪崩

      缓存在同一时间大量失效,大量请求到达数据库,或者是服务器宕机 - 设置不同失效时间,随机失效 - 缓存永不失效 - 二级缓存 - 采用 redis 集群 - 限流

  2. 如何保证缓存数据和数据库一致性

旁路缓存模式 更新完 DB 后直接删除cache

  1. Redis 集群

  2. 为什么要使用分布式缓存

  3. 常见的缓存更新策略

  4. 如何实现自动化故障转移

  5. 缓存数据量太大怎么办