架构师训练营第九周作业
题目一:简述 JVM 垃圾回收原理。
说 JVM 垃圾回收原理前,先说一下应用的内存申请和释放。我们知道,一个软件要运行起来,必须得在内存里面分配好相应的内存。在 C 语言里面,对应的操作就是 mallc()和 free()两个函数,对应内存的申请和释放。从程序的运行角度来说,按需申请和用完就释放,确实可以做到高效的内存使用和极低的内存占用,这是 C/C++这类编译型语言的优势所在。但是从软件开发工程角度来看,由于申请完内存以后,忘记释放导致的内存泄露,最终应用崩溃的例子,屡见不鲜。广大开发人员迫切需要一门有内存的管理的语言。Java 的垃圾回收(GC)也就是从这个时候推出。从本质上来说,JVM 的垃圾回收,就是自动调用 free()的一种机制,用了减轻程序员的负担。
那 JVM 如何实现垃圾回收的呢?有两个问题,第一个是哪些对象需要做垃圾回收?第二个是什么时候需要做垃圾回收?针对第一个问题,JVM 通过一个标记统计的办法,统计各个对象被引用的情况。如果这个对象没有其他的对象引用了,这个对象就会被标记为待回收,等待 GC 回收器进行内存回收。对第二个问题,在不同的 JVM 实现有不同的处理方案,列举如下:
串行回收:内存使用到某个临界值,挂起当前的所有工作线程,启动一个 GC 线程,一次性完成对象标记和回收的动作。
并行回收:内存使用到都给临界值,挂起当前的所有工作线程,启动多个 GC 线程,完成对象的标记和回收。这里的和串行的主要差异点是启动多个 GC 线程,降低 stop-the-world 的耗时。
并发回收 CMS: 为了进一步降低 stop-the-world 的耗时,cms 将 GC 过程分为 4 步,初始化标记,并发标记,重标记和并发清理。除了初始化标记和重标记需要 stop-the-world,其他都是并发执行,对应用的影响进一步降低。
分区回收 G1: G1 的设计理念是,设置期望的 stop-the-world 的时间间隔,通过将内存分区,进行对小块内存的快速回收,将 stop-the-world 时间控制在一个很小的范围,保证业务不受影响。
题目二:设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
秒杀系统是最近这些年随着电商的快速崛起带来的一种活动形态。其主要的特点有如下几点:
高并发:活动参与人数多,带来远高与平时的并发请求
大流量:秒杀页面会以非常高的频率进行刷新,带来海量的请求,对带宽的要求会非常高。
商品链接隐藏:商品链接需要在活动开始后才让客户进行访问,不然容易被人提前下单,导致活动失败。
针对秒杀系统的架构,主要有四个策略:
1. 与正常业务隔离
从业务的运行的角度来看,秒杀活动往往不是一种正常的业务形态(不过这几年秒杀已经变成常态运行了),所以为了避免对核心业务产生影响,基本的的思路是先分离。将秒杀系统和业务系统进行隔离,包括前端,后端,中间件,部署的机器,都进行隔离,避免秒杀系统影响核心业务的正常运行。
2. 用静态化解决大流量的问题
从流量的类型来说,秒杀类活动的流量大头是来着前端页面,包括页面内容,CSS,JS 这类的静态资源,占据绝大部分的带宽。这时候,CDN 这类的内容分发服务就可以派上用场。配合前端的缓存设置,后端的静态资源反向代理服务器,就可以保证在活动过程中,绝大部分页面请求是不需要请求到真正的后台服务,客观上面就解决了秒杀活动的流量过大的问题。静态化会涉及到 CMS 和静态资源压缩的相关细节问题,基本都比较成熟,基本按照步骤执行即可。
3. 用交易请求限流
由于参与秒杀的商品有限,最终应该处理的支付业务其实是有限的,这个时候就可以通过不同的策略,将超出商品数量的请求进行拦截,控制最终进入核心的交易系统的请求数量,保证系统能够正常的处理完成这些请求。这里面有几种细分的策略:
请求排队:一定时间内进入的用户都加入到队列里面,随机选取一定数量的用户进入最终的支付环节。这个思路是 12306 这边使用,保证在高并发的情况下面,公平分配有限的火车票。
交易预生成:针对某一件商品的秒杀用户,提前确定哪些用户能进入最终的支付环节,这时候绝大部分的用户其实就直接进入到秒杀结束的页面。这种思路小米用过,优点是核心系统全程只处理有限的请求,从源头就开始分流,多大的并发基本都是可控的。缺点就是,被人揭露以后,会被骂,被质疑不公平。
请求计数器:在秒杀开始的时候,开启全局的请求计数器,一旦请求数量到达某个阈值,就把剩余的请求全部拦截,定向到秒杀结束页面。这个思路优点来说,对用户来说就是比较公平,就是拼机器性能,拼网速,拼手速(不过后续有这个机器人的问题,需要由验证码技术解决)。缺点是,前置的全局计数器会是一个瓶颈点。
4. 交易链接隐藏
关键点有两个,第一是交易链接的随机化,也就是无法通过枚举或者暴力的方式猜测到,避免有人会提前下单。第二是交易链接秒杀后才放出,由于客户会在秒杀的过程中频繁刷新页面,一般的搞法是就是先预生成一个空的 js 文件,设置为不本地缓存,在秒杀开始以后再填充内容,由 js 动态填充秒杀交易链接,这样就能实现交易链接隐藏的目的。
版权声明: 本文为 InfoQ 作者【李日盛】的原创文章。
原文链接:【http://xie.infoq.cn/article/45ba0cd2a0105b47bac07294d】。文章转载请联系作者。
评论