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个哈希值,然后根据位数组长度取余后存入
影响误判的因素
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 条评论
回复 删除
下一页