架构训练营第九周 - 作业
作业
请简述 JVM 垃圾回收原理
设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些
作业一
目前,Java 主流的 VM 是 HotSpot VM 。关于 HotSpot 架构如下:
图中 Java 堆事用来保存实例或者对象的空间,是垃圾回收的主要目标。
Java 堆区域划分:
新生对象都是在 eden 中,当回收时,将 eden 中还在使用的对象复制到 survivor 中,遇到大对象 survivor 不够用时,会直接复制到老年代,由 tenured 做分配担保。
当回收再次发生时,会把 survivor 中存货下来的对象,复制到老年代。
JVM 的垃圾回收主要是通过实现某种回收算法的垃圾回收收集器,来收集和删除未引用的对象,释放内存。
垃圾回收主要涉及三个问题:
怎么知道对象是否存活
垃圾收集算法
实现某种算法的垃圾收集器
对象是否存活
在堆里面存放着 Java 世界几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要判断对象是否存活。
引用计数算法
引用计数算法(Reference Counting)实现简单,判定效率也很高。给对象中添加一个引用计数器,每当一个地方引用它时,计数器值就加 1;引用失效时,计数器值就减 1;计数器为 0 的对象就是不可能再被使用的。
Python 语言、游戏脚本领域被广泛应用的 Squire 中都使用了引用计数算法进行内存管理。但是,java 虚拟机里没有用,主要原因是很难解决对象之间相互循环引用的问题
可达性分析
可达性分析(Reachability Analysis),基本思路是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始往下搜索,搜索所走过的路程称为引用链(Reference Chain),当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象不可用。
Java 语言中,可作为 GC Roots 的对象包括以下几种:
虚拟机栈(栈帧中的本地变量表)中引用的对象;
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中 JNI(Native 方法)引用的对象
垃圾收集算法
常见的垃圾收集算法。
标记-清除算法
算法分为‘标记’、‘清除’两个阶段。
首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
复制算法
复制(Copying),将可用内存按容量分为大小相等的两块,每次只使用其中的一块。 当这一块的内存用完了,将还存活的对象复制到另外一块上去。把已使用过的内存空间一次清理掉。
实现简单,运行高效,内存使用率不高,用于回收新生代。
IBM 研究表明,新生代中 98%的对象都是在第一次 GC 时被回收掉,不需要按照 1:1 分配空间。
HotSpot 虚拟机默认 Eden 和 Survivor 比例是 8:1,只有 10%的内存会被浪费。
Survivor 空间不够时,需要依赖老年代进行分配担保,新生代收集下来的存活对象直接进入老年代。
标记-整理算法
标记-整理(Mark-Compact)算法,标记所有存活对象,向一端移动,然后直接清理掉端边界意外的内存。
分代收集算法
根据对象存活周期不同,将 Java 堆分为新生代和老年代。
新生代,采用复制算法。
老年代采用‘标记-清理’或者‘标记-整理’算法。
垃圾收集器
如果说,收集算法是内存回收的方法论,那么,垃圾收集器就是内存回收的具体体现。
Java 虚拟机规范没有规范如何实现垃圾收集器。不同的厂商、版本的虚拟机实现可能会有很大差别。
下面,基于 JDK1.7 Update14 之后的 HotSpot 虚拟机讨论收集器。
作业二
对于秒杀系统,有几个注意点:
请求数据尽量少,从而减少 cpu 消耗
访问路径尽量短,减少节点消耗
强依赖尽量少,减少加载时间
不要有单点,要有备份
减少额外请求,减少加载时间
秒杀系统一般都是独立的,不建议和其他业务系统共存。越简单越好。
对于高性能优化,常用的策略:
集群
缓存
异步
秒杀系统,一致性是比较重要的,保证在高压环境下,数据的准确性、一致性。
架构参考:
版权声明: 本文为 InfoQ 作者【无心水】的原创文章。
原文链接:【http://xie.infoq.cn/article/584b2d6774a098fb6f98dcd97】。文章转载请联系作者。
评论