创作不易,你的关注分享就是博主更新的最大动力, 每周持续更新
微信搜索【 企鹅君】关注还能领取学习资料喔,第一时间阅读(比博客早两到三篇)
求关注❤️ 求点赞❤️ 求分享❤️ 对博主真的非常重要
企鹅君原创|GitHub开源项目github.com/JavaDance 欢迎Star和完善
面试开始
激动的心,颤抖的手, 你打开了面试官发过来的远程面试链接
对面是一位身穿格子衬衫的有点中年发福的男子,
看着屏幕上面试官反光的头顶,一寸亮,一寸强!啧啧,你瞬间就感受面试官的实力恐怖如斯~~
但是你也不慌,因为你早已看了多遍《大厂秘籍》,再见面试官都是小场面
面试官从你的项目聊到了Java知识、数据库, 然后就到了面试基本必问的Redis
你心想这不踢到钢板了吗, 公司同事都尊称你是「Redis小王子」
但你还是忍住了心中的沸腾,面色平静、假装着小白等着面试官提问
面试官: 小伙汁, 你能告诉我Redis支持哪些数据结构吗?
Redis 5 种基本数据类型对应以及对应的底层数据结构分别是
数据类型 | 底层数据结构 | 应用场景 |
---|---|---|
String | 简单动态字符串(SDS) | 常规热点数据,分布式锁 |
Hash | 哈希表、压缩列表 | 结构化数据、对象存储 |
List | 双向链表(LinkedList)、压缩列表(ZipList) | 评论、商品等列表数据 |
Set | 整数数组、哈希表 | 适合交集、并集、查集操作, 如朋友圈共同好友 |
Sort Set(Zset) | 跳表(SkipList)、压缩列表 | 排行榜 |
Redis 还支持 3 种特殊的数据类型:
数据类型 | 应用场景 |
---|---|
Bitmap(位图) | 用二进制记录状态 |
HyperLogLog(基数统计) | 访问 ip 数统计, 网站UV统计 |
GEO(地理位置) | 存储地理位置信息 |
面试官接着就问到:那你讲下这几种底层数据结构吧
简单动态字符串(SDS)
Redis 是用 C 语言写的, 没有直接用C的字符串, 而是自己构造了
简单动态字符串(simple dynamic string,SDS)类型
struct sdshdr{
int len;//记录buf数组中已使用字节的数量
int free; //记录 buf 数组中未使用字节的数量
char buf[];//字符数组,用于保存字符串
}
好处是获取字符串长度复杂度为 O(1)(C 字符串为 O(N)), 通过len属性校验杜绝了缓存区的溢出
跳跃表(SkipList)
将有序链表中的部分节点分层,每一层都是一个有序链表。
1、可以快速查找到需要的节点 O(logn) ,额外存储了一倍的空间
2、可以在O(1)的时间复杂度下,快速获得跳跃表的头节点、尾结点、长度和高度。
压缩表(Ziplist)
压缩列表并不是对数据利用某种算法进行压缩,而是将数据按照一定规则编码在一块连续的内存区域,目的是节省内存。
Pipeline有什么好处,为什么要用pipeline?
Redis的pipeline功能的原理是 客户端通过一次性将多条redis命令发往Redis 服务端,减少了每条命令分别传输的IO开销。同时减少了系统调用的次数,因此提升了系统的吞吐能力。
(答得这么好,都有点佩服自己了)
面试官心想,小伙汁不错嘛,答得这么流畅,看来是没少看《大厂秘籍》,接着就问到:那你是怎么实现分布式锁的
通过Redis命令
SET key value[EX seconds][PX milliseconds][NX]
- EX seconds: 设定过期时间,单位为秒
- PX milliseconds: 设定过期时间,单位为毫秒
- NX: 仅当key不存在时设置值
争取锁的时候,执行这条命令
返回ok 代表抢到了锁可以继续执行 (Redis里key不存在)
否则就终止用户操作
如何解决数据一致性问题
可以监听mysql binlog消息,对于mysql的update、insert、delate变更数据。
利用消息队列, 推送刷新redis缓存数据。
如何解决热Key问题
-
本地缓存是最常用的解决方案, 例如guavaCache, 命中本地缓存服务端直接返回, 降低redis集群压力
-
数据分片, 通过将热点数据分散存储在多个Redis节点上,避免单个节点负载过高,也是解决热点Key问题常用的策略。
-
限流, 防止系统过载
-
预热,提前将热key加载到缓存中
面试官心想:这小伙汁看来是有备而来,得放个大招让他看看。那你说一说缓存穿透、缓存击穿、缓存雪崩的理解
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:
1)接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
3)采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力。
缓存击穿
缓存击穿是指当缓存中某个热点数据过期了,在该热点数据重新载入缓存之前,有大量的查询请求穿过缓存,直接查询数据库。这种情况会导致数据库压力瞬间骤增,造成大量请求阻塞,甚至直接挂掉。
解决方案:
1)设置热点数据永远不过期,异步线程处理。
2)使用分布式锁,保证同一时刻只能有一个查询请求重新加载热点数据到缓存中,这样,其他的线程只需等待该线程运行完毕,即可重新从Redis中获取数据。
缓存雪崩
缓存雪崩是指当缓存中有大量的key在同一时刻过期,或者Redis直接宕机了,导致大量的查询请求全部到达数据库,造成数据库查询压力骤增,甚至直接挂掉。
解决方案:
针对第一种大量key同时过期的情况,解决起来比较简单,只需要将每个key的过期时间打散即可,使它们的失效点尽可能均匀分布。或者设置key永不过期等
针对第二种redis发生故障的情况,部署redis时可以使用redis的高可用方案部署主从+哨兵,Redis cluster,避免全盘崩溃
(大家可以先关注企鹅君公众号哦,我会继续更新Redis高可用篇详解这个问题哦~)
面试结束
小伙汁你针不戳,给你发Offer了,能不能早点来公司上班呀
你心想自己手里还有几个其他大厂的Offer呢,还得问下网友考虑选哪个好呢
你当然没把心里话说出来,假装镇定回复合适的话,争取早点来公司。
好的。面试官 心想这小伙汁有点东西,必须把他招进公司,赶紧联系hr给他工资加满。
你感叹《大厂秘籍》果然有用,再也不用担心没有Offer了
赶紧让你的小伙伴也分享点赞收藏!!!
总结
技术面试其实并不难,但是也没有什么捷径,(当然博主希望《大厂秘籍》可以帮助读者少走弯路)平时多看多总结。在面试的时候,可以试着通过自己的项目引导面试官向你熟悉的领域提问,比如你的简历项目里写到了使用Redis解决了XX问题,这时候面试官基本都会问你更细节的东西,这样在你提前准备下逻辑清晰, 有理有据的讲出如何解决问题会在面试官心里加不少分, 那一个个Offer还不到手就来
创作不易,你的关注分享就是博主更新的最大动力, 每周持续更新
微信搜索【 企鹅君 】第一时间阅读(比博客早一到两篇), 关注还能领取资料
求关注❤️ 求点赞❤️ 求分享❤️ 对博主真的非常重要
企鹅君原创|GitHub开源项目github.com/JavaDance 欢迎Star和完善