写点什么

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

用户头像
wgl
关注
发布于: 2020 年 11 月 24 日
架构师训练营第 1 期 - 第 9 周 - 学习总结

9.1 数据库的基本原理

数据库架构:

数据库连接器 --- 为每个连接请求分配一块专用的内存空间用于会话上下文管理。

语义分析与优化器---将各种复杂嵌套的 SQL 进行语义等价转化,得到有限几种关系代数计算结构,并利用索引等信息进一步进行优化。

执行计划 -- mysql> explain select * from users where id = 1;

为什么 PrepareStatement 更好?

1.PrepareStatement 会预先提交带占位符的 SQL 到数据库进行预处理,提前生成执行计划, 当给定占位符参数,真正执行 SQL 的时候,执行引擎可以直接执行,效率更好一点。

2.PrepareStatement 可以防止 SQL 注入攻击。

聚簇(cu 4 声调)索引:聚簇索引的数据库记录和索引存储在一起。

MySQL 数据库的主键就是聚簇索引,主键 ID 和所在的记录行存储在一个 B+树中。

非聚簇索引在叶子节点记录的就不是数据行记录,而是聚簇索引,也就是主键。

通过非聚簇索引找到主键索引,再通过主键索引找到行记录的过程也被称作回表

合理使用索引

不要盲目添加索引,尤其在生产环境中

  1. 添加索引的 alter 操作会消耗较长的时间(分钟级)

  2. Alter 操作期间,所有数据库的增删改操作全部阻塞,对应用而言,因为连接不能释放,事实上,查询也被阻塞。

 删除不用的索引,避免不必要的增删开销。

使用更小的数据类型创建索引:int 4 字节bigint 8 字节Timestamp 4 字节Datetime 8 字节

数据事务特性 ACID

  1. 原子性(Atomicity): 事务要么全部完成,要么全部取消。如果事务崩溃,状态回到事务之前(事务回滚)。

  2. 隔离性(Isolation): 如果 2 个事务 T1 和 T2 同时运行,事务 T1 和 T2 最终的结果是相的,不管 T1 和 T2 谁先结束,隔离性主要依靠锁实现。

  3. 持久性(Durability): 一旦事务提交,不管发生什么(崩溃或者出错),数据要保存在数据库中。

  4. 一致性(Consistency): 只有合法的数据(依照关系约束和函数约束)才能写入数据库。

数据库事务日志

进行事务操作时,事务日志文件会记录更新前的数据记录,然后再更新数据库中的记录,如果全部记录都更新成功,那么事务正常结束,如果过程中某条记录更新失败,那么整个事务全部回滚,已经更新的记录根据事务日志中记录的数据进行恢复,这样全部数据都恢复到事务提交前的状态,仍然保持数据一致性。


LSN:一个按时间顺序分配的唯一事务记录日志序列号。

Ø  TransID:产生操作的事务 ID。

Ø  PageID:被修改的数据在磁盘上的位置。

Ø  PrevLSN:同一个事务产生的上一条日志记录的指针。

Ø  UNDO:取消本次操作的方法,按照此方法回滚。

Ø  REDO:重复本次操作的方法


9.2 JVM 虚拟机架构原理

构成:1.类加载器 2.运行时数据区 3. 执行引擎

java 字节码文件

java 所有的指令有 200 个左右,一个字节(8Bit)可以存储 256 种不同的指令信息,一个这样的字节称为字节码(Bytecode)。

在代码的执行过程中,JVM 将字节码解释执行,屏蔽对底层操作系统的依赖,

JVM 也可以将字节码编译执行

如果是热点代码,会通过 JIT 动态地编议为机器码,提高执行效率。

字节码执行流程

Java 字节码文件编议过程

Java 源文件 -> 词法解析 ---(token 流)-->语法解析 ->语义分析 -> 生成字节码 -> 字节码

类加载器的双亲委托模型


自定义类加载器的意义何在:

  1. 隔离加载类: 同一个 JVM 中不同组件加载同一个类的不同版本。

  2. 扩展加载类: 从网络、数据库等处加载字节码。

  3. 字节码加密: 加载自定义的加密字节码,在 ClassLoader 中解密。

堆:每个 JVM 实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都入在这个堆中,并由应用所有的线程共享。

堆栈:JVM 为每个新创建的线程都分配一个堆栈。对于一个 Java 程序来说,它的运行就是通过对堆栈的操作来完成的。

建立一个对象时从两个地方分配内存,在堆中分配的内存实际存放这个对象,在堆栈中分配内存存放指向这个堆对象的引用。


方法区--主要存放从磁盘加载进来的类字节码,而程序运行过程中创建的类实例存放在堆中。

每个线程都用自己的 Java 栈,Java 栈里存放着方法运行期的局部变量。

当前线程执行到哪 一行字节码指令,这个信息就被存放在程序计数器寄存器中。


线程工作内存 & volatile (立即可见)

Java 内存模型规定在多线程情况下,线程操作主内存变量,需要通过线程独有的工作内存拷贝主内存变量副本来进行。

一个共享变量(类的成员变量、类的静态成员变量)被 volatile 修饰之后,保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他线程是立即可见的。


9.3 JVM 垃圾回收性能分析

启动参数:

标准参数:

运行模式: -server, -client

类加载路径: -cp , -classpath

运行调试: -verbose

系统变量:-D

非标准参数:

-Xms 初始堆大小

-Xmx 最大堆大小

-Xmn 新生代大小

-Xss 线程堆栈大小

非Stable参数,此类参数各个JVM实现会有所不同,将来可能会随时取消

-XX:-UseConcMarkSweepGC 启动CMS垃圾回收。

JVM性能诊断工具:

基本工具:JPS,Jstat,Jmap,Jstack

集成工具:JConsole,JVisualVM

JPS用来查看host上运行的所有Java进程的pid(jvmid).

jstat 是JDK自带的一个轻量级小工具。对Java应用程序的资源和性能进行实时的命令行的监控。包括了对Heap size和垃圾回收状况的监控。

例:jstat -gcutil 当前运行的java进程号 interval count

jmap是一个可以输出 所有内存中对象的工具,可以将VM中的heap以二进制输出成文本。

使用方法:jmap -histo pid>a.log

jmap -dump:format=b,file=1 PID

jstack可以查看JVM内的线程堆栈信息。


9.4 Java 代码优化技巧及原理

java.util.concurrent

最佳线程数 = [任务执行时间/(任务执行时间-IO等待时间)]*CPU内核数

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,-->就是存在竞态条件。

导致竞态条件发生的代码区--> 称作 临界区。

在临界区中使用适当的同步可以避免竞态条件。


java线程安全:

  1. 基础类型的局部变量是线程安全的。

  2. 方法局部的对象引用(如果在方法中创建的对象不会逃逸出该方法,那么它就是线程安全的)

  3. 对象的成员变量(对象成员存储在堆上。如果两个线程同时更新同一个对象的同一个成员变量,那这个代码就不是线程安全的。)

ThreadLocal

Java内存泄漏:

  1. 长生命周期对象

  2. 静态容器(例如 static的Map,Set,List 等)

  3. 缓存

合理使用线程池和对象池

创建对象的步骤:

1.静态代码段

2.静态成员变量

3.父类构造函数

4.子类构造函数

计算机的任何问题都可以通过虚拟层(或者中间层)解决

  1. 面向接口编程

  2. 7 层网络协议

  3. JVM

  4. 编程框架

  5. 一致性hash算法虚拟代实现


系统性能优化案例:秒杀系统


发布于: 2020 年 11 月 24 日阅读数: 27
用户头像

wgl

关注

正走在系统架构设计师路上的程序员。 2017.12.07 加入

还未添加个人简介

评论

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