jvm是java程序运行的基石。*.java文件编译成字节码文件后,通过类加载机制加载到jvm中。JVM内存模型主要将内存分成:jvm虚拟机栈,本地方法栈,程序计数器,堆空间,metaspace,直接内存这几部分。每启动一个线程JVM就会在栈空间中创建一个线程栈,如果调用了JNI方法则创建本地方法栈,线程运行过程中每运行一个函数,JVM就会创建一个栈帧,栈帧由本地变量表,操作数栈,返回值,Class/Method指针组成。所有的对象都是在堆中创建。随着程序运行大量的对象在堆中创建,这时内存就会溢出,JVM通过GC来清除垃圾对象,常用的垃圾回收算法有三种:Mark-copy,Mark-Sweep,Mark-Sweep-Compact。目前主流的垃圾回收机包括:Serial GC,ParNew GC,Parallel Scavenge GC,Serial old,Parallel old,CMS,G1,ZGC,shennandoahGC
IO模型包括:阻塞IO模型,非阻塞IO模型,IO多路复用模型,异步IO模型,信号驱动IO模型。传统的阻塞IO模型,IO在进行读写时,线程将被阻塞。导致吞吐量降低,NIO是IO多路复用模型,主要由selector,Buffer,Channel三部分组成,selector通过调用内核函数select、epoll、kqueue来轮询所负责的socket,使用一个线程同时监听多个套接字,从而提升吞吐量。Netty是一个基于NIO的网络应用开发框架,Netty将网络和业务解耦,降低了开发难度。Netty有三种模式:单线程模式,多线程模式,主从模式
进程是资源分配的最小单位,线程是CPU调度的最小单位。多核cpu的出现意味着进程可以包含多个线程,这些线程共享进程的内存,为了性能考虑,每个线程都会有本地副本,这就带来了多线程问题 。由于同一进程的多个线程的写操作,读操作可能同时进行,导致写操作的互相覆盖、读操作读取的是过期值。为了解决多线程并发问题,java提供了JUC包,提供了同步容器,AQS组件,锁,Atomic类等,来避免并发问题。
Spring通过IOC和AOP解决的类与类之间耦合问题,以及重复代码。IOC是依赖倒置设计原则的具体实现,通过IOC容器创建Bean,控制并管理Bean的周期,将依赖项注入到类中,调用类和依赖项之间解耦。Aop(面向切面编程),通过动态代理(JDK动态代理,CGLib动态代理)创建代理对代理类增强。为了简化Spring的配置实现规约大于配置,产生了Spring Boot,spring Boot实现了自动化配置,简化了配置,实现了通过少许几个配置就能开箱即用。
Mysql是关系型数据库,将架构分成两层:服务层,存储层,从而实现存储引擎的可插拔。Innodb通过Redo log实现了crash safe,通过随机写转顺序写提高了写操作性能,通过undo log实现了事务的回滚和一致性视图的创建。Server层通过binlog实现主从同步,是主从模式的基石。通过两阶段提交实现了redo log和binlog的一致性。Innodb使用B+Tree构建索引,主键索引的叶子节点保存所有数据行记录,二级索引叶子节点保存主键id,通过二级索引获取主键再到主键索引上查数据行的过程叫回表。通过主从模式实现读写分离,是为了解决在较高的qps场景下,降低读压力,配合高可用方案:MHA,MGR,Mysql Cluster等避免单点故障
主从复制能降低主库读压力,部分解决高可用,但是在大数据量和写压力较大的场景下并不能解决写压力大,容量不足的问题。这时候就需要分库分表来提升容量和降低写压力,进而提升性能。分库分表分为:垂直分库、分表,水平分库、分表。通过对业务拆分来实现垂直分库,垂直分表是对大宽表的改造,垂直分库分表能够提升集群容量,降低单库单表的数据量进而提升查询性能,降低业务数据复杂度。水平分库分表主要是对数据分片,来提升集群容量,降低单库、单表数据量从而提升查询性能,另一方面也能解决IO瓶颈问题,但是同时也会带来一致性问题,从而引入了分布式事务。强一致性分布式事务主要是基于2pc理论,XA就是2pc的具体实现。柔性事务强调的是最终一致性,包括:TCC,AT,SAGA
RPC是基于接口的远程服务调用,他的核心是代理,通过生成接口的代理对象来实现对调用者透明的远程调用。主流的RPC框架包括Hessian,Thrift,gRPC,Dubbo。在分布式场景下下,我们还要考虑分布式服务治理:服务的注册发现、路由、负载均衡、限流容灾、过滤、心跳、重试以及集群的高可用和监控。Spring cloud是一套完整的微服务生态体系,它主要包括:spring boot(业务服务),Zuul/Zuul2/Gateway(网关),Hystix/alibaba sentinel/Reslient4j(限流容灾),Feign/Ribbon(路由/负载均衡)等组件,微服务间通过http/https协议通信。
缓存的本质是为了解决系统各级处理速度不一致,利用空间换时间,通过缓存热点数据来提升性能。缓存可以分为:本地缓存和远程缓存。常用的本地缓存包括:Ehcache、Guava cache,常用的远程缓存包括:redis、Memcached、Hazelcast、Ignite。redis是使用最广泛地缓存中间件,由于它内部事件处理是通过单线程操作,所以redis提供了很多高效的数据结构,redis通过RDB和AOF实现持久化,通过快照同步和增量同步实现了主从同步。redis sentinel是redis的高可用解决方案,sentinel之间通过raft协议选举leader,leader主导故障转移,从而保障高可用。redis cluster是redis的集群解决方案,将数据通过一致性hash路由到16384个槽中实现数据的分片,提升集群的容量
消息队列主要解决:削峰平谷,异步通信,可靠通信,系统解耦。通过将业务消息存储到远程消息中间件,来实现系统间的通信,从而实现不同应用之间的解耦。通过pull模式应用可以根据自身消费能力去拉去合适数量的消息来进行消费,实现削峰平谷。消息处理模式主要包括:PTP,PubSub。大多数消息中间件实现的是At least once,所以会有重复消息的可能性,应用要保证幂等避免重复消费。消息中间件保证同一个partition或queue中的消息是有序的,消费者要根据自身需求选择适当消费模式来保证消费的有序性。主流的消息中间件包括:rocketmq,kafka,activemq,rabbitmq,Pulsar。