JVM 垃圾回收原理 & 秒杀系统设计见解
JVM 垃圾回收
是对 java 虚拟机堆中的不再被使用的对象就行回收。通过一种可达性分析算法,识别可回收的垃圾对象。
具体过程:
什么样的对象可以进行回收?
从栈帧中的局部变量或方法区的静态变量出发,将这些变量引用的对象进行标记,然后再标记这些被引用的对象中其他被引用的对象,所有标记过的对象都是使用中的,剩余的对象就是属于可回收的垃圾对象。
如何进行垃圾回收?
回收有三种方法:1.清理,所谓清理就是将垃圾对象占用的空间标记为空闲,并记录在一个空闲列表里,当需要创建新对象时,就直接从空闲列表中找一段空闲内存分配给新对象。2.压缩,从堆空间头部开始,将存活对象拷贝放在一个连续的内存空间中,其余空间便成了连续的空闲空间。3.复制,将堆空间分成两部分,只在其中一部分创建对象,当这部分空间被对象占满时,就将标记的存活对象复制到另一部分空间中。
回收过程中如何对内存空间进行管理?
分代垃圾回收。将内存分为新生代老年代。
新生代分为 Eden 区,From 区,To 区。创建新对象都在 Eden 区,当 Eden 区内存占满时,进行垃圾回收,将标记对象复制到 From 区,继续使用 Eden 区创建新对象。当 Eden 区再次被占满时,就对 Eden 区和 From 区同时进行对象标记,将标记对象一起复制到 To 区。然后继续使用 Eden 区创建新对象。当 Eden 区再次被占满时,就对 Eden 区和 To 区同时进行对象标记,将标记对象一起复制到 From 区。如此反复。当多次从 From 拷贝到 To 区后,仍然没有被回收的对象就会被拷贝到老年代。
使用什么样的过程进行回收?
垃圾回收器算法。
串行回收器,当内存空间占满时,会触发一次 stop the world,停止所有正在运行的应用线程,单线程对垃圾对象进行回收。
并行垃圾回器,当内存空间占满时,触发 stop the world,停止所有正在运行的应用线程,多个垃圾回收线程对垃圾对象进行回收。
以上两种方式不适合对响应时间要求高的实时应用场景,对批处理形式的场景友好。
并发回收器 CMS,回收线程和应用线程同时运行,先进性初始化标记,再并发标记,最后再重新标记触发一次 stop the world,但停止时间较短,然后再进行并发清理。
G1 回收器,分为 Eden 区,survivor 区,old 区,humongous 区。内存分成 2000 个小区域,根据内存使用情况,依次触发对 Eden 区,survivor 区,old 区的回收,每次回收也需要 stop the world,但停止时间极短,毫秒级。
秒杀系统。
挑战和问题。
短时间内,并发数急剧增加,对现有正常运行的应用会造成极大的冲击。按照一般的网站应用架构,秒杀开始前,不停刷页面,会对应用和数据库造成极大的压力。对网络带宽的挑战,图片的传输,会占用大量带宽,由于大量用户刷新页面,远超出平时刷新页面传输图片时占用的带宽。下单请求 URL 获取,如果和平时获取下单请求的 URL 方式一样,则会造成秒杀未开始就可以进行拍买。
秒杀系统设计的构思方案。
秒杀应用独立部署,与其他正常使用的应用隔离开来。
秒杀页面静态化,而不是从数据库进行读取,免除高并发对应用的访问和读取数据库带来的毁灭性伤害。
临时租借网络带宽,短期租用 CDN,减少对本地服务期的压力。
动态生成随机下单页面 URL,防止提前购买造成的损失。
设计的核心思想,要使页面最大化的简单,包含数据量最小化,并使页面静态化,隔离应用环境,去除数据库访问。
评论