架构师训练营 4 期 第 9 周
作业一(至少完成一项):
请简述 JVM 垃圾回收原理
什么时 GC
GC(垃圾收集, Garbage Collection ),不是一个 Java 独有的概念,在计算机历史上出现的时间比 Java 早很多。 Java 语言来自于 C++,在 C++中,每个程序员就如同上帝一样,管理自己所需要的内存(申请,释放等),但是一旦程序员忘记了(当程序比较复杂时,就会经常发生),就可能造成资源浪费甚至内存泄露。 Java 吸取了 C++的经验,又要避免犯同样的错误,不由程序员自己管理内存,而是通过 GC 来处理,GC 会在合适的时间进行垃圾回收,避免无效的对象一直占用内存空间。
如何判断对象的无效
GC 需要对无效的对象进行回收,那么如何判断对象已经是垃圾了呢。主要有两种方式:
引用计数法 针对每个对象,只需要记住被引用的次数,当引用计数变为 0 时,这个对象就可以被安全地回收,不过可能有循环引用的问题,需要额外的管理才能处理。比如 Python 和 PHP 等平台/语言使用的就是引用计数法
可达性分析 以一系列垃圾收集根对象(GC Roots)为起始,通过引用关系向下搜索,找到所有可到达的对象形成引用链,那些不在引用链的对象就可以处理了。Java、C#等语言使用的就是可达性分析。
垃圾收集算法
在 JVM 中垃圾收集算法基本上有这么几种,判断是否是垃圾都是使用的可达性分析。
标记—清除(Mark and Sweep)
标记—清除是最经典的垃圾收集算法。它的主要步骤有两步:
标记 通过将需要清除的对象和可达对象区分开
清除 将不可达对象占用的内存回收
但是这种算法会有几个问题:
基本上大部分对象都是要清除的,将所有对象标记之后再清除效率太低
清除之后会造成内存空间碎片话,可能导致没有合适的内存可用
标记-复制算法
标记-复制算法,该算法再垃圾回收过程中会移动所有存活的对象,将存活的对象移动到另一块空闲的区域。 其优势是标记和复制可以同时进行。 不足是需要一个额外的内存区间,来存放所有的存活对象。 现代商用的虚拟机大多采用该算法来回收新生代的内存。
标记-整理算法
因为老年代的特点,可能很多对象都会存活,所以不能使用标记复制-算法(对象存活高,复制效率就地)。 所以有了标记-整理算法,该算法将所有被标记的对象(存活对象),迁移到内存空间的起始处,消除了“标记—清除算法”与标记-复制算法的不足。 优势是碎片整理之后,分配新对象就很简单,不会再导致内存碎片问题 缺点就是 GC 暂停时间会增加,因为需要将所有对象复制到另一个地方,然后修改指向这些对象的引用。
设计一个秒杀系统
主要的挑战和问题有哪些?核心的架构方案或者思路有哪些?
秒杀系统的特点
正常的购物系统一般的流程都是查询商品、创建订单、填写地址、付款、商家发货
秒杀系统与一般的系统相比有以下特点:
大幅推广,少量商品,低廉价格
准时上架,瞬时并发量高,瞬时售空
主要挑战
由于秒杀系统的特点,我们可以得出秒杀系统需要满足的要求:
支持高并发读写
准时开始
高可用
设计一个秒杀系统,主要遇到的问题是:
不影响已有的系统
日常使用的服务器一般支撑不住,如何避免服务器压力过大
如何避免超卖
如何避免刷单不能提前暴露接口如何避免恶意请求
解决方式或思路
使用单独的服务器去服务秒杀系统,与现有的系统隔离开,避免瞬时的高并发影响现有的系统
资源静态化 设计单独的商品详情等页面
提升网络利用率 临时购买带宽,使用 CDN 网络缓解服务器压力
限流 使用多级限流措施 争取在每一级页面都设置阈值避免过多的请求进入下一级,如果失败直接返回
使用队列 异步处理请求,避免对后端系统的压力、
使用缓存 减少数据库的压力
不能提前点亮购买按钮 使用 JavaScript 脚本控制,加上随机版本号(例如 xx.js?v=32353823),这样就不会被浏览器、CDN 和反向代理服务器缓存。到时间后使用 Javascript 控制按钮等逻辑
保护 url 动态生成 url,防止用户提前下单
作业二:根据当周学习情况,完成一篇学习总结
周主要讲解了数据库架构原理、JVM 原理、Java 代码优化思路以及如何设计一个秒杀系统
数据库架构原理
数据库结构
连接器 数据库连接器会为每个连接请求分配一块专用的内存空间用于会话上下文管理。建立连接对数据库而言相对比较重,需要花费一定的时间,因此应用程序启动的时候,通常会初始化建立一些数据库连接放在连接池里,这样当处理外部请求执行 SQL 操作的时候,就不需要花费时间建立连接了。
语法分析器 先进行词分析法,将 SQL 文本一系列关键词和字符串,然后分析这些信息是否满足 SQL 语法
语义分析与优化器 语义分析与优化器就是要将各种复杂嵌套的 SQL 进行语义等价转化,得到有限几种关系代数计算结构,并利用索引等信息进一步进行优化。
执行引擎 根据执行计划选择合适的索引获取数据
索引
聚簇索引 数据库记录和索引存储在一起。 MySQL 数据库的主键就是聚簇索引,主键 ID 和所在的记录行存储在一个 B+树中 非聚簇索引 在叶子节点记录的就不是数据行记录,而是聚簇索引,也就是主键。 通过非聚簇索引找到主键索引,再通过主键索引找到行记录的过程也被称作回表。
合理的使用索引:
不要盲目添加索引,尤其在生产环境中添加索引的 alter 操作会消耗较长的时间(分钟级)Alter 操作期间,所有数据库的增删改操作全部阻塞,对应用而言,因为连接不能释放,事实 上,查询也被阻塞。
删除不用的索引,避免不必要的增删开销
使用更小的数据类型创建索引 int 4 字节 bigint 8 字节,Timestamp 4 字节 Datetime 8 字节
事务
事务特性 ACID
原子性(Atomicity): 事务要么全部完成,要么全部取消。 如果事务崩溃,状态回到事 务之前(事务回滚)。
隔离性(Isolation): 如果 2 个事务 T1 和 T2 同时运行,事务 T1 和 T2 最终的结果是相同 的,不管 T1 和 T2 谁先结束,隔离性主要依靠锁实现。
持久性(Durability): 一旦事务提交,不管发生什么(崩溃或者出错),数据要保存在数 据库中。
一致性(Consistency): 只有合法的数据(依照关系约束和函数约束)才能写入数据库。
以 MySQL 的 InnoDB 引擎为例讲述,如何保证 ACID
ACD 是通过 Redo Log 和 Undo Log 实现的
I 是通过锁来实现的
JVM 虚拟机原理
运行时内存结构
线程独有: 线程栈、程序计数器、本地线程栈
线程共享:堆,方法区
字节码相关
类使用的几个步骤
编译成字节码
加载字节码
链接验证 确保 class 文件结构正确,可能引起其他接口或类的加载,但不需要进行验证和准备准备 将 static 变量赋值为其默认值 确切值在初始化阶段解析 将虚拟机常量池中的符号引用替换为直接引用
初始化
加载器:
Bootstrap ClassLoader 加载 jdk lib 核心代码
Extension ClassLoader 加载 ext
System ClassLoader 加载其他
自定义的
加载模式,双亲委派模式,先委托父加载器加载,不能加载在自己加载
垃圾回收
第一题有讲解
秒杀系统
第二题有讲解
版权声明: 本文为 InfoQ 作者【引花眠】的原创文章。
原文链接:【http://xie.infoq.cn/article/2022d79a538a5b728196e6614】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论