面试不说点分布式的东西,面试官都有点看不起我呀

现在的面试和几年前的面试差距很大了,现在培训机构出来的同学很多都占一大部分,而且那张口要的可是真的有点多,甚至比一些工作两三年的朋友们还多,不排除有一些大牛的存在,但是还是有一些不是很给力的,但是想一口吃撑的,而有经验的面试官,分分钟就能看出来你到底是有工作经验还是没有工作经验的。而分布式中的内容,将会是极其重要的一点内容。

分布式缓存

Redis

首先我们想到缓存的第一反应是 Redis,毕竟用 Redis 做缓存的还是比较多的,而在 Redis 做缓存的在比如说很多的培训机构中会有什么大型的电商项目做铺垫,然后在其中加上 Redis,但是很多时候是不知道为什么去使用这个缓存,在面试官那里,只要一问这个关于为什么使用缓存和我们在使用使用缓存时候出现的问题的时候就很容易凉凉。

那么是什么问题呢?

Redis的“二八定律”

那么这个 “二八定律” 是个什么意思呢?其实说白了就是 :80%的业务访问集中在20%的数据上,这是为了减轻数据库的压力和提高网站的数据访问速度。

阿粉在这里就不想给大家罗列代码了,这个代码你在网上搜索,绝对是一大堆一大堆的,只要你能细心的看完代码是什么意思,那么你就对 “二八定律”算是有了一个了解的意思了。

而这个 “二八定律”在你使用 Redis 中算是比较基础的问题了,那就接着往下说。

Redis的冷热数据

那么什么是冷热数据呢?

其实这个冷数据和热数据区分就是访问频次。

  • 需要被计算节点频繁访问的在线类数据是属于热数据

  • 对于离线类不经常访问的数据,比如企业备份数据、业务与操作日志数据、话单与统计数据就是冷数据

而问到这个关于冷热数据处理的时候,很多时候又会给你关联到 LRU 算法,关于这个算法,之前阿粉就已经解释过了,跑题了跑题了,我们继续回来。

而关于 Redis 冷热数据识别和交换,那么肯定也是你可以和面试官聊上一聊的,而阿里云的自主研发的 Redis 混合存储,就是全兼容Redis协议和特性的混合存储产品,通过将部分冷数据存储到磁盘,在保证绝大部分访问性能不下降的基础上,大大降低了用户成本并突破了内存对Redis单实例数据量的限制。

大家可以看一下来自百度上的关于冷热数据识别和交换的一个图

而这个冷热数据处理就得把 Redis 来真正的进行划分了,我们可以把 Key 都当成热数据,这样的话,我们可以用及其微小的代价来维护所有的 Key,并且保证所有的 Key 的访问性能是一致的,毕竟嘛,这个数据要经常访问的,那么 Value 呢?我们可以根据这个访问频次来做出正确的选择,Value大小等维度选取出部分value作为冷数据后台异步存储到磁盘上直到内存小于制定阈值为止。

就这个你要和面试官掰扯掰扯的话,怎么不得掰扯个十几二十分钟?

Redis为什么这么快

其实在问这个问题的时候,面试官的引申含义就出来了,为什么这么快,你肯定会说,Redis单线程的,就是快呀,但是这样就正好的跳下了这个大坑,为什么这么快?–单线程。为什么单线程?不知道?不知道的话,你就一首凉凉送给自己吧。

其实你在回答单线程之前的时候,可以在分析之前加上一些关于为什么 Redis 这么快的内容,比如:

  • 基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);相对于硬盘操作,那差距不是一点半点。

  • 使用多路I/O复用模型,非阻塞IO;

  • 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

  • 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

最后在说这个单线程,之前阿粉也给大家讲述过关于什么是多路复用 IO 模型了,这样在最后你说Redis的单线程给出了最好的铺垫呀,那么为什么 Redis 是个单线程就那么快呢?

既然前面说了,Redis 是一个基于内存的,那么影响 Redis 的因素就只会存在于内存的大小的问题上了,

1
2
3
4
5
6
7
8
9
Redis is single threaded. How can I exploit multiple CPU / cores?
It's not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.

However, to maximize CPU usage you can start multiple instances of Redis in the same box and treat them as different servers. At some point a single box may not be enough anyway, so if you want to use multiple CPUs you can start thinking of some way to shard earlier.

You can find more information about using multiple Redis instances in the Partitioning page.

However with Redis 4.0 we started to make Redis more threaded. For now this is limited to deleting objects in the background, and to blocking commands implemented via Redis modules. For future releases, the plan is to make Redis more and more threaded.

你在 Redis 官网上去看的时候阿粉都有一拳把屏幕锤个稀碎的冲动。

敷衍我呀,这翻译出来的意思就是直接告诉你 Redis 是单线程的,其实在理解这个单线程的时候,就又牵扯到这个 IO 多路复用上来了,采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,而我们复用的就是那单单的一个线程,感觉像死循环一样,你要是选择这么给面试官说,那么面试官一定会让你再把多路复用给他解释的明明白白的。

深度探测 java IO

再次推荐这个文章,阿粉的杰作,给大家讲多路复用,并且讲述了 IO ,完美。

Redis雪崩

说到这个阿粉真的是面试的时候从来就没有说没被面试官diss的时候,只要提到这个问题的时候,面试官总是呵呵哒,那我在这里就把阿粉了解到的关于 Redis 雪崩的一些情况分享给大家,万一大家遇到不像阿粉遇到过的面试官这么变态的呢?

什么是雪崩?

缓存雪崩就是指由于缓存的原因,导致大量请求到达后端数据库,从而导致数据库崩溃,整个系统崩溃,发生灾难。

其实还有一种情况也会出现这种问题,例如某个时间点内,系统预加载的缓存周期性集中失效了,也可能会导致雪崩。

也就是说,某一热点 Key 的请求在某一主机上超过该主机网卡上限时,由于流量的过度集中,会导致服务器中其它服务无法进行。如果热点过于集中,热点 Key 的缓存过多,超过目前的缓存容量时,直接就给怼崩溃了,就你接水,本来只想着接一桶水,结果卡没拔,硬生生给你的5L桶里面怼了了10L水,硬怼能不出事嘛!

这时候我们可以通过加锁的方式能处理一下雪崩的问题,

项目中用到了Redis分布式锁,我了解了一下背后的原理

就你出去面试你要能吧这些关于分布式缓存的说明白了,面试加分++++;

分布式数据库

说实话,之前阿粉从来没想到面试官会问分布式数据库的问题,那么我们也顺带把分布式数据库来分析一下吧。

为什么需要分布式数据库,一个数据库难道不好么?

就像现在我们这技术越来越发达,每天逛淘宝,逛京东,产生的数据,交易数据,查看的数据,最终来源还是要保存在我们的数据库中,而这样也就慢慢的出现了瓶颈,存储不够,而如果你使用的是 MySql 数据库的话,说白了不还是一个单机版本的数据库么?只要是单机,就必然会遇到的一个问题就是存储问题,因为存储是硬需求,而CPU和内存如果不够的话,只是性能不好,并不会直接否定方案或者架构。

也就是说,如果我们的数据量超标了,那么分布式的数据库是势在必行的。

而目前流行的关于处理分布式的数据库的就是几个,使用中间件,就像阿里的水彧,就是阿里的中间件部门的,这个在阿里的云栖大会的吐槽大会上的,大家有兴趣的可以看看。

MyCat

MyCat的实现架构大概上上图所示,其实如果只看图的话,这样的架构真是完美无缺,自动分片,自动聚合,分布均衡都实现的非常好。

但是 MyCat同样的是有很多问题的,因为很多的培训机构在培训中也会给学员们普及这个关于Mycat的一些内容,但是这相当于自己给自己挖坑,遇到给力的面试官一样是让你凉凉。

假如给你说 :分片多了的情况下,性能是如何保证损失最小的?

来自某大神的回答:

1
比如10个分片,如果一个语句的执行会涉及到这十个分片,那在每个分片上重写语句之后,就要分别在这十个分片上执行对应的语句了,执行时是串行,还是并行?串行的话,性能必然会下降10倍以上,所以做得好点的话,就是并行了,但并行的实现方法是,在MyCat这个连接上面,创建10个线程,去处理这十个节点的执行情况,那这样的连接多了,MyCat产生的对系统的冲击就非常大了,性能还是不行。当然也可以说,这里做了连接池,没错,是可以的,但MyCat是这样做的么?这样做了性能又如何呢?如果有一个超时,整个访问就失败了。

虽然 MyCat 有很多的缺陷,但是使用MyCat的用户其实还是挺多的,,因为需求有,但真的是没有解决方案,选择使用,实则无奈之举,而且还是开源的免费的,免费的你还想说啥是吧?关于怎么使用 Mycat 和更多 MyCat的内容之后的内容更加精彩,敬请期待!

Java Geek Tech wechat
欢迎订阅 Java 极客技术,这里分享关于 Java 的一切。