极客大学架构师训练营 0 期 week 09 作业
请简述 JVM 垃圾回收原理
引用计数法与可达性分析:当对象的引用为 0 时,表明对象可以被回收;但是如果两个对象相互引用不能进行回收;通过 GC ROOTS 方法栈桢中的局部变量、已加载类的静态变量、JNI handles、已启动且未停止的 Java 线程来标记可达对象。
Stop-the-world 以及安全点:在进行垃圾回收时需要停止其他线程的工作,停止其他线程时必须保证其他线程运行到安全点。
垃圾回收的三种方式
a. 标记清除:把死亡对象所占据的内存标记为空闲内存,并记录在一个空闲列表(free list)之中。当需要新建对象时,内存管理模块便会从该空闲列表中寻找空闲内存,并划分给新建的对象。
b. 标记压缩:把存活的对象聚集到内存区域的起始位置,从而留下一段连续的内存空间。这种做法能够解决内存碎片化的问题,但代价是压缩算法的性能开销。
c. 复制:把内存区域分为两等分,分别用两个指针 from 和 to 来维护,并且只是用 from 指针指向的内存区域来分配内存。当发生垃圾回收时,便把存活的对象复制到 to 指针指向的内存区域中,并且交换 from 指针和 to 指针的内容。复制这种回收方式同样能够解决内存碎片化的问题,但是它的缺点也极其明显,即堆空间的使用效率极其低下。
设计一个秒杀系统,主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
挑战和问题:
秒杀系统最需要考虑的:
高性能。秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。本专栏将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这 4 个方面重点介绍。
一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,我将用一篇文章来专门讲解如何设计秒杀减库存方案。
高可用。 虽然我介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,我们还要设计一个 PlanB 来兜底,以便在最坏情况发生时仍然能够从容应对。专栏的最后,我将带你思考可以从哪些环节来设计兜底方案。
架构方案及思路
架构原则:“4 要 1 不要”
数据要尽量少
请求数要尽量少
路径要尽量短
依赖要尽量少
以及不要有单点
动静分离
这就涉及对用户请求路径进行合理的架构了。根据架构上的复杂度,有 3 种方案可选:
实体机单机部署;
统一 Cache 层;
上 CDN。
有针对性地处理好系统的“热点数据”
流量削峰
思路:排队、答题、分层过滤。
性能优化
手段 :减少编码、减少序列化、Java 极致优化、并发读优化。
减库存
下单减库存,即当买家下单后,在商品的总库存中减去买家购买数量。下单减库存是最简单的减库存方式,也是控制最精确的一种,下单时直接通过数据库的事务机制控制商品库存,这样一定不会出现超卖的情况。但是你要知道,有些人下完单可能并不会付款。
付款减库存,即买家下单后,并不立即减库存,而是等到有用户付款后才真正减库存,否则库存一直保留给其他买家。但因为付款时才减库存,如果并发比较高,有可能出现买家下单后付不了款的情况,因为可能商品已经被其他人买走了。
预扣库存,这种方式相对复杂一些,买家下单后,库存为其保留一定的时间(如 10 分钟),超过这个时间,库存将会自动释放,释放后其他买家就可以继续购买。在买家付款前,系统会校验该订单的库存是否还有保留:如果没有保留,则再次尝试预扣;如果库存不足(也就是预扣失败)则不允许继续付款;如果预扣成功,则完成付款并实际地减去库存。
plan B
限流、降级、拒绝服务
评论