标签:三次握手 访问共享 double volatil 碎片 大内存 erp line mysq
executor.submit()返回执行结果Future(get()返回结果会阻塞线程去执行完成),executor.execute()不返回执行结果
public ThreadPoolExecutor(int corePoolSize,//核心线程数量
int maximumPoolSize,//最大线程数量
long keepAliveTime, //超过核心线程数量时,多出的线程等待keepAliveTime 时间后自行销毁
TimeUnit unit,//上面时间的单位
BlockingQueue<Runnable> workQueue,//等待队列
ThreadFactory threadFactory,//创建新线程的时候用到
RejectedExecutionHandler handler //拒绝策略
){...}
线程安全的理解:是有全局变量及静态变量引起的,只读没问题,但是写的要考虑线程同步。常量不会改没事,线程内的局部变量或者调用方法前每一个实例都是新建的,那也是线程安全的,因为不会访问共享的资源。
ReentrantLock 实现原理:基于AQS来实现。
Synchronized和Lock的异同:前者利用Object的notify/wait之类的调度,后者用Condition进行线程间调度。再者前者是可以加在方法/代码片段给JVM执行,后者直接代码段通过代码控制。前者自动释放,后者手动解锁。
其实就是指java.util.concurrent/.atomic包下的东西,例如常见的有volatile<特性禁止指令重排(1-开辟空间,2-空间初始化,3-空间指向地址变量)>、cas、concurrentHashMap、ContDownLatch、实现Callable接口创建线程、ReentrantLock同步锁、ReadWriterLock读写锁、线程池
cas:compare and swap,比较旧的值,没有改变则更新为新的值。atomicInteger就是利用cas、volatile和native方法
AQS:位于java.util.concurrent.locks包下,AQS是一个用来构建锁和同步器的框架,例如ReentrantLock和Semaphore等等,原理:被请求的共享资源空闲,那么当前空闲的线程就会被标记为运行状态,资源也被标记为被锁定,需要一套线程阻塞等待以及被唤醒时锁分配的机制,AQS使用CLH队列锁(自旋锁,先来先服务,保证无饥饿)实现,即将暂时获取不到锁的线程放在队列中。
堆:对象和数组分配内存,是垃圾收集器管理的主要区域,又称为GC堆,1.7之后运行时常量池也在此
方法区/元空间/直接内存:储存已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码数据
线程独有
基本采用分代垃圾回收算法,粗分为新生代和老年代,细分为eden,from survivor, to survivor,老年区
堆内存常见分配策略:对象优先在eden区分配,大对象直接进入老年代,长期存活的对象将进入老年代。
Minor GC:新生代垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。
FULL GC/Major GC: 发生在老年代的GC,速度比Minor GC慢10倍以上。
判断对象死亡:引用计数法, 可达性分析法(GC ROOT)
无用的类:所有实例被回收,加载该类的classLoader已被回收,对应的java.lang.class没有在任何地方被引用。
分代收集:新生代使用复制算法,老年代使用标记-清除或标记整理。
CMS收集器:Concurrent mark Sweep(并发标记清除) ,一种以获取最短回收停顿时间为目标的收集器,基本实现垃圾回收和用户线程同时工作。(缺点:对CPU资源敏感,无法处理浮动垃圾,标记清除有碎片)
- 初始标记:暂停其他所有线程,记录直接和root相连的对象
- 并发标记:同时开启GC和用户线程,记录可达对象(不能保证包含当前所有可达对象,因为还在更新)
- 重新标记:暂停用户线程,修正并发标记期间产生变动的那一部分标记记录
- 并发清楚:开启用户线程,同时GC线程开始对标记的区域做清扫。
G1收集器:Garbage-First 面向服务器的垃圾收集器,主要针对多颗处理器及大容量内存的机器,以高概率满足GC停顿时间的要求,还具备高吞吐量性能特征。使用标记整理、可预测的停顿时间模型。维护一个优先列表,优先回收价值最大的region
- 初始标记
- 并发标记
- 最终标记
- 筛选回收
指针碰撞:内存规整下,通过一个指针区分已使用和未使用的内存的位置,需要使用时,指针移动划分。
空闲列表:内存不规整,虚拟机维护一空闲列表,需要多大内存空闲列表又显示有就拿去用,如cms收集器
对象访问定位方式
1.使用句柄:堆中划分一块内存作为句柄,引用(变量名)储存的是对象的句柄地址,句柄包含对象实例数据地址指针和类型数据指针地址。对象移动只需要改变句柄的实例数据指针。
2.直接指针:引用储存的时候直接对象的地址,直接对象中包含到对象类型数据的指针和对象实例数据。速度快
.class文件包含以下:
类加载过程: 加载->链接->初始化。连接过程分为:验证->准备->解析
*数组类型不通过类加载器创建,它由Java虚拟机直接创建。
*类加载器:JVM内置了三个重要的ClassLoader,除了BootstrapClassLoader,其他都是由Java实现自java.lang.classloader。
- BootstrapClassLoader(启动类加载器): 最顶层的加载类,有C++实现,负责加载%JAVA_HOME%/lib目录下的jar包和类或者被-Xbootclasspath参数指定的路径的所有类。
- ExtensionClassLoader(拓展类加载器): 主要负责加载目录%JER_HOME%/lib/ext目录下的jar包和类,或被java.ext.dirs系统变量所指定的路径下的jar包。
- AppClassLoader(应用程序类加载器): 面向我们用户的加载器,负责加载当前应用classpath下所有的jar包和类。
*双亲委派模型(并非父母两个,而是指父母这一辈的): 每一个类都有一个对应它的类加载器,系统中的ClassLoader在协同工作的时候会默认使用双亲委派模型,即在类加载的时候,系统会首先判断当前类是否被加载过,已经被加载过类会直接返回,否则才会被尝试加载,加载的时候,首先会把该请求委派该父类加载器的loadClass()处理,因此所有的请求最终都应该传到最顶层的启动类加载器bootstrapClassLoader中。当父类加载器无法处理时,才由自己来处理,当父类加载器为null时,会启动类加载器BootstrapClassLoader作为父类加载器。这中的父子是按优先级定的,不是继承关系。
好处:保证Java程序的稳定运行,可以避免类的重复加载(JVM区分不同类的方式不仅仅根据类名,系统的类文件被不同的类加载器加载产生的是两个不同的类),保证了Java的核心API不被篡改,如果没有使用双亲委派模型,而是每个类加载器都加载自己的话就会出现一些问题,比较我们编写一个称为java.lang.Object类的话,那么程序运行的时候,系统就会出现不同的Object类。反正意思就是向上寻找是否已经加载过了。
bootstrapClassLoader必用因为它在虚拟机实现,其他不想用的话自己定义一个类加载器,重载loadClass()即可,就是继承ClassLoader
#{}是静态替换变量有注入风险,${}是利用PreparedStatement的?替换,相对于加‘‘,防止注入。
select|update|delete|insert|resultMap|parameterMap|sql|include|selectKey|
动态标签trim|where|set|foreach|if|choose|when|otherwise|bind
bind的作用是拼接字符串等操作,可以应对改数据库,sql注入
and user_name like #{userNameLike}
不同的xml写一样的namespace和id,可以但会覆盖,因为用的map<namespace+id,object>,没有写namespace的话相同id则会报错。
mybatis的executor执行器:(严格限制在SqlSession生命周期范围)
spring是一些模块的集合,包括核心容器(DI,验证,类型转换,资源,国际化,数据绑定,事件),数据访问/集成,Web,AOP,工具,消息,测试模块。
spring core,spring aspects,spring aop,spring jdbc,spring jms,orm,web,test
spring aop是运行时增强,aspects是编译时增强
注入对象可以是singleton、prototype,request,session
spring框架中用到哪些设计模式
使用的是代理模式,如果代理的是一个接口的话,就用java动态代理,如果是其他的类,使用CGLIB。
事务的特性:ACID(原子性、一致性、隔离性、持久性)
并发事务带来的问题:脏读、丢失修改、不可重复读、幻读。
TransactionDefinition.ISOLATION_DEFAULT:使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
TransactionDefinition.ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
TransactionDefinition.ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
TransactionDefinition.ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
当事务方法被另一个事务方法调用是,必须指定事务应该如何传播。
支持当前事务的情况:
不支持当前事务的情况:
其他情况:
public FilterRegistrationBean<MyFilter> setUpMyFilter() {
FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setOrder(2);
filterRegistrationBean.setFilter(myFilter);
filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
?
return filterRegistrationBean;
}
多个过滤器按指定顺序执行的话需要用上面的方法。
springboot引进来的基础包上已经包含所要用的校验注解,其中在方法上使用在类的,加@Valid,单独参数的@Valid @NotNull之类(此时controller需要加注解@Validated)。值得一提的是,因为之前有同事说处理参数校验出错的时候,不用在代理里处理bindResult,其实这种说法并不对,因为不单独处理的话时候会抛出异常MethodArgumentNotValidException,如果使用全局异常处理的话,就可以集中处理这类问题。
除了contoller之外,service这些也可以使用
xxxxxxxxxx
public class PersonService {
?
public void validatePerson( Person person){
// do something
}
}
xxxxxxxxxx
try {
InputStream inputStream = new FileInputStream(args[0]);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
@ToString
、@EqualsAndHashCode
、@Getter
、@Setter
和@RequiredArgsConstrutor
这些注解
SOLID模式:
优化方向:数据库表设计,良好的SQL、分库分表,读写分离、缓存、搜索引擎、硬件升级、索引使用、系统配置
第一范式是字段最小不可拆解,第二范式是字段和主键关联依赖,第三范式是字段和主键无间接关联(传递依赖)无冗余。
MVCC 一词代表的是多版本并发控制,只在READ COMMITED和REPEATABLE READ两个隔离级别下工作。
mysql存储引擎
mysql索引 :有Hash索引(单个查询)、BTree索引,全文索引(full text)
数据库事务
ACID:原子性、一致性、隔离性、持久性
导致问题,1.脏读(读到别的事务尚未提交的数据),2.丢失修改(当一个事务修改是,另一个事务也在修改覆盖,导致前面事务修改丢失),3.不可重复读(两次读的数据不一致),4.幻读(读着的数据行数变化)
SQL标准定义四个隔离级别:
- READ-UNCOMMITTED(读取未提交),允许读取尚未提交的数据。导致脏读,幻读,不可重复读
- READ-COMMITTED(读取已提交),允许读取并发事务已经提交的数据,还会幻读,不可重复读
- REPEATABLE-READ(可重复读),对同一个字段多次读取结果完全一致除非自己改,还会幻读
- SERIALIZABLE(可串行化),最高隔离级别,完全ACID隔离,一个个事务依次执行
mysql默认的是可重复读,使用next-key lock锁算法避免幻读。
InnoDB存储引擎锁算法:record lock(行锁)、Gap lock(间隙锁,锁一个范围,不包括记录本身),Next-key lock(record+gap锁定一个范围,包括记录本身)
使用redis的好处是,一处缓存多处使用,同时有丰富的数据类型。redis是单线程的,但是IO多路复用。
数据类型:String、List、Hash、Set、Sorted Set、bitmap位图,geo地理位置等
过期删除:定期扫描随机删除,惰性删除查的时候检查是否要删。
提供了一些内存淘汰机制,一般用allkey-lru(内存不足时,删除最近最少使用的key)
持久化机制:RDB、AOF(数据有改就写、每秒写一次、让操作系统决定)
缓存雪崩:本身就要随机地设置过期时间。尽量保证redis集群高可用性,发现机器宕机尽快补上,选择合适的内存淘汰策略。事中本地ehcache缓存+hystrix限流&降级,避免Mysql崩掉。事后利用redis持久化机制恢复缓存。
缓存穿透:null也缓存时间短些,布隆过滤器。
缓存一致:肯定不能读写串行化,一般是先更新数据库,再删除缓存(更新复杂,尤其涉及多表。写频繁就改频繁,再者也是赌你不会那么快读数据),但是在更新数据库的过程中,缓存的数据还是旧的。面对高并发之下的不一致(先删缓存再更数据),更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个jvm内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新执行"读取数据+更新缓存"的操作,根据唯一标识路由之后,也发送到同一个jvm内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行(一般就是会先执行更新数据库操作),这样的话,一个数据变更的操作,先删缓存,然后再去更新数据库,但是还没完成更新,如果一个读请求过来,没读到缓存,那么可以先将缓存更新的请求发送到队列中,此时会在队列中积压,然后同步等待缓存更新完成,最好不重复放到队列中。
浏览器输入URL发生什么:
网络分层:
应用层:通过应用进程间交互来完成特定网络应用。DNS服务、HTTP服务等等,交互的数据单元称为报文。
运输层:负责向两台主机进程之间的通信提供通用的数据传输服务。
传输控制协议TCP--提供面向连接、可靠的数据传输服务。保证可靠传输如下:
- 应用数据被分割成TCP认为最适合发送的数据块。
- TCP给发送的每个包进行编号,接收方对数据包顺序排序,把有序数据传到应用层。
- 校验和:TCP将保持它首部和数据的校验和。这是端到端的校验和,目的是检测数据在传输过程中的任何变化,有差错则丢弃这个报文段和不确认收到此报文段。
- TCP的接收端会丢弃重复的数据。
- 流量控制:TCP链接的每一方都有固定大小的缓冲空间,只接受能接纳的数据,过量则会提示发送方降低发送的速率,防止包丢失。
- 拥塞控制:当网络拥塞时,减少数据的发送。
- ARQ协议:每发完一个分组就停止发送,等待对方确认,收到确认后再发下一个分组。
- 超时重传:启动一个定时器,等待目的端确认收到这个报文段,不能及时就重发。
用户数据协议UDP--提供无连接、尽最大努力的数据传输服务。(不保证数据传输的可靠性)
网络层:两个计算机之间经过很多数据链路,也可能通过很多通信子网,就是选择合适的网间路由,确保数据及时发送。把运输层报文段或用户数据报封装成分组和包,使用IP协议,因此分组也叫IP数据报。
数据链路层:链路层,两台主机的数据传输,总是在一段一段的链路上传送的,将IP数据报组装成帧,其为了数据正确传输,包含了数据验证和纠错。
物理层:数据单位是比特,实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽具体传输介质和物理设备的差异。
三次握手:A-(SYN)-B,B-(SYN/ACK)-A,A-(ACK)-B。目的建立可靠的通信信道,确认双方发送接收正常。TCP用
四次挥手:A-(FIN)-B,B-(ACK)-A,B-(FIN)-A,A-(ACK)-B
HTTP长连接,短连接:http1.0短连接,每一个请求都建立一次链接。http1.1长连接保持连接性,请求头加上Connection:keep-alive,但是需要服务器也支持长连接。http1.1还增加了一些错误状态效应码,缓存处理更多,允许请求资源的某个部分。
URI:统一资源标志符,就像身份证号码
URL:统一资源定位符,提供资源的路径,就像个人地址。
HTTP和HTTPS的区别 : 1.端口,http用80,https用443。2.http运行在tcp之上,传输内容是明文,客服端和服务器端无法验证对方的身份。https是运行在SSL/TLS之上的HTTP协议,SSL/TLS运行在TCP之上,所有的内容都经过加密,但是HTTPS消耗资源给HTTP耗费更多。
认证:你是谁,验证你的身份凭据,系统你知道你这个用户存在。
授权:发生在认证之后,访问系统的权限。
Spring Session:一般与redis使用,可以在不同的项目中共享session。支持一个域名,同一个项目部署多台tomcat,也支持一个域名多个项目,支持同一根域名多个子域名,不支持不同根域名实现session共享。
原理:实现了一个filter,继承自OncePerRequestFilter(确保一次请求只通过一次filter),并且@Order优先级被优先执行
CSRF:跨站请求伪造,攻击者诱导受害者进入第三方网站,在第三方网站中,向北被攻击网站发送跨站请求,利用受害者已经获取的注册凭证,绕过后台的用户验证,达到冒充用户被攻击的网站执行某项操作的目的。
解决办法:同源策略,token(麻烦在某个请求都要验证)
OAuth2.0:主要用来授权第三方应用获取有限的权限。实际上它就是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌token,使得第三方应用能够通过该令牌获取相关的资源,也常用于第三方登录,当你的网站接入了第三方登录的时候一般就是使用的OAuth2.0协议。
SSO:单点登录,一个平台登录,可以自动登入其他关联平台。解决公司多平台访问。
六种负载均衡方式:(作用也是避免请求过了集中到一台机器)
- 轮询
- weight权重方式
- ip_hash根据ip分配方式,可以让同一个用户访问同一个资源。
- least_conn最少链接方式
- fair响应时间方式,请求向响应时间较短的机器发。
- url_hash依据URL分配方式,根据url请求到同一个服务器,避免缓存资源多次请求。
OOM怎么排查:如果JVM配置了-XX:+HeapDumpOnOutOfMemoryError,可以拿到发生OOM的时候,堆里面都有些什么。
一致性Hash:简单来说,就是一些节点发布在一个圆上,按顺时针找到第一个节点作为处理节点,会涉及增加节点和减少节点。一开始节点太少的时候,可以通过虚拟节点(即同一个节点A,虚拟节点A1,A2..但都是A处理)。
分布式事务:
- 两阶段提交方案/XA方案。意思就是各个数据库都准备好一个有错了全部回滚,但是一般一个服务对应一个库,所以操作上比较难控。(spring+JTA)
- TCC方案(Try Confirm Cancel):Try阶段对各个服务的资源做检测以及对资源进行锁定或预留。Confirm阶段是在各个服务中执行实际的操作。Cancel如果任何一个服务的业务方法执行出错,那么这里就需要进行补偿,就是执行已经执行成功的业务逻辑回滚。实际上是写代码回滚动和补偿。
- 本地消息表:依赖数据库的消息表来管理事务.A、B事务通知,失败又通知..............复杂到不想说
- 可靠消息最终一致性方案:本地消息表变MQ,A系统发一个准备消息到mq(发送失败就直接取消操作不执行了),发送成功后,执行本地事务,如果成功就告诉mq发送确认消息,如果失败就告诉mq回滚动消息,如果发送了确认消息,此时B系统会接收到确认消息,然后执行本地的事务,mq会自动定时论询所有准备消息回调你的接口,问你这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你可以查下数据库看之前本地事务是否执行,如果回滚了,那么也回滚,这个就是避免本地执行成功了而确认消息却发送失败。B失败就回滚动,通知A或直接抛错通知人员。
- 最大努力通知:A本地事务执行完,发送个消息到MQ,这里会有个专门消费MQ的最大努力通知服务,这个服务会消费MQ然后写入到数据库记录下来,或者放到个内存队列也可以,接着调用B的接口,B成功就ok,失败了那么最大努力通知服务就定时尝试重新调用系统B,反复N次,最后还是不行就放弃。
标签:三次握手 访问共享 double volatil 碎片 大内存 erp line mysq
原文地址:https://www.cnblogs.com/ljy-1471914707/p/12497482.html