220 lines
7.1 KiB
Markdown
220 lines
7.1 KiB
Markdown
1. redis 为什么这么快
|
||
|
||
- 基于内存来存储数据的,所以读写访问速度可以做到特别快
|
||
- 单线程的,可以避免多线程上下文切换带来的开销,同时加入了多路 IO 复用
|
||
- 内置了优化过的数据类型,性能高
|
||
|
||
3. 分布式缓存常见的技术选型方案
|
||
|
||
|
||
|
||
4. 为什么使用 redis/缓存
|
||
|
||
- 高性能,频繁访问的数据,访问数据更快
|
||
- 高并发,加大 QPS 访问量
|
||
|
||
5. redis 的应用场景
|
||
|
||
- 分布式锁
|
||
- 限流,通过 redis 加 Lua 脚本实现,令牌桶
|
||
- 消息队列
|
||
- 延时队列
|
||
- 分布式 Session
|
||
- 复杂业务场景,通过 bitmap 统计用户活跃量,通过或 soted set 实现排行榜
|
||
|
||
6. 常见缓存读写分类策略
|
||
7. 如何实现分布式锁
|
||
|
||
set NX key value,del NX key value
|
||
|
||
8. redis 数据结构
|
||
|
||
- String
|
||
- List
|
||
- Set
|
||
- Zset
|
||
- Hash
|
||
- HyperLogLogs
|
||
- Bitmap
|
||
- GeoSptial
|
||
|
||
10. String 的应用场景
|
||
|
||
String 是一种二进制安全的数据结构,可以用来存储任何类型数据,字符串,浮点数,图片(base 64 或地址),序列化
|
||
|
||
11. String 还是 Hash 存储对象更好
|
||
|
||
String 性能上比 Hash 节省内存,并且在存储多层嵌套的整个对象通过序列化也很方便,Hash 则是可以单独修改或者添加部分字段信息,如果是经常修改对象中的部分信息,就使用 Hash,否则用String
|
||
|
||
12. String 的底层实现
|
||
|
||
C 语言字符串是以\\0 结尾的字符数组,但是 redis 自己编写了 SDC(简单动态字符串)作为底层实现
|
||
|
||
13. 购物车使用 String 还是 Hash
|
||
|
||
使用 Hash,用户修改时就只是修改内部的 key 和 value 值即可
|
||
|
||
14. 如何实现排行榜
|
||
|
||
使用 Zset 实现
|
||
|
||
15. Set 的使用场景
|
||
|
||
存储不能重复的数据,例如网站的 UV 统计,点赞的统计
|
||
计算交集并集差集,共同好友
|
||
需要随机获取数据中的元素的场景,抽奖,随机点名
|
||
|
||
16. 使用 Set 实现抽奖系统
|
||
|
||
添加元素,随机移除并获取其中一个(不重复),随机获取一个元素(可重复)
|
||
|
||
17. 使用 Bitmap 统计活跃用户
|
||
|
||
将用户 ID 作为 offset,如果用户活跃过,就将该 bit 位设为 1
|
||
|
||
18. 使用 HyperLogLog 统计页面 UV
|
||
|
||
添加一个或多个元素到 HyperLogLog 中,
|
||
获取一个或多个 HyperLogLog 的唯一计数
|
||
|
||
19. [[Redis 持久化机制]]
|
||
|
||
20. Redis 线程模型
|
||
|
||
Redis 在 6.0 引入多线程来提供网络请求处理 IO 的性能,Redis 中的事件处理模型基于 Reacotor 模型,对应其中的文件时间处理器,这个是单线程运行的,Redis 利用 IO 多路复用程序来监听来自客户端的大量链接,无需创建多余的线程来监听,降低资源消耗
|
||
|
||
21. Redis 6.0 之前为什么不使用多线程,6.0 为何应用多线程
|
||
|
||
为了提高网络 IO 的读写性能,Redis 瓶颈主要在于**内存**和**网络**
|
||
|
||
22. Redis 后台线程
|
||
|
||
三个后台线程:
|
||
- `close_file`
|
||
- `aof_fsync`
|
||
- `lazy_free`
|
||
|
||
23. Rdis 缓存过期时间,如何判断数据是否过期,过期数据删除策略
|
||
|
||
redis 内存有限,因此要给缓存设置一定的过期时间,防止 OOM,同时可以实现某些需要一定时间后过期的业务,
|
||
通过一个过期字典(一个 hash 表)来保存数据过期的时间,过期字典的 key 指向 redis 中的 key,value 是一个 long 类型的整数,存储时间戳
|
||
|
||
**过期数据删除策略**
|
||
- **惰性删除**:只有在数据取出时判断是否过期,对 cpu 友好
|
||
- **定期删除**:定期取出一批的 key 删除过期的 key,通过限制删除操作执行时长和频率来减少对 CPU 的影响,对内存友好
|
||
---
|
||
redis 使用的是定期删除+惰性删除的方式
|
||
|
||
24. 内存淘汰机制
|
||
|
||
- **volatile-lru**:从已设置过期时间的数据集中挑选最少使用的进行删除
|
||
- **volatile-ttl**:从已设置过期时间的数据集中挑选将要过期的删除
|
||
- **volatile-random**:从已设置过期时间的数据集中随机选择数据删除
|
||
- **allkeys-lru**:内存不足时,移除最近最少使用的 key
|
||
- **allkeys-random**:从数据中随机选择数据淘汰
|
||
- **no-eviction**:禁止删除,新写入的操作报错
|
||
- **volatile-lfu**:从已设置过期时间的数据集中挑选最不经常使用的数据删除
|
||
- **allkeys-lfu**:从键空间中移除最不经常使用的数据
|
||
|
||
25. 什么是 Rdis 事务
|
||
|
||
redis 事务将多个命令打包后顺序执行,通过 `MULTI` `EXEC` `DISCARD` `WATCH` 命令实现
|
||
|
||
26. Redis 事务支持原子性吗,支持持久性吗
|
||
|
||
不支持,运行错误时也不支持回滚,除了出现错误的命令其他命令都会执行,无法保证持久性
|
||
|
||
27. 如何解决 Redis 事务缺陷
|
||
|
||
利用 Lua 脚本来批量执行,一段 Lua 脚本可以看成一条命令,执行过程中不会有其他命令执行,但是出错的命令之后的命令也不会执行
|
||
|
||
28. Redis 性能优化
|
||
1. 使用批量操作减少网络传输
|
||
一个 redis 命令执行分为以下四部
|
||
- 发送命令
|
||
- 命令排队
|
||
- 命令执行
|
||
- 返回结果
|
||
1 和 4 的耗时为 RTT,就时网络延时,通过批量操作可以减少网络传输次数,减少网络开销
|
||
1. pipeline
|
||
`MGET`,`HMGET`,`SADD`,原生支持批量操作
|
||
1. 通过pipeline
|
||
1. Lua 脚本
|
||
30. 大量 key 集中过期问题
|
||
|
||
- 给 key 设置随机过期时间
|
||
- 设置 lazy-free(惰性删除/延迟释放)
|
||
|
||
31. bigkey 分析及处理
|
||
|
||
String 类型超过 10kb,复合类型超过 5000 个元素,
|
||
使用 redis 的--bigkey 获取,借助开源工具分析,借助公有云的 Redis 分析服务
|
||
|
||
- 分割 BigKey
|
||
- 手动清理
|
||
- 采用合适的数据结构(HyperLogLog 统计页面 UV)
|
||
- 开启 lazy-free
|
||
|
||
32. hotkey 危害及处理
|
||
|
||
频繁访问的 key,
|
||
使用--hotkey,使用 `MONITOR`,使用开源项目京东 hotkey,根据业务提前预估,业务代码中记录,借助公有云分析
|
||
|
||
- 读写分离
|
||
- 使用 Redis Cluster
|
||
- 二级缓存,将 hotkey 存放一份到 JVM 本地内存中(使用Caffeine)
|
||
|
||
33. 慢查询命令
|
||
|
||
设置慢查询时间,通过查询慢查询日志获取
|
||
|
||
34. 内存碎片
|
||
|
||
不可用的内存空间
|
||
- redis 存储数据时申请的空间大于实际需要空间
|
||
- 频繁修改 redis 中的数据
|
||
|
||
通过 redis 的内存整理功能清理碎片
|
||
|
||
35. 生产问题
|
||
|
||
1. 缓存穿透
|
||
|
||
请求的 key 时不存在于缓存,也不存在于数据库中,从而大量请求到数据库中查找,
|
||
- 缓存无效 key
|
||
- 布隆过滤器
|
||
|
||
1. 缓存击穿
|
||
|
||
请求热点数据,但是热点 key过期,请求大量到数据库,
|
||
- 设置热点key永不过期
|
||
- 热点数据提前预热
|
||
- 请求数据到达数据库前获取互斥锁,保证只有一个请求到达数据库
|
||
|
||
1. 缓存雪崩
|
||
|
||
缓存在同一时间大量失效,大量请求到达数据库,或者是服务器宕机
|
||
- 设置不同失效时间,随机失效
|
||
- 缓存永不失效
|
||
- 二级缓存
|
||
- 采用 redis 集群
|
||
- 限流
|
||
|
||
36. 如何保证缓存数据和数据库一致性
|
||
|
||
**旁路缓存模式**
|
||
更新完 DB 后直接删除cache
|
||
|
||
37. [[Redis 集群]]
|
||
|
||
|
||
38. 为什么要使用分布式缓存
|
||
|
||
|
||
39. 常见的缓存更新策略
|
||
|
||
|
||
40. 如何实现自动化故障转移
|
||
|
||
|
||
41. 缓存数据量太大怎么办 |