《吊打面试官》系列-Redis终章_凛冬将至、FPX_新王登基

摘自:http://www.javashuo.com/article/p-bmsfawvg-gq.htmlhtml

 

《吊打面试官》系列-Redis终章_凛冬将至、FPX_新王登基面试

 

你知道的越多,你不知道的越多redis

点赞再看,养成习惯算法

前言

Redis在互联网技术存储方面使用如此普遍,几乎全部的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难。做为一个在互联网公司面一次拿一次offer的面霸(请容许我使用一下夸张的修辞手法),战胜了无数竞争对手,每次都只能看到无数落寞的身影失望的离开,略感愧疚,在一个寂寞难耐的夜晚,我痛定思痛,决定开始写《吊打面试官》系列,但愿能帮助各位读者之后面试势如破竹,对面试官进行360°的反击,吊打问你的面试官,让一同面试的同僚瞠目结舌,疯狂收割大厂offer!数据库

絮叨

男儿何不带吴钩,收取关山五十州 FPX 🐂B,LPL两年连冠🏆 🐂B!后端

看着金色的雨落下,我到窗边,发现天有点蓝,风有点绵,个人眼角又湿了!缓存

最近双十一讲道理有点忙的说,直接肝爆,就是这样做为暖男的我,仍是给大家挤出时间搞出终章,忍不住给本身点赞👍服务器

放个双十一照片证实真的忙,但愿别取关!!!微信

如今大家在看的时候,我应该还在睡觉哈哈。困🛌markdown

以前跟大家说的,限流降级,是否是在双十一又应验了,下单接口其实没挂,牺牲部分用户体验,保住服务器,你多点几下是能够成功的,等流量高峰过去了,全部的用户所有都恢复正常访问,服务器也没啥事。

去年退款接口被打崩了,今年阿里明显也聪明了不少。

正文

上几期吊打系列咱们提到了Redis的不少知识,还没看的小伙伴能够回顾一下

那提到Redis我相信各位在面试,或者实际开发过程当中对基本类型的使用场景,并发竞争带来的问题,以及缓存数据库双写入一致性的问题等,咱们有请下一位受害者。

面试开始

一个大腹便便,穿着格子衬衣的中年男子,拿着一个尽是划痕的mac向你走来,看着快秃顶的头发,心想着确定是尼玛顶级架构师吧!可是咱们腹有诗书气自华,虚都不虚。(这不是第一篇文章的面试官么?)

小伙子,你还记得我在第一章里面问过你,Redis有几种基础数据类型么?

嗯嗯,帅气的面试官,我确定记得,没齿难忘!!!

我特么谢谢你,都四面了还不给Offer!

那你能说一下他们的特性,还有分别的使用场景么?

行吧,那我先从String提及。

String:

这是最简单的类型,就是普通的 set 和 get,作简单的 KV 缓存。

可是真实的开发环境中,不少仔可能会把不少比较复杂的结构也统一转成String去存储使用,好比有的仔他就喜欢把对象或者List转换为JSONString进行存储,拿出来再反序列话啥的。

我在这里就不讨论这样作的对错了,可是我仍是但愿你们能在最合适的场景使用最合适的数据结构,对象找不到最合适的可是类型能够选最合适的嘛,以后别人接手你的代码一看这么规范,诶这小伙子有点东西呀,看到你啥都是用的String垃圾!

好了这些都是题外话了,道理仍是但愿你们记在内心,习惯成天然嘛,小习惯成就你。

String的实际应用场景比较普遍的有:

  • 缓存功能:String字符串是最经常使用的数据类型,不只仅是Redis,各个语言都是最基本类型,所以,利用Redis做为缓存,配合其它数据库做为存储层,利用Redis支持高并发的特色,能够大大加快系统的读写速度、以及下降后端数据库的压力。

  • 计数器:许多系统都会使用Redis做为系统的实时计数器,能够快速实现计数和查询的功能。并且最终的数据结果能够按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。

  • 共享用户Session:用户从新刷新一次界面,可能须要访问一下数据进行从新登陆,或者访问页面缓存Cookie,可是能够利用Redis将用户的Session集中管理,在这种模式只须要保证Redis的高可用,每次用户Session的更新和获取均可以快速完成。大大提升效率。

Hash:

这个是相似 Map 的一种结构,这个通常就是能够将结构化的数据,好比一个对象(前提是这个对象没嵌套其余的对象)给缓存在 Redis 里,而后每次读写缓存的时候,能够就操做 Hash 里的某个字段

可是这个的场景其实仍是多少单一了一些,由于如今不少对象都是比较复杂的,好比你的商品对象可能里面就包含了不少属性,其中也有对象。我本身使用的场景用得不是那么多。

List:

List 是有序列表,这个仍是能够玩儿出不少花样的。

好比能够经过 List 存储一些列表型的数据结构,相似粉丝列表、文章的评论列表之类的东西。

好比能够经过 lrange 命令,读取某个闭区间内的元素,能够基于 List 实现分页查询,这个是很棒的一个功能,基于 Redis 实现简单的高性能分页,能够作相似微博那种下拉不断分页的东西,性能高,就一页一页走。

好比能够搞个简单的消息队列,从 List 头怼进去,从 List 屁股那里弄出来。

List自己就是咱们在开发过程当中比较经常使用的数据结构了,热点数据更不用说了。

  • 消息队列:Redis的链表结构,能够轻松实现阻塞队列,可使用左进右出的命令组成来完成队列的设计。好比:数据的生产者能够经过Lpush命令从左边插入数据,多个数据消费者,可使用BRpop命令阻塞的“抢”列表尾部的数据。

  • 文章列表或者数据分页展现的应用。

    好比,咱们经常使用的博客网站的文章列表,当用户量愈来愈多时,并且每个用户都有本身的文章列表,并且当文章多时,都须要分页展现,这时能够考虑使用Redis的列表,列表不但有序同时还支持按照范围内获取元素,能够完美解决分页查询功能。大大提升查询效率。

Set:

Set 是无序集合,会自动去重的那种。

直接基于 Set 将系统里须要去重的数据扔进去,自动就给去重了,若是你须要对一些数据进行快速的全局去重,你固然也能够基于 JVM 内存里的 HashSet 进行去重,可是若是你的某个系统部署在多台机器上呢?得基于Redis进行全局的 Set 去重。

能够基于 Set 玩儿交集、并集、差集的操做,好比交集吧,咱们能够把两我的的好友列表整一个交集,看看俩人的共同好友是谁?对吧。

反正这些场景比较多,由于对比很快,操做也简单,两个查询一个Set搞定。

Sorted Set:

Sorted set 是排序的 Set,去重但能够排序,写进去的时候给一个分数,自动根据分数排序。

有序集合的使用场景与集合相似,可是set集合不是自动有序的,而Sorted set能够利用分数进行成员间的排序,并且是插入时就排序好。因此当你须要一个有序且不重复的集合列表时,就能够选择Sorted set数据结构做为选择方案。

  • 排行榜:有序集合经典使用场景。例如视频网站须要对用户上传的视频作排行榜,榜单维护多是多方面:按照时间、按照播放量、按照得到的赞数等。

  • Sorted Sets来作带权重的队列,好比普通消息的score为1,重要消息的score为2,而后工做线程能够选择按score的倒序来获取工做任务。让重要的任务优先执行。

    微博热搜榜,就是有个后面的热度值,前面就是名称

小结

Redis基础类型有五种,这个我在基础里面也有提到了,这个问题其实通常都是对P6如下,也就是1-3年左右的小伙伴多是会问得比较多的问题。

能回答出来五种我想你们均可以,可是不知道你们是否知道,五种类型具体的使用场景,以及何时用什么类型最合适呢?

要是你回答的很差,没说出几种数据类型,也没说什么场景,你完了,面试官对你印象确定很差,以为你平时就是作个简单的 set 和 get。因此看似很简单的面试题实则最容易看出你的深浅了,你们都要注意打好基础

你有没有考虑过,若是你多个系统同时操做(并发)Redis带来的数据问题?

嗯嗯这个问题我之前开发的时候遇到过,其实并发过程当中确实会有这样的问题,好比下面这样的状况

系统A、B、C三个系统,分别去操做Redis的同一个Key,原本顺序是1,2,3是正常的,可是由于系统A网络忽然抖动了一下,B,C在他前面操做了Redis,这样数据不就错了么。

就比如下单,支付,退款三个顺序你变了,你先退款,再下单,再支付,那流程就会失败,那数据不就乱了?你订单还没生成你却支付,退款了?明显走不通了,这在线上是很恐怖的事情。

那这种状况怎么解决呢?

咱们能够找个管家帮咱们管理好数据的嘛!

某个时刻,多个系统实例都去更新某个 key。能够基于 Zookeeper 实现分布式锁。每一个系统经过 Zookeeper 获取分布式锁,确保同一时间,只能有一个系统实例在操做某个 Key,别人都不容许读和写。

你要写入缓存的数据,都是从 MySQL 里查出来的,都得写入 MySQL 中,写入 MySQL 中的时候必须保存一个时间戳,从 MySQL 查出来的时候,时间戳也查出来。

每次要写以前,先判断一下当前这个 Value 的时间戳是否比缓存里的 Value 的时间戳要新。若是是的话,那么能够写,不然,就不能用旧的数据覆盖新的数据。

你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就必定会有数据一致性的问题,那么你如何解决一致性问题?

通常来讲,若是容许缓存能够稍微的跟数据库偶尔有不一致的状况,也就是说若是你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要作这个方案,即:读请求和写请求串行化,串到一个内存队列里去。

串行化能够保证必定不会出现不一致的状况,可是它也会致使系统的吞吐量大幅度下降,用比正常状况下多几倍的机器去支撑线上的一个请求。

把一些列的操做都放到队列里面,顺序确定不会乱,可是并发高了,这队列很容易阻塞,反而会成为整个系统的弱点,瓶颈

你了解最经典的KV、DB读写模式么?

最经典的缓存+数据库读写的模式,就是 Cache Aside Pattern

  • 读的时候,先读缓存,缓存没有的话,就读数据库,而后取出数据后放入缓存,同时返回响应。
  • 更新的时候,先更新数据库,而后再删除缓存

为何是删除缓存,而不是更新缓存?

缘由很简单,不少时候,在复杂点的缓存场景,缓存不仅仅是数据库中直接取出来的值。

好比可能更新了某个表的一个字段,而后其对应的缓存,是须要查询另外两个表的数据并进行运算,才能计算出缓存最新的值的。

另外更新缓存的代价有时候是很高的。是否是说,每次修改数据库的时候,都必定要将其对应的缓存更新一份?也许有的场景是这样,可是对于比较复杂的缓存数据计算的场景,就不是这样了。若是你频繁修改一个缓存涉及的多个表,缓存也频繁更新。可是问题在于,这个缓存到底会不会被频繁访问到?

举个栗子:一个缓存涉及的表的字段,在 1 分钟内就修改了 20 次,或者是 100 次,那么缓存更新 20 次、100 次;可是这个缓存在 1 分钟内只被读取了 1 次,有大量的冷数据

实际上,若是你只是删除缓存的话,那么在 1 分钟内,这个缓存不过就从新计算一次而已,开销大幅度下降。用到缓存才去算缓存。

其实删除缓存,而不是更新缓存,就是一个 Lazy 计算的思想,不要每次都从新作复杂的计算,无论它会不会用到,而是让它到须要被使用的时候再从新计算。

MybatisHibernate,都有懒加载思想。查询一个部门,部门带了一个员工的 List,没有必要说每次查询部门,都里面的 1000 个员工的数据也同时查出来啊。80% 的状况,查这个部门,就只是要访问这个部门的信息就能够了。先查部门,同时要访问里面的员工,那么这个时候只有在你要访问里面的员工的时候,才会去数据库里面查询 1000 个员工。

Redis 和 Memcached 有啥区别,为啥选择用Redis做为大家的缓存中间件?

Redis 支持复杂的数据结构:

Redis 相比 Memcached 来讲,拥有更多的数据结构,能支持更丰富的数据操做。若是须要缓存可以支持更复杂的结构和操做, Redis 会是不错的选择。

Redis 原生支持集群模式:

在 redis3.x 版本中,便能支持 Cluster 模式,而 Memcached 没有原生的集群模式,须要依靠客户端来实现往集群中分片写入数据。

性能对比:

因为 Redis 只使用单核,而 Memcached 可使用多核,因此平均每个核上 Redis 在存储小数据时比 Memcached 性能更高。而在 100k 以上的数据中,Memcached 性能要高于 Redis,虽然 Redis 最近也在存储大数据的性能上进行优化,可是比起 Remcached,仍是稍有逊色。

Tip:其实面试官这么问,是想看你知道为啥用这个技术栈么?你为啥选这个技术栈,你是否作过技术选型的对比,优缺点你是否了解,你啥都不知道,只是为了用而用,那你可能就差点意思了。

Redis 的线程模型了解么?

Redis 内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,因此 Redis 才叫作单线程的模型。它采用 IO 多路复用机制同时监听多个 Socket,根据 Socket 上的事件来选择对应的事件处理器进行处理。

文件事件处理器的结构包含 4 个部分:

  • 多个 Socket
  • IO 多路复用程序
  • 文件事件分派器
  • 事件处理器(链接应答处理器、命令请求处理器、命令回复处理器)

多个 Socket 可能会并发产生不一样的操做,每一个操做对应不一样的文件事件,可是 IO 多路复用程序会监听多个 Socket,会将 Socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。

面试结束

小伙子对你面试了四轮,你说话有理有据,逻辑清晰,来公司后确定是一把好手,我想要不你来当个人Leader吧,哈哈?

面试官别跟我开玩笑了,我跟您这样日积月累的技术专家仍是有不少差距的,您的经验和技术上的深度,没有很长时间的磨练是没法达到的,我还得多跟您学习。

好的,小伙子有点东西,你年少有为不自卑,知道什么是珍贵,就是你了来上班吧。

好的面试官,不过我想我在Java基础,MQ,Dubbo等等领域还有好多知识点您没问我,要不下次继续面我?

强行,为吊打下一期埋伏笔哈哈,下期写啥大家定!!!

能撑到最后,你本身都忍不住本身给本身点个赞了!

暗示点赞,每次都看了不点赞,大家想白嫖我么?大家好坏喲,不过我喜欢)。


《吊打面试官》Redis系列 ---- 全剧终


总结

既然都说了是Redis的终章我最后也作个Redis方面常见面试题,题目的总结,答案你们要去思考我前面的文章基本上都提到了,结果能够去我公众号回复【答案】获取,不过我仍是但愿你们能看到题目就能想到答案,而且记在心中,教你们怎么回答只是帮你们组织下语言,真正的场景解决方案仍是要你们理解的。

(周三之后出答案,我先睡会)

  • 0、在集群模式下,Redis 的 Key 是如何寻址的?分布式寻址都有哪些算法?了解一致性 Hash 算法吗?
  • 一、使用Redis有哪些好处?
  • 二、Redis相比Memcached有哪些优点?
  • 三、Redis常见性能问题和解决方案
  • 四、MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的数据都是热点数据?
  • 五、Memcache与Redis的区别都有哪些?
  • 六、Redis 常见的性能问题都有哪些?如何解决?
  • 七、在什么样的场景下能够充分的利用Redis的特性,大大提升Redis的效率?
  • 八、Redis的缓存雪崩、穿透、击穿了解么?有什么异同点?分别怎么解决?
  • 九、Redis的基本类型有哪些?他们的使用场景了解么?比较高级的用法你使用过么?
  • 十、Redis主从怎么同步数据的?集群的高可用怎么保证?持久化机制了解么?
  • 十一、为何 redis 单线程却能支撑高并发?
  • 十二、如何保证缓存和数据库数据的一致性?
  • 1三、项目中是怎么用缓存的,用了缓存以后会带来什么问题?

絮叨+

最后我想说的就是,我这四章只是介绍到了一些Redis面试比较常见的问题,其实还有不少点我都没回答到,你们若是为了对付面试可能是够用了,可是咱们技术人员仍是要保持对技术的敬畏心,你不能浅尝即止,仍是要深究的。

你永远只会用,不去考虑用了会带来的问题,以及出现问题以后的解决方案,我以为你大几率会停滞不前,既然入都入了这行了,为啥不武装一下本身。

其实学习技术是个反哺的过程,学习的时候可能你只是感受知识广度、深度上去了,一个知识点你这样,两个、三个知识点你都这样,最后你发现你的技术已经跟身边同样P6的仔不同了,这样你可能在团队重大项目的贡献都上去了,那P7的晋升概率是否是大了,钱是否是上去了,女友是否是好看了,房子是否是大了。

End

好了各位,以上就是这篇文章的所有内容了,能看到这里的人呀,都是人才,我后面会每周都更新几篇《吊打面试官》系列和Java技术栈相关的文章。若是你有什么想知道的,也能够留言给我,或者去公众号加我微信,我一有时间就会写出来,咱们共同进步。

很是感谢人才们能看到这里,若是这个文章写得还不错,以为「敖丙」有点东西的话 求点赞👍 求关注❤️ 求分享👥 求留言💬 对暖男我来讲很是有用

各位的支持和承认,就是我创做的最大动力,咱们下篇文章见!

敖丙 | 文 【原创】【转载请联系本人】


《吊打面试官》系列每周持续更新,能够关注个人公众号「 JavaFamily 」第时间阅读和催更(公众号比博客早一到两天哟),里面也有我我的微信有什么问题也能够直接滴滴我,我也是个新人,不过不影响咱们一块儿进步,做为渣男,我给不了你幸福,还给不了你温暖嘛?

相关文章
相关标签/搜索