技术学习总结
处理并发的方法
1.系统拆分,单个系统拆分成多个子系统,每个系统对一个库,可以较之前多抗高并发。
2.缓存,存在大量只读不写的数据,可以考虑存入缓存,然后定时更新机制。
3.分表,
4.读写分离
5.MQ,消息队列,让请求排队
垃圾收集算法:
标记-清除算法:直接标记不活跃的对象并清除、(容易造成内存碎片)
复制算法:当对象满的时候,复制活跃的对象放置于下个空闲快里。
标记-整理算法:在进行完标记-清除算法后,全体左移,更新索引。去除内存碎片产生的问题。
分代收集算法:目前大部分jvm的垃圾收集器采用的算法。
将堆区分为年轻代和老年代,在堆区之外还存在一个永久代(基本存放静态变量和方法)。
老年代:每次只有少量对象被清理。
年轻代:每次都有大量的对象被清理。
年轻代分为一个ENDU和两个survivor区(8:1:1)。
ENDU区满时候,发动minorGC清理,存活的对象放置于sorvivor0区,当sorvivor0区满的时候,将ENDU和sorvivor0的信息存放至sorvivor1中,此时sorvivor0为空,再讲sorvivor1区中的信息放置于sorvivor0中,保持sorvivor1为空
当sorvivor1不足以放置ENDU和sorvivor0存活的对象的时候,将存活对象放置于老年代。老年代再满会触发FULLGC。
能够进入老年代的对象:
1.大对象:所谓的大对象是指需要大量连续内存空间的java对象,最典型的大对象就是那种很长的字符串以及数组,大对象对虚拟机的内存分配就是坏消息,尤其是一些朝生夕灭的短命大对象,写程序时应避免。
2.长期存活的对象:虚拟机给每个对象定义了一个对象年龄(Age)计数器,如果对象在Eden出生并经过第一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并且对象年龄设为1,。对象在Survivor区中每熬过一次Minor GC,年龄就增加1,当他的年龄增加到一定程度(默认是15岁), 就将会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。
3.动态对象年龄判定:为了能更好地适应不同程度的内存状况,虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升到老年代,如果在Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。
mysql的索引类型
唯一索引,主键索引 组合索引 全文索引 普通索引
事务的ACID
原子性、隔离性、一致性、持久性
分布式事务:
多个服务之前夹杂着一个检查层,全部服务成功之后,才往下走
可能某个服务停止运行,导致一直处于等待状态,并且长期占用资源,可以设置过期时间
synchronized 和 lock
synchronized是java中的变量
lock是一个接口 使用较复杂 使用的时候需要先获得锁,再手动释放锁。synchronized是自动获得所和释放锁
lock在线程多的时候比synchronized性能好,
分布式系统具有 一致性 、可用性、分区容错性
volatitle修饰的变量存在主存上,只要修改所有线程都能读写到
线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。
mybatis中的$和#的区别
#{}是预编译的,是安全的,系统会自动带上“”,
${}是未经过编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
ArrayList和linkedList的区别
线程池合适的线程数量是多少?
通用公式:
线程数 = CPU 核心数 * (1+ IO 耗时/CPU 耗时)
结论:
- 线程的 CPU 耗时所占比例越高,就需要越少的线程
- 线程的 IO 耗时所占比例越高,就需要越多的线程
- 针对不同的程序,进行对应的实际测试就可以得到最合适的选择
- 线程数 >= CPU 核心数
多线程框架:Executors框架
多线程的队列
ConcurrentHashMap如何保证线程安全的:
redis实现分布式锁 setNx 设置key值 当key值不存在的时候返回key,若key值已存在则返回0
exprie设置释放时间
delete删除key值
AarrayList的默认长度为0,每次扩容大概为1.5倍,第一次扩容后长度为10.
线程有以下状态:新建状态、就绪状态(等待线程调度调用、获取CPU使用权)、运行状态、阻塞状态(等待阻塞、同步阻塞、其他阻塞)、死亡状态
定时任务实现:
@Scheduled和定时任务框架Quartz
前者为springBoot自带注解,方便使用
Quartz建表存放定时机制,优点是业务人员可自动调整定时机制
,缺点是比较复杂,维护麻烦。
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。
Quartz是一个完全由java编写的开源作业调度框架。不要让作业调度这个术语吓着你。尽管Quartz框架整合了许多额外功能, 但就其简易形式看,你会发现它易用得简直让人受不了!
在开发Quartz相关应用时,只要定义了Job(任务),Trigger(触发器)和Scheduler(调度器),即可实现一个定时调度能力。其中Scheduler是Quartz中的核心,Scheduler负责管理Quartz应用运行时环境,Scheduler不是靠自己完成所有的工作,是根据Trigger的触发标准,调用Job中的任务执行逻辑,来完成完整的定时任务调度。
Job - 定时任务内容是什么。
Trigger - 在什么时间上执行job。
Scheduler - 维护定时任务环境,并让触发器生效。
为防止服务宕机导致定时任务未执行,缓存或者库里数据不是最新得,需要添加中间件redis或者MQ操作,每次请求之前确定数据是否经过更新,若没有,则需要重新更新下。
mysql的隔离机制
read uncommitted (读取未提取内容)
所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
分布式系统:分布式服务主要为了解决可以横向扩展(服务部署多个实例,分摊并发压力),解决高并发问题,而且可以迭代更新(添加新服务)
AQS:
什么是OOM? OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”
JMM:为java内存模型
JVM:为虚拟机内存模型
JVM:程序计数器,java堆,方法区,java栈、本地方法栈;
程序计数器:行号指示器,通过改变此值,以选取下一步指令、 java虚拟机栈:局部变量、方法出口等、为JVM服务;本地方法栈:局部变量、方法出口等;java虚拟机堆:内存最大的一块,所有的对象实例都在这里分配内存;方法区:常量、静态变量等。
Hash索引
所谓Hash索引,当我们要给某张表某列增加索引时,将这张表的这一列进行哈希算法计算,得到哈希值,排序在哈希数组上。所以Hash索引可以一次定位,其效率很高,而Btree索引需要经过多次的磁盘IO,但是innodb和myisam之所以没有采用它,是因为它存在着好多缺点:
1、因为Hash索引比较的是经过Hash计算的值,所以只能进行等式比较,不能用于范围查询
1、每次都要全表扫描
2、由于哈希值是按照顺序排列的,但是哈希值映射的真正数据在哈希表中就不一定按照顺序排列,所以无法利用Hash索引来加速任何排序操作
3、不能用部分索引键来搜索,因为组合索引在计算哈希值的时候是一起计算的。
4、当哈希值大量重复且数据量非常大时,其检索效率并没有Btree索引高的。
Btree索引
至于Btree索引,它是以B+树为存储结构实现的。
但是Btree索引的存储结构在Innodb和MyISAM中有很大区别。
在MyISAM中,我们如果要对某张表的某列建立Btree索引的话,如图:
所以我们经常会说MyISAM中数据文件和索引文件是分开的。
因此MyISAM的索引方式也称为非聚集,Innodb的索引方式成为聚集索引。
至于辅助索引,类似于主索引,唯一区别就是主索引上的值不能重复,而辅助索引可以重复。
因此当我们根据Btree索引去搜索的时候,若key存在,在data域找到其地址,然后根据地址去表中查找数据记录。
至于Innodb它跟上面又有很大不同,它的叶子节点存储的并不是表的地址,而是数据
我们可以看到这里并没有将地址放入叶子节点,而是直接放入了对应的数据,这也就是我们平常说到的,Innodb的索引文件就是数据文件,
乐观锁 :只有在提交的时候才会去对修改的数据加锁
悲观锁:在操作的时候就加上锁了
redis的zset(sorted set)是一个有序集合。它里面的每一个member都有一个对应的score用来排序,由于score是double类型的,理论上可以满足任何数量优先级的需求。本文就是基于zset来设计一个千万级容量的优先队列。
arrlist的最大值是:2的31次方-8 int的最大值-8
arrlist的底层原理:首先在object[size]添加值,然后size加1,满了得时候,新建个list,然后复制进去新list中
springBean的生命周期有四种:实例化、属性赋值、初始化、销毁
分布式事务在于保证不同服务节点的数据一致性
Eureka和zookeeper的区别:
Eureka满足分布式服务的AP特性(可用性和分区容错性)
zookeeper满足分布式服务的CP特性(一致性和分区容错性)
zookeeper在master节点因为网络等原因发生故障的时候与其他节点失去联系,剩余节点在此期间会自动记性leader选举,在此期间,zk集群服务不可用
Eureka优先保证可用性,几个节点之间是平等的,几个节点挂掉都不会影响正常工作,剩余节点依旧可以进行注册和查询服务。
AOP是类似横切的技术,将影响多个类的公共行为封装成一个可重用模块,命名为切面。切面就是与业务无关。却为业务模块所共同调用的逻辑或责任封装起来,减少系统的重复代码,降低模块之间耦合度,将核心关注点和横切关注点分离开来。
AOP的核心概念:
- 横切关注点:对那些方法拦截,怎么处理
- 切面:类是对物体特征的抽象,切面是对横切关注点的抽象
- 连接点:被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就 是被拦截到的方法,实际上连接点还可以是字段或者构造器
- 切入点:对连接点进行拦截的定义
- 通知:指拦截到连接点要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
- 目标对象:代理的目标对象
- 织入:将切面应用到目标对象并导致代理对象创建的过程
- 引入:在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
预防XSS注入对用户 输入得信息,例如”<>“做转义处理
SQL注入:对外部sql做转义处理
TCP 三次握手:
第一次:手机客服端向服务端发送syn包,进入SYN_SEND状态,等待服务端确认
第二次:服务端收到syn包之后,必须确认客户端的syn包,同时自己也发送一个syn包即syn+ack包给客户端,此时服务器进入SYN_RECV状态
第三次:客户端收到用户端的syn+ack包,向服务器发送确认包ACK包,此包发送完毕,服务端和客户端正式连接。
断开连接也需要握手一次,需要其中一方断开连接。
HTTP协议显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。
innodb为什么选择b+树,是因为b+树能够很好的配合磁盘的读写特性,减少单次查询的磁盘访问次数、降低IO、提升性能
HSAHMAP
(1)首先将k,v封装到Node对象当中(节点)。
(2)然后它的底层会调用K的hashCode()方法得出hash值。
(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。
Spring Cloud基于Spring Boot提供了一套微服务解决方案,并配置服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用SpringBoot的开发风格做到一键启动和部署。
springBoot是一个快速开发框架,通过maven依赖的继承方式,帮助我们快速整合第三方常用框架,完全采用注解化(使用注解方式启动springmvc),简化xml配置,内置http服务器,最终以java应用程序进行执行。
callable和runnable
callable具有返回值,可以返回futer对象,runnable没有返回值
无序的数组,求两两相加等于固定key值的算法:
map key存下标,value存前后相加的值,加完以后,然后map查一下有没有key,如果有的话直接输出下标就行。
@SpringBootApplication
主要下面包含@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
线程得七大参数:
(1)corePoolSize:线程池中常驻核心线程数
(2)maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
(3)keepAliveTime:多余的空闲线程存活时间。当前线程池数量超过corePoolSize时,当空闲时间到达keepAliveTime值时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止。
(4)unit:keepAliveTime的时间单位
(5)workQueue:任务队列,被提交但尚未执行的任务
(6)threadFactory:表示生成线程池中的工作线程的线程工厂,用于创建线程,一般为默认线程工厂即可
(7)handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何来拒绝来请求的Runnable的策略
gateway过滤器:
GlobalFilter :应用于全局的路由。 可以在接口访问之前校验token和token的正确性
gatewayFilter:应用于单个或者某个分组的路由上。
伪共享:CPU的缓存是以缓存行为单位进行缓存的,当多个线程对各自独立的变量进行修改时,而这些变量又恰巧位于同一个缓存行时,就会无意中影响彼此的性能,这就是伪共享。