Redis提供的数据类型
常见数据类型
- 5种常见数据类型:String(字符串)、List(列表)、Set(集合)、ZSet(有序集合)、Hash(散列)
- 3种特殊数据类型:HyperLogLog(基数统计)、Bitmap (位图)、Geospatial (地理位置)。
使用String还是Hash存储对象数据?
- String存储的是序列化后的对象数据,存放的是整个对象。Hash是对对象的每个字段单独存储,可以获取部分字段的信息,也可以修改和添加部分字段,适用于经常变动或单独查询对象中的个别字段信息。
- String存储相对来说更加节省内存,缓存相同数量的对象数据,String消耗的内存是Hash的一半。
在绝大多数情况下,建议使用String来存储对象。
主从复制原理
从节点对主节点的数据进行备份,提升容灾能力。主节点负责写,从节点负责读。如果master宕机,则从slave中选出一台作为master即可实现故障转移。
Redis两种持久化方式的对比
为什么全量复制使用的rdb模式,而不是aof
【Redis可以通过创建快照的方式来获得存储在内存里的数据在某个时间点上的副本】
文件格式 | 数据恢复 | 刷盘策略 | |
rdb【默认开启】 | 压缩的二进制文件,很小,传输起来更快 | 由子进程保存,不影响父进程。恢复速度快 | 快 |
aof | 存储的每一次的写命令,文件很大 | 需要依次执行写命令,恢复速度慢 | 慢 |
快照模式rdb的缺点,每次保存点之间redis不可意料的关闭,可能造成数据丢失;每次保存数据都要fork出一个子进程,对性能有损耗。
redis4.0支持混合持久化
Redis内存淘汰机制
Redis提供6种数据淘汰策略
多级缓存时怎么做的?为什么还要多加一层本地缓存呢?
什么是多级缓存?
本地缓存+分布式缓存,本地缓存的访问速度要远大于分布式缓存,因为访问本地缓存不存在额外的网络开销
适合多级缓存的两种业务场景:
- 缓存的数据不会频繁修改,比较稳定
- 数据访问量特别大如秒杀场景
多级缓存方案中,第一级缓存使用本地内存(比如caffrine),第二级缓存使用分布式缓存(如Redis)。如果L2也没有此数据,才去数据库查询,数据查询成功后再将数据写入L1和L2中
Redis生产问题
如何避免key大量过期
给key设置随机过期时间+开启惰性删除模式
什么是缓存穿透?如何解决
大量请求的key不在缓存中,导致直接打到了数据库上。
常见的解决方案:
- 缓存无效key:将不存在的数据也加入到redis,设置过期时间,攻击无法直达数据库【空间换时间】
- 布隆过滤器
- 接口限流:根据用户或者IP对接口进行限流,对于异常频繁访问的行为,还可以才去黑名单机制,例如将异常ip列入黑名单
美团面试拷打:Redis 缓存穿透、缓存击穿、缓存雪崩区别和解决方案
什么是缓存击穿?如何解决
请求的key对应的是热点数据,该数据存在于数据库中,不存在于缓存中(通常是因为缓存过期),导致瞬间大量的请求直接打到了数据库上,对数据库产生了巨大的压力。
解决方案:
- 设置热点数据永不过期或者过期时间较长
- 针对热点数据提前预热,将其存入缓存并设置合理的过期时间。
- 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力
什么是缓存雪崩?如何解决
缓存同一时间大面试失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求。
redis不可用的情况:
- 搭建redis集群避免单点风险
- 限流,避免同时处理大量的请求
- 多级缓存,如本地缓存+Redis缓存的组合,当Redis缓存出现问题时,还可以从本地缓存中获取到部分数据。
热点缓存失效的情况:
- 设置不同的失效时间比如随机设置缓存的失效时间
- 缓存预热,也就是在程序启动或运行过程中,主动将热点数据加载到缓存中。
缓存穿透、缓存击穿和缓存雪崩有什么区别?
缓存穿透中,请求的 key 既不存在于缓存中,也不存在于数据库中。
缓存击穿中,请求的 key 对应的是 热点数据 ,该数据 存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期)
缓存雪崩中,缓存中大量或者所有数据失效
如何保证缓存和数据库数据的一致性
旁路缓存模式,遇到写请求:更新DB,然后直接删除cache
如果更新数据库成功,删除缓存失败怎么办?有两个解决方案:
- 缓存失效时间变短:让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。
- 增加cache更新重试机制(常用):如果cache服务当前不可用导致缓存删除失败的话,我们就嗝一段时间去进行重试,重试次数可以自己定。如果多次重试还是失败的话,可以把当前更新失败的key存入队列,等缓存服务可用之后,将缓存中对应的key删除即可。
Redis除了做缓存还可以做什么?
- 分布式锁:基于Redission来实现分布式锁 支付宝一面:如何基于Redis实现分布式锁?
- 限流:通过redis和lua脚本实现限流 我司用了 6 年的 Redis 分布式限流器,可以说是非常厉害了!
- 消息队列:redis自带的list数据结构可以作为一个简单的队列使用
- 延时队列:redission内置了延时队列(基于Sorted Set实现的)
- 分布式session:利用String或者Hash数据类型保存Session数据,所有的服务都可以访问