架构师训练营第 9 周 命题作业
一、请简述 JVM 垃圾回收原理
JVM 如何找到待回收的,不被使用的对象?
从线程栈帧中的局部变量,或方法区的静态变量出发,将这些变量引用的对象进行标记,然后看标记的对象是否引用了其他有对象,继续进行标记,最终剩余未被标记的对象,作为待回收的对象。
垃圾回收的过程有哪些方法?
清理: 清理对象占据的内存。JVM 将这些垃圾对象占用的内存空间标记为空闲状态,并记录到空闲列表,提供给应用程序再次使用。
压缩: 清理需被回收对象所占据的内存,并将不需要被回收的对象整理在连续的内存空间中。
复制:将堆空间分为两部分,只在其中一部分创建对象,这部分空间用完时,将标记过的可用对象复制到另一个空间中,再释放当前空间。
jvm 分代垃圾回收
jvm 在垃圾回收时,按照生命周期将对象所在区域划分为新生代与老年代。
新生代按照 8:1:1 的比例划分三个区域 Eden 区(伊甸园),from 区, to 区。
1、对象刚创建时,会直接进入新生代 Eden 区。
2、Eden 区满的时候,利用复制算法在新生代上进行垃圾回收,回收 Eden 与 from 区可被回收的对象,
eden 区上还在用的对象就也复制到了 from 区。注意这时候 from 区因回收会出现内存碎片。
3、如果在复制到 from 区的时候,发现空间不足(很有可能是内存碎片的广泛存在,导致较大的对象找不到连续的内存空间),jvm 会把 from 区中的可用对象与拷贝过来的可用对象复制到 to 区,并交换 from 区与 to 区的逻辑概念。如果此时,to 区依旧放不下,JVM 会把对象移至老年代,倘若此时老年代也无法分配空间,则会触发 full GC。
4、复制算法垃圾回收来回几次后,某些在新生代的对象依旧未被回收,它们会被从新生代拷贝到老年代。如果在拷贝前,发现老年代无法分配给这些对象内存空间时,会触发 full GC。
5、在执行 full GC 后,仍然无法给对象分配内存空间时,就会抛出熟悉的 OOM (OutOfMemoryError)
二、设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
主要的挑战与问题
1、高并发的用户请求
秒杀时间点上瞬间的高并发,会导致带宽迅速耗尽;服务器 CPU 负载 LOAD 飙高,停止响应;数据库压力过大瘫痪。
2、来自秒杀器的作弊
类型一:机器人秒杀前不断刷新页面,到时间点后,开始下单。
类型二:用 URL 跳过秒杀页面,直接进入下单页面下单。
解决方法
隔离
先做隔离,开发一套新的秒杀系统,不去影响现有的,版本迭代的项目。做个新项目的成本会比迭代原有项目的成本要低很多。其中包含域名隔离。
准备服务器与带宽
为构建秒杀服务器集群,准备图片服务器,静态服务器,交易服务器,style 服务器;同时准备带宽,提高图片上行带宽上限,准备 CDN 作为第一道防线拦住大部分的静态资源访问。如需快速部署可使用第三方服务商提供的服务。
提升手段:准备更轻量,更快速的服务器。
设计原则
1、静态化: JS 自动更新技术将动态页面转为静态页面。多张图片合成一张,内容压缩,合并 JS,避免发送 cookies 等;可以由后台定时地生成(如商品的)静态页面,推送到静态服务器上去。同时也需要一套由运营人员录入商品信息的系统。
2、并发控制,防秒杀器: 设置阀门,降低流量。只放最前面部分的请求进入秒杀系统。
3、简化流程:删掉不重要的查询,禁止模糊查询,留下最基本的功能,降低数据库压力;下单成功作为秒杀成功的标志,支付流程可以延长,比如提示用户 24 小时支付即可。
4、前端优化:根据 YSLOW 插件反馈的提升建议,调整页面代码。。
高并发的应对:
利用计数器树立三道阀门:允许进入秒杀页面的数量;秒杀页面允许点击购买的数量;订单生成页面可以提交订单的数量。
不能通过阀门的直接弹出秒杀结束。
如已参与过秒杀,也直接进入秒杀结束页面。
秒杀器的应对:
订单 ID 随机。
秒杀链接是一个以预先生成的随机 TOKEN 作为参数的 URL。
在秒杀时间点到达时,会更新一个包含商品 ID 与秒杀链接的 js。用户浏览器更新后才会点亮。而在秒杀时间点之前,该 JS 不包含这些信息,用户反复的请求,会从 CDN 中取,也不为后台服务带来压力。
评论