写点什么

架构师训练营第 1 期第 9 周学习总结

用户头像
好吃不贵
关注
发布于: 2020 年 11 月 22 日
架构师训练营第 1 期第 9 周学习总结

本周主要学习了数据库的基本原理,JVM 虚拟机架构原理,JVM 垃圾回收性能分析,Java 代码优化技巧及原理,同时分析了系统性能优化的案例,秒杀系统的设计。

数据库的基本原理

数据库一般使用 prepare statement 预编译,这样,提交数据时,不会影响到最后的执行计划。可以防止 SQL 注入攻击。原理是语法树已经生成好了,不会再把输入当做 SQL 语句。核心组件是连接器,词法分析,语法分析和语义分析。

B+树是 MySQL 存储的结构,聚簇索引表示数据库记录和索引存储在一起。非聚簇索引的叶子节点存的不是数据,而是聚簇索引。要合理使用索引,但索引太多,也会导致问题,要删除不用的索引。数据库事务遵守 ACID 的原则:Atomicity 要么全部完成,要么全部取消,Isolation 两个事务 T1 和 T2 同时的处理,最终结果相同,靠锁实现。Durability 一旦提交,不管发生什么,数据都保存在数据库中。Consistency,合法数据才能写入数据库中。

日志使用 log record,用 LSN 按时间分配的唯一事务记录日志序列号。还有 TransID,PageID,PrevLSN,UNDO,REDO 等字段。

JVM 虚拟机架构原理

JVM 的组成部分是三部分:类加载器,运行期数据区(方法区、堆、Java 栈、程序计数寄存器),以及执行引擎。对象是在堆里的,但变量在栈里。JVM 是一个 Java 进程,执行引擎就像 CPU,看起来像个完整的计算机一样。

Java 的所有指令有 200 个左右,一个字节存 256 种不同的指令信息。一个这样的字节成为字节码(Bytecode)。屏蔽对底层操作系统的依赖。所有的字节码都是 cafe babe 开头的,是 Java 字节码的魔术数。多次执行的指令,会交给编译器编译为字节码去执行,否则用解释器去解释执行。Java 编译词法解析、语法解析、语义分析、生成字节码。

类加载器是分层加载的。向上询问是否已加载。Application -> Platform -> Bootstrap ClassLoader。自定义类加载器,隔离加载类,同样的 class 类名,为每个 war 包分配一个 classLoader。同一 JVM 中不同组件加载同一个类的不同版本。扩展加载源,从网络、数据库等处加载字节码。字节码加密,加载后解密。

JVM 中的堆和栈用处不同。每个 JVM 实例唯一对应一个堆。每个线程都分配一个栈,运行就是通过对栈的操作来完成的。所有对象的存储空间都是在堆中分配的,对象的引用是在栈中分配,建立对象从两个地方都分配内存,栈中对象的引用指向堆里的空间。

方法区是特殊的堆,存的是类字节码,程序计数器 PC(Program Counter)指向当前运行的指令。当 JVM 进入启动类的 main 方法时,为应用程序创建一个主线程。main 方法里的代码就会被这个主线程执行。每个线程有自己的 Java 栈。

线程工作内存和主内存中数据变量值可能是不一样的。但不能每次执行指令都去主内存获取。Volatile 修饰后,一定会从主内存中去读,Save 和 Load 操作在工作内存和主内存间同步。编译流程是.java 文件通过 Java 编译器编译为.class 文件。运行期环境会从编译环境拿字节码。

Java 内存垃圾回收性能分析

可达性分析算法实现。从栈帧的局部变量或方法区的静态变量出发。将引用的对象进行标记,然后看标记的对象是否引用了其他对象,继续标记,剩下的就是需要清理的。回收的三种方式是清理,压缩,复制。可视化的方式。清理是标记为空闲,缺点是碎片化,不好使。压缩会通过拷贝,把数据放到一起。复制是把空间分成两部分,复制到另一个空间去。原来的空间可以使用。

分代垃圾回收,老年代和新生代,是方法内部的生存时间。生存时间短的,放到较小区域里。新生代分 Eden 区,存刚创建的,大部分可以直接回收,Eden 区满了之后,用的是复制算法,放到 From 区。如果 From 区满了,再拷贝出对象放到 To 区。如果 To 区也满了,放到老年代。老年代也满了的话,再对老年代垃圾回收。有两种回收,Young GC 和 Full GC(新老一起回收)

回收器算法有串行回收器,并行回收器,并发回收器 CMS 和 G1 回收器。串行所有线程都停止,垃圾回收线程只有一个。并行回收器有多个垃圾回收线程。并发回收分成了 4 个阶段,初始化标记(stop the world,但时间短)、并发标记(回收和用户线程并发执行)、重标记(可能不准,用户线程 stop the world)、并发清理。并发回收对用户时间的线程影响小。G1 垃圾回收分为更小的两千个区域,速度更快。Eden,Survivor,old,Humongous 区域。主要用 max gc 暂停时间控制。指定时间后,会根据期望的执行时间来回收。

Java 启动参数有三种,标准参数,非标准参数和非 stable 参数,所有 JVM 实现都必须实现这些参数的功能,而且向后兼容。

JVM 性能诊断工具有基本的是 JPS,JSTAT,JMAP,JSTACK,集成的工具有 JConsole,JVisualVM。

JPS 看 host 上所有的 Java 进程的 pid(jvmid),参数有-l, -q, -m, -v 等。主要是-q 找到 JVM 本身的 pid,或者通过-v 看 JVM 的参数。

JSTAT 主要是对垃圾回收的监控,jstat -gcutil 94685 1000 10

进程 ID,输出 1000ms,输出 10 次

JMAP 可以输出所有内存中的对象,将 VM 中的 heap,以二进制形式输出文本。使用方法是 jmap -histo pid > a.log,将其保存到文本中去。可以对比出 GC 回收了哪些对象。

jmap -dump:format=b file=f1, 可以将 PID 进程的内存 heap 输出到 f1 文件里。


jstack 可以看到 JVM 的线程堆栈信息。可以看到进程中的线程有哪些,以及线程的调用栈。

JVisualVM 可以更加可视化 CPU,Thread 的使用情况。

秒杀系统设计

原系统扩容 100 倍,服务器不可能短时间内增加到 1 万台。单独开发一个秒杀软件,构建新秒杀系统。跟原来系统完全隔离的,而是全新做系统。做新东西容易,老东西上做新的东西,问题反而更多。把系统,需求,业务约束隔离开,理清了,可以解决,混在一起,很难解决。

服务器准备,带宽准备(CDN:Chinacache,借用 CCCC CDN),

核心思路:先做隔离。新的沙盒,新的东西隔离在里面。做新的,比维护旧的容易。

网站并发秒杀系统组成:秒杀商品列表,秒杀商品介绍,下单部分。前两个是静态的,放在 CDN,后面是动态的,放在服务器。支付部分不需要变,因为成功的只有 50 多个客户。

设计原则

  1. 静态化。JS 自动更新技术把动态页面转化为静态页面。

  2. 并发控制,防秒杀器。只放最前面的一部分人进入秒杀系统,不是所有的都能进来。

  3. 简化流程。砍掉不必要的分支流程,比如数据库查询。下单成功作为秒杀成功标志。支付在 1 天内完成即可。

  4. 前端优化。YSLOW 原则提升页面响应速度。


用户头像

好吃不贵

关注

还未添加个人签名 2018.11.20 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第 1 期第 9 周学习总结