vlambda博客
学习文章列表

【高性能Java架构:核心原理与案例实战】

高性能Java架构:核心原理与案例实战

第1章 高性能Java核心知识概述

1.1 高性能

  • 在做性能优化时,计算密集型和I/O密集型是有很大差别的,需要分开考虑

  • 在做性能优化时,计算密集型和I/O密集型是有很大差别的,需要分开考虑

  • 影响程序性能的原因

    • • 因为I/O阻塞会让CPU闲置,导致CPU浪费。

    • • 在多线程间增加锁来保证同步,导致并行系统串行化。

    • • 创建、销毁、维护太多进程和线程,导致操作系统把资源浪费在调度上。

    • • 没有异步返回数据进行处理。• 数据量过大,线程循环次数过多。

    • • 协议消耗资源过多。

    • • 未控制的慢请求、慢读取造成的并发不良。

1.2 高并发

1.3 高可用

1.4 算法、GC与诊断工具

1.5 分离术

1.6 基准测试

1.7 性能测试

1.8 业务测试

1.9 单元测试

1.10 数据库概述


    • (1)常用的性能基准测试工具有sysbench和mysqlslap。

    • (2)对应用程序进行性能测试的常用工具是JMeter。

    • (3)对MySQL和服务器CPU等信息进行性能监控架构可选择Grafana + InfluxDB +Telegraf架构或Prometheus + Grafana架构。

    • (4)集群可选择MyCAT。

    • (5)相关统计可选择percona-toolkit。

    • (6)慢SQL查询可选择mysqldumpslow。

    • (7)分布式事务可选择Fescar(Seata)。

    • (8)事务处理测试可选择HammerDB。

    • (9)快速备份与恢复可选择mysqlhotcopy。

    • (10)常规备份与恢复可选择mysqldump。

    • (11)二进制日志(binlog)解析工具可选择Maxwell。

    1. 常用的MySQL工具

1.11 缓存的核心知识

1.12 总结——业务、性能、编程、架构相辅相成

第2章 为MySQL填充亿级数据

2.1 问题描述

在编写代码之前,应先针对业务设计的数据格式创建表结构,然后填充亿级数据,此阶段出现的典型问题如下:(1)对于新上线的项目,我们希望能测试出它的最高承载用户量,在数据库为空的情况下,应如何增加亿级数据?(2)在学习和工作工程中,经常需要使用数据量庞大的表来模拟系统在真实环境中的响应情况。如果只写一段代码,之后循环使用INSERT语句插入数据则实在是太慢了,是否有更快速的方法?

2.2 问题分析与解决方案

  • 我们分别通过INSERT INTO SELECT、存储过程和Loadfile三种方案为MySQL快速填充亿级数据

2.3 为MySQL填充亿级数据实战

  • 2.3.1 INSERT INTO SELECT方案

  • 2.3.2 存储过程方案

  • 2.3.3 Loadfile方案

  • 2.3.4 第三方解决方案

2.4 最终结果

第3章 MySQL基准测试:sysbench与mysqlslap

3.1 问题描述

(1)如何为刚搭建的MySQL数据库配置相关参数,例如8CPU、16MEM的服务器,应配置何种参数使该服务器最优?(2)当前设计的数据结构与表结构在没有其他因素影响性能时,基准响应情况如何?(3)当前负载均衡架构体系是否过多地影响了单台MySQL数据库的性能,例如,主从复制在当前架构中应当选择何种策略才不会过度损耗单台MySQL数据库的性能?(4)当前单台MySQL数据库的最大承载访问量是多少?(5)当MySQL数据库单表数据量过亿时,返回数据的速度极慢是正确的吗?

3.2 问题分析与解决方案

  • 3.2.1 解决方案:sysbench

  • 3.2.2 sysbench的命令与参数

  • 3.2.3 解决方案:mysqlslap

  • 3.2.4 mysqlslap的命令与参数

3.3 sysbench实战

  • 3.3.1 使用sysbench压测CPU、内存和磁盘I/O

  • 3.3.2 初次使用sysbench压测MySQL

  • 3.3.3 深度使用sysbench压测MySQL

3.4 mysqlslap实战

3.5 其他基准压测工具

  • 目前主流的第三方磁盘I/O压测工具有fio、Iometer和Orion

第4章 代码单元的性能测试与优化

4.1 问题描述

在编写代码过程中,程序中通常会有许多个函数和接口,此时需要对函数和接口进行单元测试,以便了解函数或接口的性能,此阶段出现的典型问题如下:(1)if和switch哪个性能更好?(2)FastJSON和GSON哪个性能更好?(3)程序使用Spring和不使用Spring哪个性能更好?(4)HashMap初始化是否需要指定初始大小?(5)HashMap获得容器占用大小时是否需要更多延时?(6)JDK的Lambda表达式是否会消耗更多的性能?(7)MyBatis和Spring-Data-JDBC哪个效率更高?(8)Redisson和Spring-Data-Reids哪个效率更高?

4.2 问题分析与解决方案

4.3 JMH实战

  • 4.3.1 测试JMH基准性能

  • 4.3.2 测试i++基准性能

  • 4.3.3 用JMH执行多个函数的结果

第5章 Web性能测试解决方案:JMeter

5.1 问题描述

在代码写好之后,通常需要对场景进行性能测试,例如购买商品场景、登录场景、支付场景等,此阶段会出现的典型问题如下:(1)当前登录场景可能需要调用N个接口,每天高峰期的时候,应用程序可以承受多少人登录。(2)秒杀系统最多可以让多少人同时单击“购买”按钮而不出现异常。(3)连续100小时以上的疲劳测试是否会使系统内存出现无法下降、GC无法回收内存、疲劳测试之后CPU无法正常下降等问题。(4)在并发压力下,应用程序哪里消耗资源过多,需要进行优化?(5)在复杂场景下,整体接口包含调用逻辑,其中可能包括if-else判断、for/while循环、获取上一个接口的信息传输到下一个接口中等操作,如何简化这部分性能测试的需求?(6)针对协议如何进行测试?例如HTTP轮询与WebSocket哪个更消耗性能?大概相差多少?(7)当单台压力机无法生成更大的压力时,如何增加压力机?

5.2 问题分析与解决方案

5.3 JMeter的特点

5.4 深入理解JMeter

  • 5.4.1 JMeter中的部分配置元件

  • 5.4.2 JMeter参数化的实现方式

  • 5.4.3 JMeter函数

  • 5.4.4 通过JMeter读取外部文件

  • 5.4.5 通过JMeter提取上一个接口返回值

5.5 JMeter实战

  • 5.5.1 初次使用JMeter测试REST接口

  • 5.5.2 录制性能测试脚本

第6章 SQL优化与索引优化

6.1 问题描述

在场景性能测试过程中,许多场景的响应速度可能并不如人意,此时可以通过优化SQL的方式,对场景性能测试函数与接口进行优化。此阶段会出现的典型问题如下:(1)在场景性能测试中,当前SQL是如何扫描MySQL的,导致返回速度特别慢?(2)当返回速度较慢时应如何增加索引?(3)应增加哪种类型的索引?(4)应用程序在生产环境中运行时,是如何知道哪条SQL语句执行的速度较慢的?

6.2 问题分析与解决方案

6.3 SQL执行计划

6.4 SQL优化与索引优化实战

  • 6.4.1 SQL索引优化

  • 6.4.2 分页查询优化

  • 6.4.3 慢SQL日志分析工具mysqldumpslow

第7章 MySQL主从复制

7.1 问题描述

在程序上线运行一段时间之后,随着用户量的逐渐增多,单台MySQL开始无法承受所有的压力,为了承载更大的数据库并发,避免单台MySQL宕机,即无法正常提供服务,出现整体应用程序崩溃的情况,此时需要使用MySQL集群,此阶段会出现的典型问题如下:(1)在生产环境中,当MySQL处于运行状态时应如何备份当前数据?(2)在某场景下,某个接口需要锁表以便修改数据,而其他读取的线程都处于阻塞等待状态,此时应如何对其进行优化?(3)并发读取越来越多,单台无法满足业务需求,如何进行处理?

7.2 问题分析与解决方案

7.3 MySQL主从复制原理


    1. 部署过程中需要注意的事项


    1. MySQL主从复制的架构拓扑

7.4 深入理解MySQL中的二进制日志

  • 7.4.1 查看MySQL二进制日志状态

  • 7.4.2 log_bin和sql_log_bin的区别

  • 7.4.3 开启二进制日志

  • 7.4.4 查看二进制日志文件的名称、大小和状态

  • 7.4.5 删除某个日志之前的所有二进制日志文件

  • 7.4.6 删除某个时间点以前的二进制日志文件

  • 7.4.7 删除所有的二进制日志文件

  • 7.4.8 查看二进制日志文件内容

  • 7.4.9 通过二进制日志文件恢复MySQL

7.5 MySQL主从复制实战

  • 7.5.1 构建MySQL主从复制架构

  • 7.5.2 使用Spring Boot整合MySQL主从复制架构

第8章 MySQL分库分表:MyCAT

8.1 问题描述

8.2 问题分析与解决方案

8.3 MyCAT实战

  • 8.3.1 构建MyCAT一主多从架构

  • 8.3.2 构建MyCAT双主多从环境

  • 8.3.3 MyCAT分库——垂直拆分

  • 8.3.4 MyCAT分表——水平拆分

  • 8.3.5 构建HAProxy + MyCAT + MySQL高可用架构

第9章 MySQL性能监控解决方案:Prometheus+Grafana

9.1 问题描述

在对MySQL进行主从复制、分库分表等架构之后,MySQL的节点数量变得越来越多,无法实时监控到每一台MySQL节点,此时应当如何处理?

9.2 问题分析与解决方案

9.3 Prometheus概述与适用场景

Prometheus是一个开源的服务监控系统和时间序列数据库,Kubernetes(k8s)内部使用的就是Prometheus数据库。Kubernetes的流行,带动了Prometheus社区的发展。Prometheus在大规模数据管理与读取上,比传统的NoSQL数据库要快很多。在数据压缩上,Prometheus具有高效压缩数据的算法,节省了存储空间,可有效减少服务器I/O的瓶颈。

  • Prometheus的适用场景如下:

    • (1)部署监控服务器,实现7×24实时监控。

    • (2)针对公司的业务及研发部门设计监控系统,对监控项和触发器给出合理意见。

    • (3)做好问题预警机制,对可能出现的问题及时告警并形成严格的处理机制。

    • (5)处理好公司服务器异地集中监控的问题。

  • Prometheus的主要特征:

    • (1)多维度数据模型。

    • (2)灵活的查询语言。

    • (3)不依赖分布式存储,单个服务器节点是自主的。

    • (4)以HTTP方式通过pull模型拉取时间序列数据。

    • (5)通过中间网关支持push模型。

    • (6)通过服务发现或者静态配置发现目

9.4 时序数据库概述与适用场景

在工作中,时序数据库(TimeSeries DataBase,TSDB)主要记录按照时间顺序进行管理的数据。这些以时间为变化的数据被统称为时序数据。时序数据库对该类数据有更好的读取性能,其应用场景如下所示

  • (1)Linux服务器每秒的CPU占用百分比、内存占用百分比、硬盘占用百分比等相关数据。

  • (2)无人汽车每秒的速度、油耗、方向、地理位置等相关数据。

  • (3)无人机每秒的经纬度、飞行高度、地理位置等相关数据。

  • (4)证券中心每秒开盘的行情数据、资金流数据。

  • (5)银行账号每天、每周的存款数据。

9.5 Grafana概述与适用场景

9.6 构建Prometheus + Grafana监控实战

第10章 堆内缓存解决方案:Java堆内缓存与Guava Cache

10.1 问题描述

当数据库臃肿性能不佳时,需要通过多层缓存的方式,在不同层级上设置缓存,减少数据库的连接次数与查询次数。假设有这样一个场景,首先查询一次堆内缓存,如果没有命中堆内缓存,则需要在MySQL中进行查询,然后将查询结果放置在堆内缓存中,以免下次查询不到,最后返回数据。这种方案比较常见,但是会出现许多细节上的问题,例如:(1)缓存穿透:DB中不存在数据,每次都穿过缓存查询DB,当给DB造成较大压力时应当如何处理?(2)缓存击穿:在缓存失效的瞬间涌入大量请求,造成DB的压力瞬间增大,此时应当如何处理?(3)缓存雪崩:大量缓存设置了相同的失效时间,使得性能瞬间急剧下降,此时应当如何处理?(4)JDK中主要包含几种缓存形式?

10.2 问题分析与解决方案

10.3 Java堆内缓存

  • 10.3.1 Java堆内缓存原理

  • 10.3.2 Java堆内缓存中的常见算法及实战







    1. 从0到1编写ArrayList

    2. 跳表算法

    3. 分段锁算法

    4. 无锁算法

    1. 安全失败

    2. 快速失败

    10.4 Guava Cache实战

    • 10.4.1 创建Google的容器工厂

    • 10.4.2 屏蔽NULL值

    • 10.4.3 管理字符串

    • 10.4.4 操作Google的Multiset容器

    • 10.4.5 操作Google的Multimap容器

    • 10.4.6 操作Google的BiMap容器

    • 10.4.7 操作Google的Table容器

    • 10.4.8 操作Google的classToInstanceMap容器

    • 10.4.9 操作Google的RangeSet容器

    • 10.4.10 操作Google的RangeMap容器

    • 10.4.11 操作Google的Guava Cache

    第11章 堆外缓存与磁盘缓存解决方案:MapDB

    11.1 问题描述

    在互联网项目中,一般以堆内缓存的使用居多,无论Guava Cache还是JDK自带的HashMap、ConcurrentHashMap等,都是在堆内缓存中做数据计算操作。这是因为堆内缓存的响应速度最快,但是堆内缓存的价格也最高。有没有既能节约成本,又能提供较好的性能的工具呢?JVM一旦出现GC或者FULL GC的情况,就然删掉堆内存,此时应如何快速读取缓存数据?

    11.2 问题分析与解决方案

    实际上,堆内缓存、堆外缓存、磁盘缓存的响应速度是依次递减的。堆外缓存同样不需要考虑I/O、网卡、网络流量、连接数等一系列问题,数据并不存放在JVM内存上,而是直接存放在Linux系统内存上。因此针对在11.1节中提出的问题,均可使用堆外缓存处理。

    • 11.2.1 堆外缓存

    • 11.2.2 MapDB

    • 11.2.3 实战:初次使用MapDB

    11.3 MapDB的构造原理

    11.4 MapDB的使用方法

    11.5 MapDB实战

    • 11.5.1 MapDB的序列化

    • 11.5.2 MapDB的事务

    • 11.5.3 MapDB的监听器与多级缓存

    第12章 基于Redis的分布式锁解决方案:Redisson

    12.1 分布式锁与Redisson原理

    通常来说,秒杀系统在活动期间都需要极高的性能,为了防止超买或超卖,此时需要使用分布式锁解决数据的一致性问题。本章介绍基于Redis的分布式锁解决方案:Redisson。


      1. 分布式锁


      1. Redisson原理


      1. Redisson相关机制

    12.2 单机版超买或超卖问题描述及解决方案

    12.3 分布式版超买或超卖问题描述及解决方案

    12.4 多线程死锁问题描述及解决方案

    12.5 Redisson实战

    • 12.5.1 Redisson的可重入锁

    • 12.5.2 Redisson的公平锁

    • 12.5.3 Redisson的联锁

    • 12.5.5 Redisson的读写锁

    • 12.5.6 Redisson的信号量

    • 12.5.7 Redisson的分布式闭锁

    第13章 Java中的常见架构与工具

    13.1 自动化测试架构

    13.2 自动化持续集成部署架构

    13.3 高并发架构

    13.4 响应式编程架构

    13.5 负载均衡架构

    13.6 监控工具与监控架构

    13.7 其他工具与架构