本文倒序。

作者:金山软件西山居技术经理 刘超

09-结束语丨栉风沐雨,砥砺前行!

结束nothing

08-模块七 实战演练场(4讲)

43丨记一次双十一抢购性能瓶颈调优20200803

1.限流实现优化

nginx 包含了两个限流模块:ngx_http_limit_conn_module和ngx_http_limit_req_module 前者限制单个ip单位时间内的请求数量,后者是用来限制单位时间内所有皮的请求数量。

配置:

limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
 location / {
 limit_conn addr 1
 }
}
http {
 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
 server{
 location / {
 limit_req zone=one burst=5 nodelay;
 }
}

在网关层,可以tongueolua编写OpenResty来实现一套限流功能,也可以通过现成的Kong安装插件来实现。

还可以基于服务才能实现接口的限流,通过Zuul RateLimit 活Guava RateLimiter实现。

42丨如何使用缓存优化系统性能?20200803 无重点

1.前端缓存

本地缓存

If-Modified-Since 字段与返回头部中的 Last- Modified 字段实现,也可以基于请求头部中的 If-None-Match 字段与返回头部中的 ETag 字段来实现。前者基于时间,后者基于唯一标示。

网关缓存

CDN

2.服务器缓存技术

Guava cache

Redis

41丨电商系统的分布式事务调优20200803 重要

1.分布式事务实现方式有多种,例如

XA协议实现的二阶段提交 2pc

DTP 模型,该模型规范了分布式事务的模型设计。DTP 规范中主要包含了 AP、RM、TM 三个部分,其中 AP 是应用程序,是事务发起和结 束的地方;RM 是资源管理器,主要负责管理每个数据库的连接数据源;TM 是事务管理器,负责事务的全局管理,包括事务的生命周期管理和资源的分配协调等。

三阶段提交3pc

3pc把2pc的准备阶段分为了准备阶段和预处理阶段。

第一阶段只是询问各个资源节点是否可以执行事务。

第二阶段 所有的几点反馈可以执行事务,才开始执行事务。

第三阶段 执行提交或回滚操作。RM、TM都引入了超时机制。

缺点:无法解决在最后提交全局事务时,由于网络故障无法通知到一些节点的问题,特别是回滚通知,会导致事务等待超时从而默认提交。

XA规范实现的事务提交,由于阻塞等性能问题,低性能、低吞吐。

TCC补偿性事务:最常用的分布式事务解决方案

分别在不同服务上连接数据源,提交数据库操作。

采用最终一致性的方式实现了一种柔性分布式事务,基于服务层实现的一种二阶事务提交。

三个阶段:

Try

Confirm

Cancel

缺点:对业务侵入性非常大,实现和维护成本高。

需要在设计的时候考虑预留资源;

需要编写大量业务性代码

考虑每个方法的幂等性

2.业务无侵入方案-Seata(Fescar)

40丨如何设计更优的分布式?20200728

1.数据库分布式锁

2.zookeeper分布式锁

3.Redis实现分布式锁

4.Redlock算法 redisson

07-模块六 数据库性能调优(6讲)

39丨答疑课堂:MySQL中InnoDB的知识点串讲 略,可以单独加强InnoDB 内容20200702

1.缓存池:不仅缓存了索引页和数据页,还包括了undo页、插入缓存、自适应哈希索引以及InnoDB的锁信息。

2.后台线程

Master Thread 主要负责将缓冲池中的数据异步刷新到磁盘中,初次之外还包括插入缓存,undo页的回收等。

IO Thread 是负责读写 IO 的线程,而 Purge Thread 主要用于回 收事务已经提交了的 undo log

3.存储文件

4.InnoDB 逻辑存储结构

InnoDB 逻辑存储结构分为表空间(Tablespace)、段 (Segment)、区 (Extent)、页 Page) 以及行 (row)。

表空间:

5.InnoDB 事务之 redo log 工作原理

6.LRU淘汰策略

InnoDB 则是将数据放在一个 midpoint 位置,通常这个 midpoint 为列 表长度的 5/8。避免一些不常查询的操作突然将热点数据淘汰出去。

38丨数据库参数设置优化,失之毫厘差之千里 略 20200702

1.SWAP 页交换:SWAP 分区在系统的物理内存不够用的时候,就会把物理内 存中的一部分空间释放出来,以供当前运行的程序使用。被释放的空间可能 来自一些很长时间没有什么操作的程序,这些被释放的空间的数据被临时保 存到 SWAP 分区中,等到那些程序要运行时,再从 SWAP 分区中恢复保存 的数据到内存中。

2.redo log 主要是为了解决 crash-safe 问题而引入的。

3.InnoDB Buffer Pool(IBP)是InnoDB存储引擎的一个缓冲池。

innodb_buffer_pool_size :默认128M,推荐配置IBP的大小为服务器内存的80%。

innodb_buffer_pool_instances:IBP被划分了多个实例,只有上面1G时才有用。

innodb_log_file_size:1g

innodb_log_buffer_size:InnoDB重做日志缓冲池的大小,默认8M

innodb_flush_log_at_trx_commit:控制重做日志从缓存写入文件刷新到磁盘中的策略,默认1

37丨电商系统表设计优化案例分析20200702

1.平时不用看,面试可略一眼

36丨什么时候需要分表分库20200702 看笔记即可

1.分布式事务,两阶段提交(2PC)以及补偿事务提交TCC.

2.中间件:Spring 实现的JTA,Fescar(seata)

3.跨节点JOIN查询问题

冗余基础表或者个别字段

4.跨节点分页查询问题

两套存储: 一套数据库,一套Elasticsearch

5.全局主键ID

uuid:性能差

redis分布式锁实现一个递增的主键ID,有一定性能损耗

Twiitter开源的分布式ID生产算法:snowflake。

6.扩容问题

2的倍数设置表数量

7.表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。

分表:指的是通过一定规则,将一张表分解成多张不同的表。比如将用户订单记录根据时间成多个表。

分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。

ALTER TABLE erp_bill_index PARTITION by RANGE(to_days(billdate))

35丨记一次线上SQL死锁事故:如何避免死锁?20200702

1.我们可以在 information_schema 数据库 中查询到具体的死锁情况

2.此节值得关注。

3.查看运行中事务:select * from information_schema.innodb_trx

当前出现的锁: select * from information_schema.innodb_locks

锁等待的对应关系 select * from information_schema.innodb_lock_waits

4.非唯一索引,RR事务隔离级别,for update 加锁类型为 gap lock。

34丨MySQL调优之索引:索引的失效与优化20200702

1.回表

基于主键查询可以直接获取到行信息,而基于辅助索引作为查询条 件,则需要进行回表,然后再通过主键索引获取到数据。

2.建立和使用索引 的调优方法

A覆盖索引优化查询

B自增字段作主键优化查询

C前缀索引优化

减小索引字段大小,可以增加一个页中存储的索引想,有效提高索引的查询速度,但又一定局限性,order by 无法使用前缀索引,无法吧前缀索引作为覆盖索引。

D防止索引失效

对索引进行函数操作或者表达式计算也会导致索引的失效

33丨MySQL调优之事务:高并发场景下的数据库事务调优20200701

1.行锁通过索引实现,如果不同过索引条件检索数据,行锁会升级到表锁。

2.优化高并发事务

结合业务场景,使用低级别事务隔离

避免行锁升级为表锁

控制事务的大小,减少锁定的资源量和锁定的时间长度。




hive 性能 hive性能调优实战pdf_数据


3.binlog + redo log 两阶段提交保证持久性

事务的回滚机制 保证原子性 要么全部提交成功 要么回滚

undo log + MVCC 保证一致性 事务开始和结束的过程不会其它事务看到 为了并发可以适当破坏一致性。

32丨MySQL调优之SQL语句:如何写出高性能SQL语句?

1.explain

type:结果值从好到差依次是:system > const > eq_ref > ref > range > index > ALL

2.通过 Show Profile 分析 SQL 执行性能 -new

3.常用的SQL优化

优化分页查询,利用子查询优化分页查询。

select count(*) 可以增加汇总统计。

4.是否开启了记录慢sql的功能,以及最大的执行时间

Show variables like 'slow_query%’;

Show variables like 'long_query_time';

06-模块五 设计模式调优(6讲)

31 丨 答疑课堂:模块五思考题集锦 20200703

1.单例和享元模式区别联系

单例模式更多的是强调减少实例化提升性能

享元模式更多的是强调共享相同对象或对象属性,以此节约内存使用空间

共性:

这两种设计模式也有共性,单例模式可以避免重复创建对象,节约内存空间,享

元模式也可以避免一个类的重复实例化。

2.work-thread模式中,如果要获取子线程的结果

jdk1.5后Future 类 ,性能比较糟糕。

jdk1.8中提供了CompletableFuture 类,它是基于异步函数式编程。相对阻塞式等待返回结果, CompletableFuture 可以通过回调的方式来处理计算结果,所以实现了异步非阻塞,从性 能上来说它更加优越了。

3.漏桶算法可以通过限制容量池大小来控制流量,而令牌算法则可以通过限制

发放令牌的速率来控制流量

4.策略模式和装饰者模式区别:

策略模式与装饰器模式则更为相似,策略模式主要由一个策略基类、具体策略类以及一个工厂环境类组成,与装饰器模式不同的是,策略模式是指某个对象在不同的场景中,选择的实现策略不一样。例如,同样是价格策略,在一些场景中,我们就可以使用策略模式实现。基于红包的促销活动商品,只能使用红包策略,而基于折扣券的促销活动商品,也只能使用折扣券。

30 丨 装饰器模式:如何优化电商系统中复杂的商品价格策略? 20200703

1.可借鉴 复杂情景 业务开发。

29 丨 生产者消费者模式:电商库存设计优化 20200703

1.问题:生产方则会因为瞬时高并发,而发生大量线程阻塞。面对这样的情况,你知道有

什么方式可以优化线程阻塞所带来的性能问题吗?

精选答案:

A.网关与服务之间增加令牌桶 或者mq 以保护秒杀服务不会被大的流量压垮.

B.在网关层中把请求放入到mq中,后端服务从消费队列中消费消息并处理;或者用有固定容 量的消费队列的令牌桶,令牌发生器预估预计的处理能力,匀速生产放入令牌队列中,满 了直接丢弃,网关收到请求之后消费一个令牌,获得令牌的请求才能进行后端秒杀请求, 反之直接返回秒杀失败

C限流

2.其他略

28丨如何使用设计模式优化并发编程?20200703

整体来讲没咋理解。

线程上下文设计模式 没太明白

Thread-Per-Message 设计模式

Thread-Per-Message 设计模式翻译过来的意思就是每个消息一个线程的意思。

Worker-Thread 设计模式

当主线程处理每次请求都非常耗时时,就可能出现阻塞问题,这时候我们可以考虑将主线程 业务分工到新的业务线程中,从而提高系统的并行处理能力。而 Thread-Per-Message 设 计模式以及 Worker-Thread 设计模式则都是通过多线程分工来提高系统并行处理能力的设 计模式。

27丨原型模式与享元模式:提升系统性能的利器-新知识 20200702

1.通过 clone 方法复制的对象才是真正的对象复制,clone 方法赋值的对象完全是一个独立 的对象。

2.浅拷贝

拷贝成员变量值,但对于对象的引用以及List等类型的成员属性,只能复制这些对象的引用了。super.clone()属于浅拷贝。

3.深拷贝

深拷贝就是基于浅拷贝来递归实现具体的每个对象。

4.原型模式使用场景:

循环体内创建对象时

Student stu = new Student();
 for(int i=0; i
 Student stu1 = (Student)stu.clone(); 
 }

5.为什么使用原型模式:

Object 类的 clone 方法是一个本地方法,它可以直接操作内存中的二进制流,所以性能相 对 new 实例化来说,更佳。


hive 性能 hive性能调优实战pdf_数据_02


享元模式

1.运用共享技术有效地最大限度地复用细粒度对象的一种模式。

2.使用场景

字符串常量,线程池就是享元模式的一种实现。

26丨单例模式:如何创建单一对象优化系统性能?

1.happens—before: 前一个操作的结果可以被后续的操作获取。这条规则规范了编译器对程序的重排序优化。

2.单例内部类 写法-new。

05-模块四·JVM性能监测及调优(3讲)

25丨答疑课堂:模块四热点问题解答

1.cms

2.G1 和 CMS 主要的区别在于:

CMS 主要集中在老年代的回收,而G1集中在分代回收,包括了年轻代的Young GC以及老年代的 Mix GC;

G1 使用了Region方式对堆内存进行了划分,且基于标记整理算法实现,整体减少了垃圾碎片的产生;

在初始化标记阶段,搜索可达对象使用到的 Card Table,其实现方式不一样。

CMS 和 G1 在解决并发标记时漏标的方式也不一样,CMS 使用的是 Incremental Update 算法,而 G1 使用的是 SATB 算法.


hive 性能 hive性能调优实战pdf_hive 性能_03


24丨内存持续上升,我该如何排查问题?20200720

本节有一个内存溢出的案例-threadlocal。

1.vmstat 是一款指定采样周期和次数的功能性监测工具,它不仅可以统计内存的使用情况,还可以观测到 CPU 的使用率、swap 的使用情况。但 vmstat 一般很少用来查看内存的使用情况,而是经常被用来观察进程的上下文切换。

2.pidstat 命令则是深入到线程级别

3.jstat 可以监测 Java 应用程序的实时运行情况,包括堆内存信息以及垃圾回收信息。

4. jstack是一种线程堆栈分析工具,最常用的功能就是使 用 jstack pid 命令查看线程的堆栈信息,通常会结合 top -Hp pid 或 pidstat -p pid -t 一 起查看具体线程的状态,也经常用来排查一些死锁的异常。

5.jmap 查看堆内存初始化配置信息以及堆内存的使用情况。还可以使用 jmap 输出堆内存中的对象信息,包括产生了哪些对象, 对象数量多少等。

jmap -dump:format=b,file=/tmp/heap.hprof 28677

将文件下载下来使用MAT工具分析。

6.实例:https://mp.weixin.qq.com/s/IPi3xiordGh-zcSSRie6nA

https://mp.weixin.qq.com/s/ji_8NhN4NnEHrfAlA9X_ag

23丨如何优化JVM内存分配?

1.基本不打用看

22丨如何优化垃圾回收机制?

1.Gc调优策略

降低Minor GC频率

降低Full Gc的频率

减少创建大对象。

增加堆内存空间

选择合适的Gc回收期

2.对吞吐量有要求时,可以选择Parallel Scavenge回收器来提高系统的吞吐量。

3.在Java语言里,可作为GC Root对象的包括如下几种: 1. Java虚拟机栈中的引用的对 象 ; 2. 方法区中的类静态属性引用的对象 ; 3. 方法区中的常量引用的对象 ; 4. 本地方法栈中 JNI的引用的对象。

我们知道,垃圾回收一般是回收堆和方法区的对象,而堆中的对象在正常情况下,一般是通过常 量、全局变量、静态变量等间接引用堆中的对象,所以这些可以作为GC Root。

4.

21丨深入JVM即时编译器JIT,优化Java编译 20200720

本节主要:学习运行时编译如何实现对java代码的优化

1.编译后的字节码文件主要包括常量池和方法表集合这两部分。

2.在字节码转换为机器码的过程中,虚拟机中还存在着一道编译,那就是即时编译。

3.在hotpot虚拟机中,内置了两个JIT,分别是C1编译器和C2编译器。分层编译将jvm执行状态分为了5个层次。

4.热点探测是JIT优化的条件。虚拟机为每个方法指标了两类计数器:方法计数器和回边计数器。

建立汇编计数器的主要目的是为了出发OSR编译,(On StackReplacement) ,即 栈上编译。

5.编译优化技术

方法内联

逃逸分析

是判断一个对象是否被外部方法引用或外部线程访问的分析技术,编译器会根据逃逸分析的结果对代码进行优化。

锁消除

6.Class.forName加载类的时候会对类进行初始化,如静态代码块,ClassLoader 不会做初 始化。spring做类加载的时候应该用的是ClassLoader把。

7.

20丨磨刀不误砍柴工:欲知JVM调优先了解JVM内存模型

1.方法区主要是用来存放已被虚拟机加载的类相关信息,包括类信息、运行时常量池、字符串常量池。类信息又包括了类的版本、字段、方法、接口和父类等信息。

2.方法区与堆空间类似,也是一个共享内存区,所以方法区是线程共享的。

JVM 的运行原理

1.过程

A.JVM 向操作系统申请内存,根据参数内部分配

B.JVM获得内存空间后,会根据配置参数分配堆,栈以及方法区的内存大小

C.class文件加载验证准备以及解析。

D.初始化,JVM执行构造器

E.执行main

04-模块三 . 多线程性能调优(8讲)

加餐丨什么是数据的强、弱一致性?20200717

1.Java 提出了 Happens-before 规则来规范线程的执行顺序

2.

答疑课堂:模块三热点问题解答20200717

1.vmstat是一款指定采样周期和次数的动能性检测工具,可以使用他监控进程上下文切换的情况。

2.pidstat命令:

检测到具体的线程的上下文切换。

3.jstack

查看具体线程的上下文切换异常,可以使用jstack命令查看堆栈的运行情况。

jstack 最常用的功能就是使用 jstack pid 命令查看线程堆栈 信息,通常是结合 pidstat -p pid -t 一起查看具体线程的状 态,也经常用来排查一些死锁的异常。

19丨如何用协程来优化多线程业务?

1.内核线程(Kernel-Level Thread, KLT)是由 操作系统内核支持的线程,内核通过调度器对线程进行调 度,并负责完成线程的切换。

2.轻量级进程(Light Weight Process,即 LWP):使用 clone() 系统调用创建线程。LWP 是跟内核线程一对一映射的,每个 LWP 都是由一个内核线程支持。

3.实现线程主要有三种方式:

轻量级进程和内核线程一对一相 互映射实现的 1:1 线程模型

复制一份,占用大量内存空间,又消耗大量 CPU 时间用 来初始化内存空间以及复制数据。

用户线程和内核线程实现的 N:1 线程模型以及用户线程

N:1 线程模型的缺点在于操作系统不能感知用户态的线程, 因此容易造成某一个线程进行系统调用内核线程时被阻塞, 从而导致整个进程被阻塞。

轻量级进程混合实现的 N:M 线程模型。

N:M 线程模型是基于上述两种线程模型实现的一种混合线 程管理模型,即支持用户态线程通过 LWP 与内核线程连 接,用户态的线程数量和内核态的 LWP 数量是 N:M 的映 射关系。

4.我们可以将协程看作是一个类函数或者一块函数中的代码,我们可以在一个主线程里面轻松创建多个协程。

5.协程少了由于同步资源竞争带来的 CPU 上下文 切换,I/O 密集型的应用比较适合使用,特别是在网络请求 中,有较多的时间在等待后端响应,协程可以保证线程不会 阻塞在等待网络响应中,充分利用了多核多线程的能力。

6.线程是通过 共享内存来实现数据共享,而协程是使用了通信的方式来实 现了数据共享,主要就是为了避免内存共享数据而带来的线 程安全问题。

7.I/O 阻塞型场景也就是协程在 Java 中的主要应用。

8.Kilim

18丨如何设置线程池大小?20200716

1.调用 prestartAllCoreThreads() 或者 prestartCoreThread() 方法的话,可以提前创建等于核心线程数的线程数量,这种方式被称为预热,在抢购系统中 就经常被用到。

2.CPU 密集型任务:这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心 数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其它原因 导致的任务暂停而带来的影响。

3.I/O 密集型任务:2N。

4.参考以下公式来计算线程数:

线程数 =N(CPU 核数)*(1+WT(线程等待时间)/ST(线程时间运行时间))

17丨并发容器的使用:识别不同场景下最优容器20200715

1.在非线程安全的 Map容器中,用TreeMap容器来存取大数据;在线程安全的Map容器中,用SkipListMap 容器来存取大数据。

2.跳跃表

跳跃表是基于链表扩展实现的一种特殊链表,类似于树的实现,跳跃表不仅实现了横向链表,还实现了垂直方向的分层索引。

3.如果对数据有强一致要求,则需使用 Hashtable;在大部分场景通常都是弱一致性的情况 下,使用ConcurrentHashMap 即可;如果数据量在千万级别,且存在大量增删改操作, 则可以考虑使用 ConcurrentSkipListMap。

4.


hive 性能 hive性能调优实战pdf_JVM_04


16丨多线程调优(下):如何优化多线程上下文切换?20200715

1.竞争锁优化:

在多线程编程中,锁其实不是性能开销的根源,竞争锁才是。

优化方式:

减少锁的持有时间

降低锁粒度:锁分离;锁分段

非阻塞乐观锁替代竞争锁

15丨多线程调优(上):哪些操作导致了上下文切换?20200710

1.自发性上下文切换指线程由 Java 程序调用导致切出,在多 线程编程中,执行调用以下方法或关键字,常常就会引发自 发性上下文切换。

非自发性上下文切换指线程由于调度器的原因被迫切出。常见的有:线程被分配的时间片用完,虚拟机垃圾回收导致或者执行优先级的问题导致。

2.进程上下文切换,是指用户态和内核态的来回切 换。当Synchronized锁资源竞争激烈,线程将会被阻塞, 阻塞的线程将会从用户态调用内核态,尝试获取mutex,这 个过程是Synchronized锁产生的进程上下文切换。

14丨多线程之锁优化(下):使用乐观锁优化并行操作

1.不会带来死锁、饥饿等活性故障问题,线程间的相互影响也远远比悲观锁要小。更为重要的是,乐观锁没有因竞争造成的系统开销,所以在性能上也是更胜一筹。

2.CAS 是实现乐观锁的核心算法,它包含了 3 个参数:V(需 要更新的变量)、E(预期值)和 N(最新值)。

3.目前最新的处理器都支持缓存锁定机制。

4.LongAdder

将热点数据value被分离成多个单 元的cell,每个cell独自维护内部的值,当前对象的实际值 由cell[]数组中所有的cell累计合成。这样,热点就进行了 有效的分离,提高了并行度,所以LongAdder虽然降低 了并发竞争,但是却对实时更新的数据不友好。

在高并发场景下会比 AtomicInteger 和 AtomicLong 的性能更好,代价就是会消耗更多的内存空 间。

5.CAS 乐观锁在平常使用时比较受限,它只能保证单个变量操 作的原子性,当涉及到多个变量时,CAS 就无能为力了,但 前两讲讲到的悲观锁可以通过对整个代码块加锁来做到这 点。

6.

13丨多线程之锁优化(中):深入了解Lock同步锁的优化方法

ReentrantReadWriteLock 和 StampedLock还需要再看看。

1.


hive 性能 hive性能调优实战pdf_调优_05


2.ReentrantLock 独占锁。

3.读写锁 ReentrantReadWriteLock

state

获取写锁:

获取写锁:

4.读写锁再优化之StampedLock

在读很多、写入很少的情况下,RRW会使写线程遭遇饥饿问题,也就是说写入线程会因迟迟无法竞争到锁而一直处于等待状态。

StampedLock控制锁有是三种模式:

悲观读

乐观读

StampedLoack不支持重入,不支持条件变量,线程中断时可能导致CPU暴涨。

12丨多线程之锁优化(上):深入了解Synchronized同步锁的优化方法 20200630

1.synchronizede 修饰方法时,jvm使用了ACC_SYNCHRONIZED访问标志来区分一个方法是否是同步方法。synchronizede修改代码块时,使用monitorenter和moniterexit指令,依靠底层操作系统的Mutex Lock来实现互斥的。存在用户态和内核态之间的切换,增加了性能开销。

synchronized 加在非静态方法是对象锁,静态方法是类锁。

2.jdk1.6引入了偏向锁、轻量级锁、重量级锁概念,来减少锁竞争带来的上下文切换,

而正是新增的Java对象头实现锁升级功能。

3.java对象头由mark word、指向类的指针以及数组长度三部分组成。

4.偏向锁:主要用来优化统一线程多次申请同一个锁的竞争。

5.轻量级锁:使用与线程交替执行同步快的场景。

6.在锁竞争不激烈且锁占用时间非常短的场景下,自旋锁可以提高系统性能。

-XX:-UseSpinning // 参数关闭自旋锁优化 (默认打开)

7.锁消除,同步快只被一个线程访问,不会生产synchonized所表示的锁的申请和释放的机器码。java7后自动

8.锁粗化

9.减小锁粒度

经典:jdk1.8之前实现的concurrentHashMap版本。

03-模块二 · Java编程性能调优 (10讲)

加餐丨推荐几款常用的性能测试工具

本节可略

1.ab -c 并发次数,例如:10个请求,10个并发,实际就是1人请求1次。

2.付费测试工具LoadRunner,支持iP欺骗

11丨答疑课堂:深入了解NIO的优化实现原理

本节 关于I/O模型东西多,不是很理解。可看一遍

  • 阻塞IO:调用read()线程阻塞了
  • 非阻塞IO:调用read()马上拿到一个数据未就绪,或者就绪。
  • I/O多路复用:selector线程阻塞,channel非阻塞,用阻塞一个selector线程换了多个channel了非阻塞。select()函数基于数组,fd个数限制1024,poll()函数也是基于数组但是fd数目无限制。都会负责所有的fd(未就绪的开销浪了),
  • epll()基于红黑数实现,fd无大小限制,平衡二叉数插入删除效率高。
  • 信号驱动模式IO:对IO多路复用进一步优化,selector也非阻塞了。但是sign信号无法区分多信号源。所以socket未使用这种,只有在单一信号模型上才能应用。
  • 异步IO模型:真正的非阻塞IO,其实前面的四种IO都不是真正的非阻塞IO,他们的非阻塞只是,从网络或者内存磁盘到内核空间的非阻塞,调用read()后还需要从内核拷贝到用户空间。异步IO基于回调,这一步也非阻塞了,从内核拷贝到用户空间后才通知用户进程。

tomcat 调优

10丨网络通信优化之通信协议:如何优化RPC网络通信?

1.作者认为 微服务的核心是远程通信和服务治理。

2.无论是微服务、SOA还是RPC架构,他们都是分布式服务架构,都需要实现服务之间的互相通信,我们通常吧这种通信统称为RPC通信.

3.RPC remote Process Call 即远程服务调用,是通过网络请求远程计算机程序服务的通信技术。

4.RMI Remote Method Invocation 是jdk中最先实现了RPC通信的框架之一。

5.一个高并发场景下的RPC通信优化路径:

RPC 通信包括建立通信、实现报文、传输协议以及传输数据编码解码等操作。

A.选择合适的通信协议

B.使用单一长链接

C.使用Socket通信

D.量身定做报文格式

E.编码、解码

F.调整Linux的TCP参数设置选项:需要看 pdf

6.三次握手:

URG:紧急指针(urgent pointer)有效。

ACK:确认序号有效。

PSH:接收方应该尽快将这个报文交给应用层。

RST:重置连接。

SYN:发起一个新连接。

FIN:释放一个连接。


hive 性能 hive性能调优实战pdf_hive 性能_06


7.四次挥手:

所谓的四次挥手即TCP连接的释放(解除)。连接的释放必须是一方主动释放,另一方被动释放


hive 性能 hive性能调优实战pdf_hive性能调优实战pdf_07


2MSL:为的是确认服务器端是否收到客户端发出的ACK确认报文

大文件传输,使用 hessian协议较好。

09丨网络通信优化之序列化:避免使用Java序列化20200701

1.java序列化机制:能够将一个对象序列化为二进制形式(字节数组),用于写入磁盘活输出到网络,同时也能从网络或磁盘中读取字节数组,反序列化成对象,在程序中使用。

2.java序列化的缺陷

无法跨语言

易被攻击

序列化后的流太大

序列化性能太差

3.使用protobuf序列化替换Java序列化

4.没太懂:单例模式 implements serializable ,序列化会通过反射调用午餐构造器返回一个新对象,破坏单例模式。

解决方法是添加readResolve()方法,自定义返回对象策略。

08丨网络通信优化之I-O模型:如何解决高并发下I-O瓶颈?20200701

本节略简单,看下笔记即可


hive 性能 hive性能调优实战pdf_数据_08


1.传统IO和NIO的做大区别就是传统IO是面向流,NIO是面向Buffer。

Buffer可以将文件一次性读入内存在做后续处理,而传统的方式是边读文件边处理数据。

NIO是基于块(block)的,以块为基本单位处理数据。

2.NIO提供了一个直接访问物理内存的类DirectBuffer。非jvm,创建和小会代价很高。

3.NIO NON-block I/O 非阻塞I/O.

通过 通道和多路复用器两个基本组件实现了NIO的非阻塞。

通道:channel

多路复用器:用于检查一个或多个NIO channel的状态是否处于可读、可写。

epoll 相比传统的select机制,epoll没有最大连接句柄的限制。所以selector理论上可以轮询成千上万个的客户端。

4.AIO 实现了真正意义 上的异步 I/O,它是直接将 I/O 操作交给操作系统进行异步处理。这也是对 I/O 操作的一 种优化,那为什么现在很多容器的通信框架都还是使用 NIO 呢?

答:异步I/O没有在Linux内核中实现

07丨深入浅出HashMap的设计与优化-基础知识补强 20200701

1.

2.Object类中的equals方法和“==”是一样的,没有区别,即俩个对象的比较是比较他们的栈内存中存储的内存地址。而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,他们比较的是值是不是相等。所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。

3.但一个面临问题:若两个对象equals相等,但不在一个区间,因为hashCode的值在重写之前是对内存地址计算得出,所以根本没有机会进行比较,会被认为是不同的对象。所以Java对于eqauls方法和hashCode方法是这样规定的:

1 如果两个对象相同,那么它们的hashCode值一定要相同。也告诉我们重写equals方法,一定要重写hashCode方法,也就是说hashCode值要和类中的成员变量挂上钩,对象相同–>成员变量相同—->hashCode值一定相同。

4. putVal 方法中的 (n - 1) & hash 决定 该 Node 的存储位置?为什么?

2的幂次方减1后每一位都是1,让数组每一个位置都能添加到元素。

例如十进制8,对应二进制1000,减1是0111,这样在&hash值使数组每个位置都是可以添加到元素的,如果有一个位置为0,那么无论hash值是多少那一位总是0,例如0101,&hash后第二位总是0,也就是说数组中下标为2的位置总是空的。

如果初始化大小设置的不是2的幂次方,hashmap也会调整到比初始化值大且最近的一个2的幂作为capacity。

总之,减少哈希冲突,均匀分布元素。

5.

06丨Stream如何提高遍历集合效率?20200630

本节新知识

1.Stream操作类型

中间操作

  • 无状态Stateless
  • 有状态Stateful

终结操作

  • 非短路操作
  • 短路操作

2.使用场景:

在循环迭代次数较少的情况下,常规的迭代方式性能反 而更好;在单核 CPU 服务器配置环境中,也是常规迭代方式更有优势;而在大数据循环迭 代中,如果服务器是多核 CPU 的情况下,Stream 的并行迭代优势明显。所以我们在平时 处理大数据的集合时,应该尽量考虑将应用部署在多核 CPU 环境下,并且使用 Stream 的 并行迭代方式进行处理。

05丨ArrayList还是LinkedList?使用不当性能差千倍

1.可略

04丨慎重使用正则表达式

可参考:

1.


hive 性能 hive性能调优实战pdf_数据_09


2.三种匹配模式:

贪婪模式、懒惰模式、独占模式

独占模式:正则表达式尽可能长地去匹配字符串,一旦匹配不成功就会结束匹配而不会回溯

3.正则引擎主要可以分为基本不同的两大类:一种是DFA(确定型有穷自动机),另一种是NFA(不确定型有穷自动机)

4.正则表达式的优化:

A少用贪婪模式,多用独占模式

B减少分支选择 (X|Y|Z)

C减少捕获嵌套

捕获组是指把正则表达式中,子表达式匹配的内容保存到以数字编号或显式命名的数组中, 方便后面引用。一般一个 () 就是一个捕获组,捕获组可以进行嵌套。

如果你并不需要获取某一个分组内的文本,那么就使用非捕获分组。例如,使 用“(?:X)”代替“(X)”,我们再看下面的例子: 具体看例子。

03丨字符串性能优化不容小觑,百M内存轻松存储几十G数据

1.在java中,有两种创建字符串对象的方式,一种是通过字符串常量创建,如String s=“abc”;

另一张是字符串变量通过new形式创建String s =new Stirng(“abc”)

2.String对象的优化

A如何构建超大字符串,StringBuidler 线程不安全

B如何使用String.intern节省内存

在字符串常量中,默认会将对象放入常量池。


hive 性能 hive性能调优实战pdf_JVM_10


3.如何使用字符串的分割方法

A.

02-模块一 · 概述 (2讲) 20200629

02丨如何制定性能调优策略?

1.两种常用的测试方法

微基准性能测试

宏基准性能测试:是一个综合测试,需要考虑到测试环境、测试场景和测试目标

2.几种调优策略

A.优化代码,LinkedList集合 for慢,要使用Iterator(迭代器),因为LinkedList是链表实现的,如果使用for循环获取元素,在每次循环获取元素时,都会去遍历一次List,这样会降低读的效率。

B.优化设计

C.优化算法

D.时间换空间

E.空间换时间:使用存储空间来提升访问速度

F.参数调优


hive 性能 hive性能调优实战pdf_hive 性能_11


01 如何制定性能调优标准

性能调优的标准:响应时间、吞吐量、计算机资源分配使用率、负载承受能力

1.磁盘吞吐量

IOPS:Input/output Per Second ,每秒的输入输出量(或读写次数)

数据吞吐量:单位时间内可以成功传输的数据量。

精选问题:请问老师最近段时间遇到端口被CLOSE_WAIT占用,重启后过了半天又重现,以前没有出现过,一般如何排查:

作者回复: 可以通过tcpdump抓包看看连接状态,分析是否是服务端的FIN packet没有发出去。

正常的关闭流程是:服务端在接收到客户端发送的关闭请求FIN后,会进入CLOSE_WAIT状态,同 时发送ACK回去。在完成与客户端直接的通信操作之后,再向客户端发送FIN,进入LAST_ACK状态。

如果连接是CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Client,那么可能是 在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。

建议确定关闭请求的四次握手,哪个环节出了问题,再去排查业务代码,可能是由于超时或者异

常导致没有正常关闭连接。

01-开篇词