写点什么

极客大学 - 架构师训练营 第九周作业

用户头像
9527
关注
发布于: 2020 年 11 月 16 日

作业一



题目一: 请简述 JVM 垃圾回收原理

在JVM运行时,数据区的三个非常重要的地方:



  • 堆(heap) : 他是最大的一块区域,用于存放对象实例和数组,是全局共享的.

  • 栈(stack) : 全称为虚拟机栈,主要存储基本数据类型,以及对象的引用,私有线程

  • 方法区(Method Area) : 在class被加载后的一些信息 如常量,静态常量这些被放在这里,在Hotspot里面我们将它称之为永生代



什么是JVM垃圾回收?

JVM的垃圾回收就是讲JVM堆中的已经不再被使用的对象清理掉,释放宝贵的内存资源。

JVM 通过一种可达性分析算法进行垃圾对象的识别,具体过程是:从线程栈桢中的局部变量,或者方法区的静态变量出发,将这些变量引用的对象进行标记,然后看这些被标记的对象是否引用了其他对象,继续进行标记,所有被标记的对象都是被使用的对象,而那些没有被标记的对象就是可回收的对象。在垃圾回收算法和垃圾收集器之前,首先要做的就是判断哪些对象已经“死去”,需要进行回收即不可能再被任何途径使用的对象。



一般来说,有两种思路可以判断对象的存活

引用计数算法

如果有其他对象对其引用,则计数器加一,引用失效的时候,计数器减一。计数器为0时则可以被回收。

弊端:无法解决对象互相引用的问题,他们是内存中的孤岛,但却无法被回收 例如: A.a = B;B.b = A



可达性分析算法

通过一系列称为GC Roots的对象作为起始点,然后向下搜索,走过的路径为引用链,如果一个对象到GC Roots 没有任何引用链,则说明此对象是不可达(不可用)的。



GC Roots Tracing 算法



四种引用

  1. 强引用

  2. 普通的引用方式, A a = new A() , 只要强引用还存在,GC就不会回收。

  3. 如果一个对象具有强引用,那垃圾回收器绝不会回收它。直到强引用的对象不使用或者超出对象的生命周期范围。则GC认为该对象不存在引用,这时候就可以回收这个对象。

  4. 当内存不足时,JVM宁愿抛出OutOfMemoryError的错误,使程序异常终止,也不会靠随意回收具有强引用对象来解决内存不足的问题。



  1. 软引用

描述有用但非必需的对象。在发生内存溢出异常之前,会把软引用的对象列为回收范围第二次再回收。如果第二次回收没有足够的内存,才抛出异常。 可以使用 SoftReference

内存空间充足时,垃圾回收器不会回收

内存空间不足时,就会尝试回收这些对象。只要垃圾回收器没有回收它,该对象就可以被程序使用



  1. 弱引用

GC 总会回收掉被弱引用关联的对象。 WeakReference



  1. 虚引用(幽灵引用,影子引用)

最弱的引用。能在被GC回收时得到一个通知。 phantomReference

虚引用主要用来跟踪对象被垃圾回收器回收的活动。 虚引用软引用弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中

垃圾回收算法

1. 标记-清除算法

标记清除算法有两个阶段,标记阶段和回收阶段。标记阶段将需要被清除的对象打上标签,回收阶段完成对于对象的回收。这种算法回收过后会产生大量内存碎片。

  1. 标记:首先标记出所有需要回收的对象

  2. 清除:在标记完成后统一回收所有被标记的对象

标记-清除算法主要有两个不足:

  1. 效率问题,标记和清除的两个过程效率都不高

  2. 标记-清除会产生大量不连续的内存碎片,这会导致在后面需要分配连续的大对象时,无法找到足够大的连续内存而导致不得不提前触发另一次垃圾收集动作



2. 复制算法

复制算法的大致思路如下,其执行过程如下图所示:



  1. 首先将可用内存分为大小相等的两块,每次只使用其中的一块。

  2. 当这一块的内存用完了,就将还存活的对象连续复制到另一块上面,然后把使用过的内存空间一次清理掉

复制算法的代价就是将内存缩小为原来的一半。



3. 标记-整理算法

标记-整理算法分为“标记”和“整理”两个阶段,执行过程如下图所示:

编辑

删除



  1. 标记:首先标记出所有需要回收的对象

  2. 整理:让所有的存活的对象都向一端移动,然后直接清除掉边界以外的内存



4. 分代收集算法

分代收集算法就是降Java堆分为新生代和老年代,根据其各自的特点采用最适当的收集算法。



  1. 新生代中大批对象死去,只有少量存活,就选用复制算法

  2. 老年代中对象存活几率高,没有额外的空间对它进行分配担保,就必须使用标记-清除或者标记-整理算法。



垃圾回收器

JVM垃圾收集器发展历程大致可以分为以下四个阶段: Serial(串行)收集器 -> Parallel(并行)收集器 -> CMS(并发)收集器 -> G1(并发)收集器

  • 串行回收器:一个垃圾回收线程,stw(stop-the-world)停止所有的用户线程回收。

  • 并行回收器:多个垃圾回收线程,stw停止所有线程回收垃圾。



并发回收期CMS分为以下4个阶段

  1. 初始标记:标记一下GC Roots能直接关联到的对象,会“Stop The World”。

  2. 并发标记:GC Roots Tracing,可以和用户线程并发执行。

  3. 重新标记:标记期间产生的对象存活的再次判断,修正对这些对象的标记,执行时间相对并发标记短,会“Stop The World”。

  4. 并发清除:清除对象,可以和用户线程并发执行。

G1回收器:其他收集器的工作范围是整个新生代或者老年代、G1收集器的工作范围是整个Java堆。在使用G1收集器时,它将整个Java堆划分为多个大小相等的独立区域(Region)器垃圾回收过程如下:

  1. 初始标记:仅标记GC Roots能直接到的对象,并且修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象。(需要线程停顿,但耗时很短。)

  2. 并发标记:从GC Roots开始对堆中对象进行可达性分析,找出存活对象。(耗时较长,但可与用户程序并发执行)

  3. 最终标记:为了修正在并发标记期间因用户程序执行而导致标记产生变化的那一部分标记记录。且对象的变化记录在线程Remembered Set  Logs里面,把Remembered Set  Logs里面的数据合并到Remembered Set中。(需要线程停顿,但可并行执行。)

  4. 筛选回收:对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。(可并发执行)

题目二: 秒杀系统

设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?



秒杀活动的本质其实是营销,通过秒杀活动以更低廉的价格换得更多的流量进来,提高知名度,吸引粉丝。

但秒杀活动本身由于吸引大量用户进来,会对系统造成巨大的冲击,如何承载这么大的并发量是秒杀需要考虑的,所以秒杀最主要考虑的关键问题其实是如何去有效的限流

可以设置三道阀门:

  • 列表页阀门,商品列表页点击详情按钮进入商品详情页,可以通过一个计数器进行控制进入详情页的人数,比如这里只允许1000人进入,其余超出的跳转到“秒杀结束”页。

  • 详情页阀门,商品详情页点击下单按钮进入订单提交页,同样是通过计数器进行控制进入的人数,比如这里为100人,那么最终只有100人可以进入提交订单的页面参与抢购。

  • 秒杀阀门,商品数量有限,比如100个人提交订单到订单系统,但只有10件商品,那么只允许前10个人下单成功,其余的90人进入“秒杀结束”页。

通过这三道阀门,可以逐步将流量限制到一个比较小的数量级,保证不会对后台订单系统造成冲击。如下图所示:



主要挑战
  • 高并发下保证系统可用性

  • 商品数据的一致性保障

  • 秒杀商品页面浏览/更新高可用

  • 秒杀按钮/功能高可用

  • 防黑客攻击/秒杀器

  • 下单/支付功能高可用

  • 开发和架构人力物力的花费

  • 如何最大程度的减少对已有系统的影响

主要面对的问题
  • 如何应对面对秒杀前大量用户的刷新请求?

  • 如何保障核心业务系统的稳定?

  • 如何保证秒杀商品订单数量不失控?

  • 如何确保秒杀商品在预定时间才可以抢购?

  • 如何规避机器人自动刷单?

核心的架构方案
  • 应对瞬时并发请求的处理与系统可用性保障

  • 预估用户量和系统资源,优化系统参数,保障系统资源高效协同工作

  • 整体评估现有核心系统能力,为解决方案提供指导

  • 功能页面动静分离,采用CDN等缓存方案,缩短用户请求路线,降低系统服务请求压力

  • 精简页面内容,删除不必要的内容,降低网络带宽消耗

  • 合并css和js等文件,减少用户http请求数量

  • 高并发页面静态化处理,减少不必要的请求

  • 减少不必要的系统依赖,保障各系统的稳定

  • 提前缓存热点数据,提升热点数据读取效率

  • 分级控制流量,避免大量的无效请求对核心系统的影响

  • 缓存节点虚拟化处理,降低某一缓存节点出现问题后的影响

  • 确保链路中无单点节点,保障系统高可用

  • 域名独立,方便针对不同请求进行特殊配置

  • 设计有效可行的PlanB方案,保证系统用户可以获得响应

  • 商品数据的一致性保障

  • 秒杀开始前不提供商品下单功能,秒杀开始生成随机验证信息,防止通过分析下单功能地址,然后通过系统自动抢单

  • 下单环节可以设置验证环节(答题、验证码等),降低一点下单页面瞬时高并发请求量,同时防止机器人自动刷单

  • 商品库存缓存维护,提高商品库存读写效率,降低核心数据库压力

  • 采用消息队列控制实际订单请求处理数量,可在实际缴款环节进行数量校验

  • 分层控制请求数量,减少关键节点的无效请求处理

  • 在有限的时间和资源里,如何打好手上的牌

  • 了解现有系统能力,现有系统能力充足,就直接使用

  • 现有能力不足,改造现有系统风险大、可行性不高

  • 最好的方案是针对秒杀设计独立的秒杀系统,摒弃一切不相关功能,做到功能单一,高效响应

  • 根据业务预案合理估算资源

  • 合理规划时间,抓住关键问题

  • 分析不可控因素,提前提出,做好可控预案

  • 平时注意提升自身能力,提高应对能力,超出能力范围内的事情做好评估

  • 做好应急预案

  • 备用带宽、服务器

  • 服务降级,当系统容量达到一定程度是,限制或关闭系统的某些非核心功能

  • 拒绝服务:万能出错页面 —— “秒杀活动已结束”



发布于: 2020 年 11 月 16 日阅读数: 39
用户头像

9527

关注

还未添加个人签名 2020.04.22 加入

还未添加个人简介

评论

发布
暂无评论
极客大学 - 架构师训练营 第九周作业