Redis高频面试题(单线程/数据结构/缓存)
2021-03-01 23:38:19 1 举报
AI智能生成
Redis高频面试题(单线程/数据结构/缓存)
作者其他创作
大纲/内容
单线程
redis是单线程吗?为什么?
这里的单线程是指Redis在处理网络请求的时候只有一个线程来处理
Redis为什么这么快?
1、基于内存实现,数据都存储在内存里,减少了一些不必要的 I/O 操作
2、redis采用IO多路复用模型,同时监听客户端连接,单线程在执行过程中不需要进行上下文切换,减少了耗时
epoll
3、高效的数据结构
比如String底层的SDS、List的双端链表和压缩列表、Set的跳跃表等等
4、合理的数据编码
String:存储数字的话,采用int类型的编码,如果是非数字的话,采用 raw 编码
List:字符串长度及元素个数小于一定范围使用 ziplist 编码,任意条件不满足,则转化为 quicklist 编码
Set:保存元素为整数及元素个数小于一定范围使用 intset 编码,任意条件不满足,则使用 hashtable 编码
Zset:zset 对象中保存的元素个数小于及成员长度小于一定值使用 ziplist 编码,任意条件不满足,则使用 skiplist 编码
Hash:hash 对象保存的键值对内的键和值字符串长度小于一定值及键值对
数据结构
redis为什么有16个库?
在单个库中不允许存在重复key
用来区分不同的业务逻辑
redis如何存放对象?
基于Json序列化存放
优点:阅读性强、可以跨语言
缺点:明文不安全
基于String的二进制存放
优点:比较安全
缺点:不支持跨语言、阅读性差
为什么zset使用跳跃表而不用红黑树?
跳跃表的时间复杂度和红黑树一样,而且实现起来更简单
在并发环境下红黑树在插入和删除时需要rebalance,性能不如跳跃表
什么样的数据适合放缓存?
高频被访问的数据
数据的变化率不高
非敏感数据
缓存问题
缓存穿透:大量请求一个数据库不存在的数据
查询为空也暂时放入缓存
接口层增加校验
布隆过滤器
底层是很长的位数组
对同一个即将存入的数据 → 使用n个不同的hash算法
计算出n个哈希值,然后根据位数组长度取余后存入
计算出n个哈希值,然后根据位数组长度取余后存入
影响误判的因素
Hash函数的个数
位数组的长度
缺点
难以维护(数据不能删除)、需要定时更新数据(重建)
种类
Google的Guava,存储在JVM
分布式,存储在Redis位图
缓存击穿:热点key扛高并发,缓存失效的瞬间
热点数据不失效
互斥锁
缓存雪崩:缓存服务器宕机或者缓存集中失效
给缓存加随机因子,分散失效时间
对redis缓存做高可用,集群部署,增加抗风险能力(前)
设置本地缓存ehcache+限流hystrix,避免数据库被干掉(中)
利用redis的持久化机制,重启redis快速恢复缓存数据(后)
数据一致性
缓存双写一致性?
先删缓存再更新数据库,期间有查询呢?
先更新数据库再删缓存,缓存删除失败呢?
最终解决方案
延迟双删:先删缓存再更新数据库,等几百毫秒
再删缓存 (延迟时间根据具体的业务耗时而定)
再删缓存 (延迟时间根据具体的业务耗时而定)
并发竞争?
分布式锁
set key value px milliseconds nx 或使用 jedis
注意点
value要具有唯一性,可用UUID.randomUUID().toString()方法生成
释放锁时使用lua脚本保证原子性,并验证value值,防止误解锁
存在的风险
如果存储锁对应key的那个节点挂了的话,就可能存在丢失锁
的风险,导致出现多个客户端持有锁的情况
的风险,导致出现多个客户端持有锁的情况
解决
redis官方提供了RedLock算法
Redission
大key
原生自带的bigkeys命令,找出来拆分或者删除
热点key
如何发现热点key?
凭借业务经验,进行预估哪些是热key
客户端收集,在操作redis前对数据进行统计
使用redis自带命令:redis-cli 时加上 –hotkeys
如何解决热点key?
(隔离+分治)
(隔离+分治)
打散到多个节点
分散一台redis服务器上的压力
热点Key+随机数,分散缓存至其他节点
利用多级缓存
添加本地缓存缓解redis压力
读写分离扩容
增加从节点增加读能力
设置永不过期
防止缓存击穿
0 条评论
下一页