java核⼼技术卷pdf,总结到位
前⾔
今天的分享主要是讲下这个 redis,什么是缓存雪崩、穿透和击穿。这三个技术问题是我们平时开发⼯作中和⾯试过程中,必须要会的知识点,因为⽬前的互联⽹系统没有⼏个不需要⽤到缓存的,只要⽤到缓存的话,就需要掌握这三个技术问题。
基本上⽆论哪个⽼哥去⼤⼚⾯试,都会被问题这⼏个问题,所以作为⼀个互联⽹开发程序员来说,这个⼏个技术问题⼤家是需要搞懂的。⽽解决这⼏个问题的⽅案,通常有布隆过滤器,还有分布式锁。
布隆过滤器是1970年的⼀项技术,距今也有50年了,之所以能够应⽤⾄今,说明这项技术还是挺优秀的,它也是⾕歌搜索引擎所采⽤的⼀项技术,⾮常的⽕。这⾥就不展开说这个布隆过滤器了,后续会专门⽤⼀篇⽂章来讲这个布隆过滤器和分布式锁。
接下来我们正式来说下什么是redis的缓存雪崩、穿透和击穿。
ES 集架构演进之路
1、初始阶段
订单中⼼ES初始阶段如⼀张⽩纸,架设⽅案基本没有,很多配置都是保持集默认配置。整个集部署在集团的弹性云上,ES集的节点以及机器部署都⽐较混乱。同时按照集维度来看,⼀个ES集会有单点问题,显然对于订单中⼼业务来说也是不被允许的。
2、集隔离阶段
和很多业务⼀样,ES集采⽤的混布的⽅式。但由于订单中⼼ES存储的是线上订单数据,偶尔会发⽣混布集抢占系统⼤量资源,导致整个订单中⼼ES服务异常。
显然任何影响到订单查询稳定性的情况都是⽆法容忍的,所以针对于这个情况,先是对订单中⼼ES所在的弹性云,迁出那些系统资源抢占很⾼的集节点,ES集状况稍有好转。但随着集数据不断增加,弹性云配置已经不太能满⾜ES集,且为了完全的物理隔离,最终⼲脆将订单中⼼ES集部署到⾼配置的物理机上,ES集性能⼜得到提升。
3、节点副本调优阶段
ES的性能跟硬件资源有很⼤关系,当ES集单独部署到物理机器上时,集内部的节点并不是独占整台物理机资源,在集运⾏的时候同⼀物理机上的节点仍会出现资源抢占的问题。所以在这种情况下,为了让ES单个节点能够使⽤最⼤程度的机器资源,采⽤每个ES节点部署在单独⼀台物理机上⽅式。
但紧接着,问题⼜来了,如果单个节点出现瓶颈了呢?我们应该怎么再优化呢?
ES查询的原理,当请求打到某号分⽚的时候,如果没有指定分⽚类型(Preference参数)查询,请求会负载到对应分⽚号的各个节点上。⽽集默认副本配置是⼀主⼀副,针对此情况,我们想到了扩容副本的⽅式,由默认的⼀主⼀副变为⼀主⼆副,同时增加相应物理机。
订单中⼼ES集架设⽰意图
如图,整个架设⽅式通过VIP来负载均衡外部请求:
整个集有⼀套主分⽚,⼆套副分⽚(⼀主⼆副),从⽹关节点转发过来的请求,会在打到数据节点之前通过轮询的⽅式进⾏均衡。集增加⼀套副本并扩容机器的⽅式,增加了集吞吐量,从⽽提升了整个集查询性能。
下图为订单中⼼ES集各阶段性能⽰意图,直观地展⽰了各阶段优化后ES集性能的显著提升:
当然分⽚数量和分⽚副本数量并不是越多越好,在此阶段,我们对选择适当的分⽚数量做了进⼀步探索。分⽚数可以理解为MySQL中的分库分表,⽽当前订单中⼼ES查询主要分为两类:单ID查询以及分页查询。
分⽚数越⼤,集横向扩容规模也更⼤,根据分⽚路由的单ID查询吞吐量也能⼤⼤提升,但聚合的分页查询性能则将降低;分⽚数越⼩,集横向扩容规模也更⼩,单ID的查询性能也会下降,但分页查询的性能将会提升。
所以如何均衡分⽚数量和现有查询业务,我们做了很多次调整压测,最终选择了集性能较好的分⽚数。
4、主从集调整阶段
到此,订单中⼼的ES集已经初具规模,但由于订单中⼼业务时效性要求⾼,对ES查询稳定性要求也⾼,如果集中有节点发⽣异常,查询服务会受到影响,从⽽影响到整个订单⽣产流程。很明显这种异常情况是致命的,所以为了应对这种情况,我们初步设想是增加⼀个备⽤集,当主集发⽣异常时,可以实时的将查询流量降级到备⽤集。
那备⽤集应该怎么来搭?主备之间数据如何同步?备⽤集应该存储什么样的数据?
考虑到ES集暂时没有很好的主备⽅案,同时为了更好地控制ES数据写⼊,我们采⽤业务双写的⽅式来搭设主备集。每次业务操作需要写⼊ES数据时,同步写⼊主集数据,然后异步写⼊备集数据。同时由于⼤部分ES查询的流量都来源于近⼏天的订单,且订单中⼼数据库数据已有⼀套归档机制,将指定天数之前已经关闭的订单转移到历史订单库。
所以归档机制中增加删除备集⽂档的逻辑,让新搭建的备集存储的订单数据与订单中⼼线上数据库中的数据量保持⼀致。同时使⽤ZK 在查询服务中做了流量控制开关,保证查询流量能够实时降级到备集。在此,订单中⼼主从集完成,ES查询服务稳定性⼤⼤提升。
5、现今:实时互备双集阶段
期间由于主集ES版本是较低的1.7,⽽现今ES稳定版本都已经迭代到6.x,新版本的ES不仅性能⽅⾯优化很⼤,更提供了⼀些新的好⽤的功能,所以我们对主集进⾏了⼀次版本升级,直接从原来的1.7升级到6.x版本。
集升级的过程繁琐⽽漫长,不但需要保证线上业务⽆任何影响,平滑⽆感知升级,同时由于ES集暂不⽀持从1.7到6.x跨越多个版本的数据迁移,所以需要通过重建索引的⽅式来升级主集,具体升级过程就不在此赘述了。
java学习资源主集升级的时候必不可免地会发⽣不可⽤的情况,但对于订单中⼼ES查询服务,这种情况是不允许的。所以在升级的阶段中,备集暂时顶上充当主集,来⽀撑所有的线上ES查询,保证升级过程不影响正常线上服务。同时针对于线上业务,我们对两个集做了重新的规划定义,承担的线上查询流量也做了重新的划分。
备集存储的是线上近⼏天的热点数据,数据规模远⼩于主集,⼤约是主集⽂档数的⼗分之⼀。集数据量⼩,在相同的集部署规模下,备集的性能要优于主集。
然⽽在线上真实场景中,线上⼤部分查询流量也来源于热点数据,所以⽤备集来承载这些热点数据
的查询,⽽备集也慢慢演变成⼀个热数据集。之前的主集存储的是全量数据,⽤该集来⽀撑剩余较⼩部分的查询流量,这部分查询主要是需要搜索全量订单的特殊场景查询以及订单中⼼系统内部查询等,⽽主集也慢慢演变成⼀个冷数据集。
同时备集增加⼀键降级到主集的功能,两个集地位同等重要,但都可以各⾃降级到另⼀个集。双写策略也优化为:假设有AB集,正常同步⽅式写主(A集)异步⽅式写备(B集)。A集发⽣异常时,同步写B集(主),异步写A集(备)。
ES 订单数据的同步⽅案
MySQL数据同步到ES中,⼤致总结可以分为两种⽅案:
⽅案1:监听MySQL的Binlog,分析Binlog将数据同步到ES集中。
⽅案2:直接通过ES API将数据写⼊到ES集中。
考虑到订单系统ES服务的业务特殊性,对于订单数据的实时性较⾼,显然监听Binlog的⽅式相当于异步同步,有可能会产⽣较⼤的延时性。且⽅案1实质上跟⽅案2类似,但⼜引⼊了新的系统,维护成本也增⾼。所以订单中⼼ES采⽤了直接通过ES API写⼊订单数据的⽅式,该⽅式简洁灵活,能够很好的满⾜订单中⼼数据同步到ES的需求。
由于ES订单数据的同步采⽤的是在业务中写⼊的⽅式,当新建或更新⽂档发⽣异常时,如果重试势必会影响业务正常操作的响应时间。
所以每次业务操作只更新⼀次ES,如果发⽣错误或者异常,在数据库中插⼊⼀条补救任务,有Worker任务会实时地扫这些数据,以数据库订单数据为基准来再次更新ES数据。通过此种补偿机制,来保证ES数据与数据库订单数据的最终⼀致性。
遇到的⼀些坑
1、实时性要求⾼的查询⾛DB
推荐阅读:ES ⼏⼗亿数据检索 3 秒返回。
对于ES写⼊机制的有了解的同学可能会知道,新增的⽂档会被收集到Indexing Buffer,然后写⼊到⽂件系统缓存中,到了⽂件系统缓存中就可以像其他的⽂件⼀样被索引到。
然⽽默认情况⽂档从Indexing Buffer到⽂件系统缓存(即Refresh操作)是每秒分⽚⾃动刷新,所以这就是我们说ES是近实时搜索⽽⾮实时的原因:⽂档的变化并不是⽴即对搜索可见,但会在⼀秒之内变为可见。
当前订单系统ES采⽤的是默认Refresh配置,故对于那些订单数据实时性⽐较⾼的业务,直接⾛数据库查询,保证数据的准确性。
2、避免深分页查询
ES集的分页查询⽀持from和size参数,查询的时候,每个分⽚必须构造⼀个长度为from+size的优先队列,然后回传到⽹关节点,⽹关节点再对这些优先队列进⾏排序到正确的size个⽂档。
假设在⼀个有6个主分⽚的索引中,from为10000,size为10,每个分⽚必须产⽣10010个结果,在⽹关节点中汇聚合并60060个结果,最终到符合要求的10个⽂档。
由此可见,当from⾜够⼤的时候,就算不发⽣OOM,也会影响到CPU和带宽等,从⽽影响到整个集的性能。所以应该避免深分页查询,尽量不去使⽤。
3、FieldData与Doc Values
FieldData:
线上查询出现偶尔超时的情况,通过调试查询语句,定位到是跟排序有关系。排序在es1.x版本使⽤的是FieldData结构,FieldData占⽤的是JVM Heap内存,JVM内存是有限,对于FieldData Cache会设定⼀个阈值。
如果空间不⾜时,使⽤最久未使⽤(LRU)算法移除FieldData,同时加载新的FieldData Cache,加
载的过程需要消耗系统资源,且耗时很⼤。所以导致这个查询的响应时间暴涨,甚⾄影响整个集的性能。针对这种问题,解决⽅式是采⽤Doc Values。
Doc Values:
Doc Values是⼀种列式的数据存储结构,跟FieldData很类似,但其存储位置是在Lucene⽂件中,即不会占⽤JVM Heap。随着ES版本的迭代,Doc Values⽐FieldData更加稳定,Doc Values在2.x起为默认设置。
总结
以上是字节⼆⾯的⼀些问题,⾯完之后其实挺后悔的,没有提前把各个知识点都复习到位。现在重新好好复习⼿上的⾯试⼤全资料(含JAVA、MySQL、算法、Redis、JVM、架构、中间件、RabbitMQ、设计模式、Spring等),现在起闭关修炼半个⽉,争取早⽇上
岸
下⾯给⼤家分享下我的⾯试⼤全资料,如果你也有需要,
第⼀份是我的后端JAVA⾯试⼤全
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论