JAVA技术栈
2024-11-09 12:16:03 1 举报
AI智能生成
为你推荐
查看更多
java 技术栈
作者其他创作
大纲/内容
顺序消息
广播消息
延迟消息
批量消息
过滤消息
事务消息
消息类型
同步刷盘
异步刷盘
刷盘机制
同步复制
异步复制
消息主从复制
CommitLog:存储消息的元数据。
ConsumerQueue:存储消息在CommitLog的索引。
IndexFile:为了消息查询提供了一种通过key或时间区间来查询消息的方法,
RocketMQ消息的存储分为三个部分
消息存储
ROCKETMQ详细特性和场景
参考:https://note.youdao.com/ynoteshare/index.html?id=c91c232cb5052cc9917c35ff2aa62e49&type=note&_time=1726298216245
ROCKETMQ核心源码解析
参考:https://note.youdao.com/ynoteshare/index.html?id=34ee9fe19157c6f4f0ab416d69622c7a&type=note&_time=1726303554161
ROCKETMQ源码解读和实践问题
ROCKETMQ
KAFKA快速实战和基本原理
KAFKA发送接收消息核心参数配置与设计原理详解
KAFKA生产问题总结和性能优化实战
KAFKA
RABBITMQ集群及高级特性
RABBITMQ如何作可靠消息的投递
RABBITMQ
分布式消息中间件
MONGDB集群架构及高级特性
MONGDB企业应用实战
MONGDB
ShardingSphere核心概念
ShardingSphere内核原理及核心源码解析
ShardingProxy分库分表实战及同类产品选型
ShardingSphere
MYSQL主从架构分库分表
分布式技术MongDBSharding-Sphere
JAVA BIO&NIO&AIO精讲
netty核心功能与线程模型精讲
netty编解码&粘包拆包及零拷贝精讲
netty线程模型源码解析
分布式通信netty框架
随机负载均衡(Random Load Balance)
轮询负载均衡(Round Robin Load Balance)
最少活跃数负载均衡(Least Active Load Balance)
一致性哈希负载均衡(Consistent Hash Load Balance)
负载均衡
服务超时
集群容错
服务降级
本地存根
本地伪装
参数回调
异步调用
泛化调用
DUBBO基本应用和高级应用
DUBBO的可扩展SPI源码解析
Spring与Dubbo整合原理
DUBBO服务导出源码解析
DUBBO服务导入源码解析
DUBBO服务调用源码解析
分布式技术apache Dubbo
ElasticSearch核心语法与集群环境搭建
ElasticSearch集群架构原理和搜索技术深入
ElasticSearch底层原理与分组聚合查询
ElasticSearch进阶与Java api整合ES
分布式ELK
为什么Springboot可以运行jar包?
继承@Configuration,标注这是一个Spring Boot配置类:@SpringBootConfiguration
启用Spring Boot的自动配置机制,尝试根据类路径设置、其他bean以及各种属性设置自动配置:@EnableAutoConfiguration
启用组件扫描,允许Spring Boot查找其他组件、配置文件和服务。:@ComponentScan
@SpringBootApplication
SpringBoot自动装配核心源码剖析
微服务架构Alibaba nacos 注册中心实战
负载均衡组件RRibbon&LLoadBalancer实战
微服务技术
引导类加载器扩展类加载器应用程序类加载器自定义加载器
类加载机制流程图
类加载的双亲委派机制
类加载机制
JVM整体结构图
JVM整体结构
对象内存分配图
对象内存分配流程图
大对象直接进入老年代大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。JVM参数 -XX:PretenureSizeThreshold 可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在 Serial 和ParNew两个收集器下有效。
长期存活的对象将进入老年代既然虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别哪些对象应放在新生代,哪些对象应放在老年代中。为了做到这一点,虚拟机给每个对象一个对象年龄(Age)计数器。
对象动态年龄判断当前放对象的Survivor区域里(其中一块区域,放对象的那块s区),一批对象的总大小大于这块Survivor区域内存大小的50%(-XX:TargetSurvivorRatio可以指定),那么此时大于等于这批对象年龄最大值的对象,就可以直接进入老年代了,例如Survivor区域里现在有一批对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代。这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代。对象动态年龄判断机制一般是在minor gc之后触发的。
老年代空间分配担保机制流程图
老年代空间分配担保机制年轻代每次minor gc之前JVM都会计算下老年代剩余可用空间如果这个可用空间小于年轻代里现有的所有对象大小之和(包括垃圾对象)就会看一个“-XX:-HandlePromotionFailure”(jdk1.8默认就设置了)的参数是否设置了如果有这个参数,就会看看老年代的可用内存大小,是否大于之前每一次minor gc后进入老年代的对象的平均大小。如果上一步结果是小于或者之前说的参数没有设置,那么就会触发一次Full gc,对老年代和年轻代一起回收一次垃圾,如果回收完还是没有足够空间存放新的对象就会发生\"OOM\"当然,如果minor gc之后剩余存活的需要挪动到老年代的对象大小还是大于老年代可用空间,那么也会触发full gc,full gc完之后如果还是没有空间放minor gc之后的存活对象,则也会发生“OOM”
对象进入老年代几种机制
JVM内存分配
JVM字节码文件结构
对于还在正常运行的系统:1.可以使用jmap来查看JVM中各个区域的使用情况2.可以通过jstack来查看线程的运行情况,比如哪些线程阻塞、是否出现了死锁3.可以通过jstat命令来查看垃圾回收的情况,特别是fullgc,如果发现fulgc比较频繁,那么就得进行调优了4.通过各个命令的结果,或者jvisualvm等工具来进行分析5.首先,初步猜测频繁发生fullgc的原因,如果频繁发生fullgc但是又一直没有出现内存溢出,那么表示fullgc实际上是回收了很多对象了,所以这些对象最好能在younggc过程中就直接回收掉,避免这些对象进入到老年代,对于这种情况,就要考虑这些存活时间不长的对象是不是比较大,导致年轻代放不下,直接进入到了老年代,尝试加大年轻代的大小,如果改完之后,fullgc减少,则证明修改有效6.同时,还可以找到占用CPU最多的线程,定位到具体的方法,优化这个方法的执行,看是否能避免某些对象的创建,从而节省内存
对于已经发生了OOM的系统:1.一般生产系统中都会设置当系统发生了OOM时,生成当时的dump文件(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/base)2.我们可以利用jsisualvm等工具来分析dump文件3.根据dump文件找到异常的实例对象,和异常的线程(占用CPU高),定位到具体的代码4.然后再进行详细的分析和调试
调优流程
arthas工具
jsisualvm工具
调优工具
JVM调优工具
JVM调优实战
JVM
Serial收集器
Serial
Parallel收集器
parallel
ParNew收集器
parNew
CMS收集器
CMS收集器步骤图
CMS相关参数
垃圾回收器底层算法-三色标记
GC ROOTS算法
CMS
G1垃圾回收器
G1收集器参数设置
G1
ZGC
垃圾回收器选择
垃圾收集器
JVM性能调优
索引是帮助MySQL高效获取数据的排好序的数据结构
二叉树
红黑树
Hash表
B-Tree
B+Tree
底层数据结构
MyISAM存储引擎索引实现
InnoDB存储引擎索引实现
索引最左前缀原理
存储引擎索引
MYSQL索引底层数据结构和算法
依次从最优到最差分别为:system>const>eq_ref>ref>range>index>ALL;一般来说,得保证查询达到range级别,最好达到ref
索引类型(type)
key_len计算规则如下:字符串char(n):n字节长度varchar(n):如果是utf-8,则长度 3n+2 字节,加的2字节用来存储字符串长度0数值类型tinyint:1字节。smallint:2字节int:4字节bigint:8字节时间类型date:3字节timestamp:4字节。dateime:8字节如果字段允许为 NULL,需要1字节记录是否为 NULL索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索引。
explain的sql字段说明
explain详解与索引的最佳实践
一条SQL怎么执行
开启trace
trace信息:预估成本
trace信息:最优选择
关闭trace
trace工具
总结
order by和group by优化
单路排序和双路排序
索引设计原则
索引设计实战
分页查询
join优化
in和exsits优化
count优化
字段类型优化
MYSQL索引优化实战
事务及其ACID属性
脏读
不可重复读
幻读
并发事务带来问题
未提交读
提交读
可重复读:写时加锁
可串行化:读写加锁
事务隔离级别
乐观锁
读锁(共享锁,S锁(Shared)):针对同份数据,读操作可以同时进行而不会互相影响
写锁(排它锁,X锁(eXclusive)):当前写操作没有完成前,它会阻断其他写锁和读锁
行锁每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。InnoDB与MYISAM的最大不同有两点:InnoDB支持事务(TRNSACTION)InnoDB支持行级锁
表锁每次操作锁住整张表。开销小,加锁快;不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低:一般用在整表数据迁移的场景
悲观锁
间隙锁
临键锁
无索引行锁会升级为表锁
查看锁情况
锁优化建议
锁分类
概述
MYSQL事务隔离级别和锁机制
MVCC的判断规则
可重复读事务:在一个事务中,第一个查询会生成一个readview,后面的查询都使用这个readview;已提交读事务:在一个事务中,第一个查询会生成一个readview,后面的查询都会实时生成一个readview;
MVCC
BufferPool
MVCC与BufferPool缓存机制
MYSQL性能调优
TOMCAT核心组件及应用架构详解
TOMCAT核心组件源码解析
TOMCAT源码之HTTP请求响应过程剖析
TOMCAT源码之热加载热部署及类加载器剖析
TOMCAT性能调优
操作系统底层工作的底层认识
可见性:当一个线程修改了一个被声明为 volatile 的共享变量时,其他线程能够立即看到这个变化,而不是等待缓存失效或刷新。这意味着对 volatile 变量的写操作会强制刷入主内存,并且读操作会从主内存中读取最新值。
多线程下可见性
禁止指令重排序:编译器和CPU不会对 volatile 变量进行指令重排序优化,保证了程序执行的顺序与源代码中的顺序一致(即 happens-before 规则)。这对于依赖于特定顺序执行的操作特别重要。
内存屏障:Java内存模型(JMM)通过插入内存屏障来实现 volatile 的语义。内存屏障是一种硬件层面的技术,它可以确保一些内存操作按照指定顺序执行。对于 volatile 写操作,会在其后插入“写屏障”,这样能确保所有之前的操作都完成并刷新到主内存;对于 volatile 读操作,则在其前插入“读屏障”,确保在此之后的所有操作都能看到此变量的最新值。
缓存一致性协议:现代多核处理器使用缓存一致性协议(如Intel的MESI协议等)来维持不同CPU核心之间的缓存数据同步。当一个CPU核心修改了 volatile 变量时,该协议会确保其他核心上的缓存副本失效,从而需要从主内存重新加载最新的值。
多线程下有序性
总结:总结来说,volatile关键字是Java中用于简化并发编程的一种机制,它确保了多线程环境下的简单同步问题,但不能替代原子操作或解决复杂的互斥问题。在实际应用中,volatile 常用于状态标志、计数器等简单的并发场景,而更复杂的并发控制通常需要借助于 synchronized 或 java.util.concurrent 包中的工具类。
JMM&volatile详解
JMM&MESI协议
锁的状态总共有四种,无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁,但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级。从JDK 1.6 中默认是开启偏向锁和轻量级锁的,可以通过-XX:-UseBiasedLocking来禁用偏向锁。
synchronized详解
AQS核心:①自旋;②线程阻塞;③cas;④队列;
AQS应用lock详解
AQS应用阻塞队列(BlockingQueue)
底层是基于AQS实现的
CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
CountDownLatch.countDown()CountDownLatch.await();
countDownLatch
Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目
SemaPhore
countDownLatch&SemaPhore应用
atomic&Unsafe详解
ArrayList和Vector是基于动态数组实现的,LinkedList是基于双向链表实现的(含有头结点)
ArrayList、LinkedList、Vector区别和实现原理
hashMap内部存储结构是数组加链表,线程非安全
hashtable内部存储结构是数组加链表,线程安全,在很多方法定义时都会加上 synchronized关键字
ConcurrentHashMap底层采用分段的数组+链表实现,底层先调用lock(),lock是ReentrantLock类的一个方法,因此是线程安全锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
hashMap hashtable ConcurrentHashMap区别
Map&List&Set详解
拒绝策略
ThreadPoolExcutor七大参数说明
线程数设置
Excutor线程池原理和源码解读
定时任务线程池
Future&ForkJoin框架
无锁并发框架-Disruptor
并发编程专题
流程1:
流程2:
流程3:
SpringIOC流程和源码
切面术语:
解析切面:
创建动态代理:
调用:
切面流程:
一、BeanNameAutoProxyCreator
二、DefaultAdvisorAutoProxyCreator
三 、aop:config 配置代理
四 、注解方式实现AOP
链接:https://blog.csdn.net/d1451545368/article/details/127304500声明式事务管理和编程式事务管理
aop的四种实现方式:
SpringAOP流程和源码
A 原子性:原子性指的是 在一组业务操作下 要么都成功 要么都失败在一组增删改查的业务下 要么都提交 要么都回滚
C 一致性:事务前后的数据要保证数据的一致性 在一组的查询业务下 必须要保证前后关联数据的一致性
I 隔离性:在并发情况下 事物之间要相互隔离。
D 持久性:数据一旦保存就是持久性的。
声明性事务四大特性ACID
@Transactional 可以标记在类上面(当前类所有的方法都运用上了事务)
@Transactional 标记在方法则只是当前方法运用事务
也可以类和方法上面同时都存在, 如果类和方法都存在@Transactional会以方法的为准。如果方法上面没有@Transactional会以类上面的为准建议:@Transactional写在方法上面,控制粒度更细, 建议@Transactional写在业务逻辑层上,因为只有业务逻辑层才会有嵌套调用的情况。
子类继承父类事务,子类依然具有事务功能
@Transactional注解应该写在哪:
事务配置属性
不可重复度
幻影读
并发事务产生问题
并发安全:SERIALIZABLE>REPEATABLE_READ>READ_COMMITTED运行效率:READ_COMMITTED>REPEATABLE_READ>SERIALIZABLE
设置隔离级别(isolation)
事务的传播特性
指定事务等待的最长时间(秒)当前事务访问数据时,有可能访问的数据被别的数据进行加锁的处理,那么此时事务就必须等待,如果等待时间过长给用户造成的体验感差。
超时属性(timeout)
设置事务只读(readOnly)
异常属性
在实战中事务的使用方式
面试题:Spring事务的实现方式和实现原理说一下Spring的事务传播行为说一下 spring 的事务隔离?Spring框架的事务管理有哪些优点?操作!!
面试题
事务实现流程
Spring事务流程和源码
SpringMVC流程
SpringMVC流程和源码
MyBatis流程和源码
Spring整合MyBatis的源码解析
源码框架专题
五种数据结构
高性能原理
Redis核心数据结构与高性能原理
RDB快照(snapshot)
AOF(append-only file)
Redis 4.0 混合持久化
Redis持久化
主从架构
主从、哨兵架构
集群架构
Redis的主从、哨兵、集群架构
Redis分布式实战锁
1、缓存空对象
2、布隆过滤器
缓存穿透
由于大批量缓存在同一时间失效可能导致大量请求同时穿透缓存直达数据库,可能会造成数据库瞬间压力过大甚至挂掉,对于这种情况我们在批量增加缓存时最好将这一批数据的缓存过期时间设置为一个时间段内的不同时间。
缓存失效(击穿)
1) 保证缓存层服务高可用性,比如使用Redis Sentinel或Redis Cluster。
2) 依赖隔离组件为后端限流熔断并降级。比如使用Sentinel或Hystrix限流降级组件。比如服务降级,我们可以针对不同的数据采取不同的处理方式。当业务应用访问的是非核心数据(例如电商商品属性,用户信息等)时,暂时停止从缓存中查询这些数据,而是直接返回预定义的默认降级信息、空值或是错误提示信息;当业务应用访问的是核心数据(例如电商商品库存)时,仍然允许查询缓存,如果缓存缺失,也可以继续通过数据库读取。
3) 提前演练。 在项目上线前, 演练缓存层宕掉后, 应用以及后端的负载情况以及可能出现的问题, 在此基础上做一些预案设定。
缓存雪崩
开发人员使用“缓存+过期时间”的策略既可以加速数据读写, 又保证数据的定期更新, 这种模式基本能够满足绝大部分需求。 但是有两个问题如果同时出现, 可能就会对应用造成致命的危害:当前key是一个热点key(例如一个热门的娱乐新闻),并发量非常大。重建缓存不能在短时间完成, 可能是一个复杂计算, 例如复杂的SQL、 多次IO、 多个依赖等。在缓存失效的瞬间, 有大量线程来重建缓存, 造成后端负载加大, 甚至可能会让应用崩溃。要解决这个问题主要就是要避免大量线程同时重建缓存。我们可以利用互斥锁来解决,此方法只允许一个线程重建缓存, 其他线程等待重建缓存的线程执行完, 重新从缓存获取数据即可。
热点缓存key重建优化
Redis缓存设计与性能优化
配置文件优化:可以适当增加Redis的最大连接数(maxclients),设置合适的内存限制(maxmemory),根据实际情况设置合理的超时时间,确保Redis能够处理足够多的连接和请求
网络配置优化:调整操作系统的参数,如增加文件描述符限制、调整TCP连接参数等,以提高Redis的并发处理能力。
配置优化
分片横向扩展:将数据按照一定规则划分到多个Redis实例中,每个实例负责处理一部分数据。这样可以将负载均衡到多个实例上,提高整体并发能力。
分区键优化:合理选择分区键,避免某个键对应的数据集中在某个实例上,导致某个实例成为热点,影响整体性能。
数据分片
数据预加载:启动Redis时,可以通过导入rdb文件或者aof文件来提前将数据加载到内存中,避免数据一开始大量访问导致的性能瓶颈。
缓存预热:根据业务情况,在Redis启动前预先将热点数据加载到缓存中,可以提前将数据加载到内存中,避免大量请求的时候造成冷启动的性能问题。
数据预加载和缓存预热
主从复制:通过搭建Redis主从复制架构,将读请求分发到从节点,减轻主节点的负载,提高并发能力。
哨兵模式:通过引入Redis哨兵来实现自动的故障转移和主从切换,保证Redis的高可用性。
使用主从复制和哨兵模式
Redis Cluster:Redis Cluster支持在多个节点上分布数据,自动进行数据分片和容错,实现高可用和高并发
使用集群模式
综上所述,通过合理的配置优化、数据分片、数据预加载和缓存预热、主从复制和哨兵模式、使用集群模式等方法来解决Redis高并发问题。
redis的高并发
分布式缓存技术Redis
客户端与zookeeper断开连接后,该节点依旧存在,只要不手动删除该节点,他将永远存在
PERSISTENT-持久化目录节点
客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点
客户端与zookeeper断开连接后,该节点被删除
EPHEMERAL-临时目录节点
客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点
Container 节点
( 默认禁用,只能通过系统配置 zookeeper.extendedTypesEnabled=true 开启,不稳定)
TTL 节点
zookeeper特性和节点数据类型
zookeeper客户端使用和集群特性
zookeeper典型使用场景实战
zookeeper典型核心源码解析
zookeeper的ZAB原理和源码
分布式协调服务zookeeper
单例模式:懒汉与饿汉,使用饿汉模式,数据库连接池,创建一个单例对象,用于提供对数据库连接方法,还有在一些配值类中,声明一个配置读取单例用于配值类的读取。
原型模式:创建复杂对象时,如果每次都是从头初始化,可能会带来性能开销或者逻辑过于复杂,通过实现Cloneable()接口与实现Searializiable接口实现浅克隆与深克隆。
模板方法模式:主要特点是封装了不变的部分,扩展了可变的部分。它将不变的算法骨架封装在父类中,而将可变的步骤留给子类实现。使用场景:当某个方法的实现需要多个步骤,其中有些步骤是固定的,而有些步骤可以变化时。
工厂方法模式:定义工厂接口,然后根据具体工厂类进行产品的管理,客户端直接与具体的工厂进行交互。
建造者模式:创建带参数的构造器对象的时候可以使用建造者模式,可以动态改变参数传递顺序,代码可读性也会更好。
代理模式:面向切面编程,日志处理,事务管理这些都可以用代理模式,有接口用jdk动态代理,无接口用cglib动态代理。
策略模式:在Java开发中,策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。通过定义一系列可互换的算法(策略),并在上下文中使用这些策略来解决特定问题,就是定义抽象的策略接口,定义不同接口实现类实现不同的策略,比如:电商网站购卡的不同优惠策略。
观察者模式:用于实现对象之间的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都会得到通知并自动更新。比如:消息队列就是典型的观察者模式。
备忘录模式:用于在不违反封装性原则的前提下,捕获并存储对象的内部状态,以便将来可以恢复到之前的状态,用于在一些回滚的场景,用于还原状态。
装饰者模式:java.io` 包中的输入/输出流类如 `BufferedReader`、`BufferedWriter`、`DataInputStream` 和 `DataOutputStream` 等,这些类作为装饰器添加额外功能到基础的 `InputStream` 和 `OutputStream` 流上。
类名使用 UpperCamelCase 风格,以下情形例外 :DO / PO(持久对象) / DTO(数据传输对象 )/ BO(业务对象) / VO / UID 等。使用版本控制:如Git,管理代码变更,便于追踪和协作。编写清晰的注释:为复杂的逻辑、方法和类提供注释。异常处理:妥善处理异常,并给出明确的错误信息。遵循SOLID原则:编写可维护、可扩展和可测试的代码。使用日志:记录关键信息和错误,便于调试和排查问题。编写测试:包括单元测试、集成测试和功能测试。避免硬编码:将常量、配置信息等放入配置文件或环境变量中。遵循代码风格指南:保持代码风格一致。使用合适的集合:根据需求选择合适的集合类型。避免长方法:将长方法拆分为多个小方法。使用设计模式:在适当的情况下使用设计模式。考虑接口兼容性:修改老接口时,确保新旧接口的兼容性。遵循依赖注入原则:通过依赖注入来解耦代码,提高代码的可测试性和可维护性。使用接口隔离原则:为每个类定义明确的接口,并只让它们依赖于它们真正需要的接口。使用设计模式:不仅限于常见的设计模式,也要根据具体场景选择合适的设计模式,如观察者模式、策略模式等。
好的编程习惯
设计模式
自由主题
JAVA技术栈
0 条评论
回复 删除
下一页