文章目录
- 缓存穿透、缓存击穿、缓存雪崩
- Redis键的过期
- 1. 设置过期时间的命令
- 2. 过期时间设置原则
- 3. Redis处理过期键策略
- 4. Redis缓存淘汰策略
- Redis的线程
- 1. 版本变更中的多线程
- 2. Redis为什么快
- 3. Redis核心为什么使用单线程
- 如何设计分布式锁
- 双写一致问题
- 1. 删除和更新缓存的比较
- 2. 先删缓存后更数据库
- 3. 先更新缓存后更新数据库
- 4. 先更数据库,后删除/更新缓存
- 5. 延时双删
- 6. 如何强一致
- Redis高可用
- 1. 哨兵
- 2. 集群
- 3. 复制/主从同步
- 如何使用布隆过滤器
- 其它
- 1. Redis各种数据结构原理
- 2. 持久化
- 参考
缓存穿透、缓存击穿、缓存雪崩
缓存穿透 | 缓存击穿 | 缓存雪崩 | |
---|---|---|---|
描述 | 查询不存在的数据 | 某小段时间大量相同查询达到存储层 | 缓存无法提供服务,大量请求打到存储层 |
可能原因 | 1. 缓存和库中数据被删除 2. 恶意攻击 | 某些热点数据过期失效 | 大量数据过期,或Redis宕机 |
解决方法 | 1. 缓存空对象,未命中时将空值存入缓存 2. 布隆过滤器拦截 | 1. 热点数据永不过期 2. 互斥加锁,多线程访问redis某key无数据时,只有一个线程能去存储层查询并存入redis,然后其它线程再从redis取数据 | 1. 避免数据同时过期,设置过期时间为随机值 2. 降级和熔断,对于非核心请求直接返回预定义信息 3. 构建高可用服务 |
Redis键的过期
1. 设置过期时间的命令
命令 | 示例和描述 |
---|---|
PERSIST | PERSIST key-name —— 移除键的过期时间 |
TTL | TTL key-name —— 查看给定键距离过期还有多少秒 |
EXPIRE | EXPIRE key-name seconds —— 让给定键在指定的秒数之后过期 |
EXPIREAT | EXPIREAT key-name timestamp —— 将给定键的过期时间设置为给定的 UNIX 时间戳 |
PTTL | PTTL key-name —— 查看给定键距离过期时间还有多少毫秒 |
PEXPIRE | PEXPIRE key-name milliseconds —— 让给定键在指定的毫秒数之后过期 |
PEXPIREAT | PEXPIREAT key-name timestamp-milliseconds —— 将一个毫秒级别精度的 UNIX 时间戳设置为过期时间 |
2. 过期时间设置原则
- 热点数据不设置过期时间,可以避免缓存击穿问题
- 设置的过期时间时随机值,避免大量key同时过期,导致缓存雪崩
3. Redis处理过期键策略
- 惰性删除: 客户端访问key时,检查是否过期,过期则删除
- 定期删除: 服务端将设置了过期时间的key放到独立字典中,定期进行扫描。扫描逻辑:
- 随机选择部分key(20)
- 删除过期key
- 若过期比例超过25%则重复操作
4. Redis缓存淘汰策略
LRU和LFU的算法代码见这里
当写入数据将导致超出maxmemory限制时,Redis会采用maxmemory-policy所指定的策略进行数据淘汰。该策略包含如下八种。
策略 | 描述 | 版本 |
---|---|---|
noeviction | 直接返回错误; | |
volatile-ttl | 从设置了过期时间的键中,选择过期时间最小的键,进行淘汰; | |
volatile-random | 从设置了过期时间的键中,随机选择键,进行淘汰; | |
volatile-lru | 从设置了过期时间的键中,使用LRU算法选择键,进行淘汰; | |
volatile-lfu | 从设置了过期时间的键中,使用LFU算法选择键,进行淘汰; | 4.0 |
allleys-random | 从所有的键中,随机选择键,进行淘汰; | |
allkeys-lru | 从所有的键中,使用LRU算法选择键,进行淘汰; | |
allkeys-lfu | 从所有的键中,使用LFU算法选择键,进行淘汰; | 4.0 |
前缀含义:
- volatile:从设置了过期时间的键中淘汰数据
- allkeys:从所有的键中淘汰数据
LRU与LFU:
- LRU最近最少访问删除策略,非热点数据在偶尔访问后,一段时间内不会被淘汰。
- LFU最近最不经常使用删除策略,访问次数最少会被删除,如果多个数据访问数据相同,则这些数据根据LRU策略删除
Redis的线程
从 Redis 的 v1.0 到 v6.0 版本之前,Redis 的核心网络模型一直是一个典型的单 Reactor 模型。Redis v6.0 才改造成多线程模式。
Redis的主要瓶颈是内存和网络带宽,而非CPU。6.0引入多线程解决网络IO问题。
1. 版本变更中的多线程
涉及的多线程 | |
---|---|
Redis 3.0前 | 1. 持久化:BGSAVE和BGREWRITEAOF会fork子进程进行 2. 异步任务:关闭文件、将缓冲区冲洗到磁盘文件中 |
Redis 4.0 | 异步删除键值对的命令:UNLINK(DEL的异步版本)、FLUSHALL ASYNC、FLUSHDB ASYNC(删除选项,整个数据集还是单个数据库) |
Redis 6.0 | socket读写、请求解析是多线程,但命令执行是单线程(键值对操作,防止线程不安全) |
2. Redis为什么快
- 单线程处理命令避免上下文切换和线程竞争带来的开销
- 数据存储在内存
- c语言本身性能高
- IO多路复用技术,实现高吞吐的网络IO UNIX IO五种模型
3. Redis核心为什么使用单线程
- 避免上下文切换
- 避免同步机制带来开销
- 简单可维护
如何设计分布式锁
- set key value nx ex seconds 原子性地赋值和设置过期时间
- Redisson框架
更多
双写一致问题
- 先删缓存后更数据库
- 先更新缓存后更新数据库
- 先更数据库后删缓存
- 先更新数据库后更新缓存
- 延时双删
1. 删除和更新缓存的比较
- 删除:
- 优点:操作简单
- 缺点:下次读取时需要重新从数据库取
- 更新:
- 优点:数据变化更新及时
- 缺点:写多读少的场景性能差。
2. 先删缓存后更数据库
在A线程删缓存和更新数据库期间,其他线程查询并更新缓存后,会造成数据库和缓存不一致的情况。
3. 先更新缓存后更新数据库
A线程更新缓存后若数据库更新失败,会造成数据库和缓存不一致的情况。一般需要重试,一般通过异步方式进行
4. 先更数据库,后删除/更新缓存
- 在 A线程更新数据库到删除/更新缓存期间,其它线程查询到的数据是历史缓存数据,与数据库不一致。
- 若A线程删/更新缓存失败,则从A更新数据库后,缓存和数据库就一直不一致。
5. 延时双删
- 若B线程在A第一次删缓存和更数据库期间查询数据库,并在A更新数据和延时删除缓存之间更新了缓存,那么在B更新缓存和A延时删缓存的中间时刻发生数据不一致。
- 若是B线程更新缓存在A延时删除缓存之后发生,则同样发生了数据不一致。这说明延时时间设置不合理。
延时时间的设置:
- 设置时间过大可能导致情况1发生
- 设置时间过小可能导致情况2发生
- 需要根据业务场景合理估计设置时间
6. 如何强一致
- 对单key使用分布式锁,将缓存操作和数据库操作放到一个锁中,会影响性能,需要注意失败处理和锁的释放
- 放弃缓存
- 单key串行化读写,相同key的操作加入等待队列(类似于加锁)
Redis高可用
1. 哨兵
角色说明:
- 主结点:负责处理外部的读写操作
- 从结点:只读,主节点无效时可能被选拔为主节点
- 哨兵:监控主结点、从结点、其他哨兵。主结点故障时选从结点变为主结点。哨兵是特殊的Redis结点,不存储数据,只只支持部分命令
2. 集群
通过虚拟槽实现数据分片。
3. 复制/主从同步
psync命令支持全量复制和部分复制。
全量复制的两个阶段:
- 同步阶段:主结点执行BGSAVE,将RDB通过网络传输给从结点,从结点载入数据。实现数据一致
- 命令传播:数据一致后,主节点数据发生更改,会将使数据发生更改的写命令发送给从结点,进而一致
部分复制的来由:
若每次主从结点网络断开重连后都需要全量复制,不必要资源开销较大。可以从上次复制过的数据开始增量更新
部分复制实现的方式: - 复制偏移量:主从结点记录上次复制后的偏移量,下次可以接着该位置增量更新
- 积压缓冲区:写命令会被记录到增量缓冲区,增量复制时回到缓冲区找偏移量。找到则将偏移量开始后的数据传递给从结点。若是找不到说明相差太多,需要进行全量复制。
- 主节点运行ID:为了防止从结点切换复制的主节点,从结点需要记录之前同步的主节点ID,每次想要部分复制时比较当前存储的ID和想要复制的主节点ID是否相同。
如何使用布隆过滤器
布隆过滤器使用bit位存储数据。占用空间小。
可以用于拦截不存在的数据,有概率拦截到存在的数据。
其它
1. Redis各种数据结构原理
见【Redis】数据结构与对象
2. 持久化
见【Redis】RDB与AOF持久化
参考
- Java面试宝典
- Redis多线程网络模型全面揭秘
- Reactor模式介绍
- Redis(十三):Redis多线程
- Redis6系列1-线程模型(单线程OR多线程)
- Redis6.0多线程模型总结
- redis缓存为什么要延时双删
- 分布式锁中的王者方案 - Redisson
- 七种方案!探讨Redis分布式锁的正确使用姿势
更多推荐
【Redis】八股文必背
发布评论