java
一.jdk8新特性
1. 接口新增默认方法和静态方法。默认方法加上default修饰符,并且有方法体;静态方法使用static声明
2. 函数式接口:只有一个抽象方法的接口称为函数式接口,接口类上通过@FunctionInterface注解可以检测接口是否只有一个抽象函数。
3. lambda表达式:Runnable runnable = () -> System.out.println("Hello world");
二.java引用类型
1. 强引用:内存不足时,虚拟机宁愿抛出异常也不会回收强引用对象
2. 软引用:内存足够时,软引用对象可用;内存不足时,jvm会回收软引用对象
3. 弱引用:不管内存是否足够,jvm都会回收该对象
4. 虚引用:如果一个对象仅持有虚引用,则任何时候都有可能被回收,必须结合ReferenceQueue使用(用来跟踪对象被垃圾回收的活动)
三. 锁
1. synchronized与Lock的区别
a. synchronized是一个关键词,Lock是一个接口
b. 出现异常时synchronized自动释放锁,Lock不能自动释放
c. synchronized不能知道是否已经加过锁,Lock.tryLock能判断是否已经加锁
d. synchronized采用的是CPU悲观锁,即线程获得是独占锁。很多线程阻塞时,会导致CPU频繁切换上下文,效率很低。
Lock采用的是乐观锁,如果有冲突时,会进行重试直到成功。乐观锁的机制是CAS
e. Lock可以让等待锁的线程响应中断,而synchronized则不行
lock.lockInterruptibly(); //允许在等待时由其他线程调用Thread对象的interrupt()方法中断等待锁的线程r
2. Condition的使用
当满足一定条件时,调用condition的await()方法使当前线程休眠进行等待,调用Condition的signalAll()方法唤醒因await()进入等待的线程。
典型的生产-消费模型中可以使用:
ReentrantLock lock = new ReentrantLock();
consummerCond = lock.newCondition();
providerCond = lock.newCondition();
List<String> pool = new ArrayList<String>();
int maxSize = 100;
consummer(){
lock.lock();
try{
//如果池中数据为空,则线程等待
if(pool.size() == 0){
consummerCond.await();
}
pool.get();//从池中消费
providerCond.signalAll();//唤醒所有等待的生产者
}catch(){}
finally{
lock.unlock();
}
}
3. ReentrantLock相比Synchronized的特有功能:
a. ReentrantLock支持公平锁和非公平锁,公平锁即先等待的线程先获得锁;Synchronized只能支持非公平锁
b. ReentrantLock提供了Condtion类,用来分组唤醒需要唤醒的线程。而synchronized要么随机唤醒一个线程,要么唤醒所有的线程
c. ReentrantLock提供来了一种能够中断等待锁的线程的机制,通过lock.lockInterruptibly()实现
4. AQS(AbstractQueuedSynchronized抽象队列同步器)实现原理
加锁原理:AbstractQueuedSynchronized把所有请求的线程构成一个CLH队列(FIFO队列),当一个线程执行完毕(lock.unLock())时会激活自己的后继节点, 而那些等待的线程都处于阻塞状态。
线程阻塞调用的是LockSupport.park(),而LockSupport.park()调用的是sun.misc.Unsafe.park()
https://www.jianshu.com/p/279baac48960
四. 集合
1. HashMap线程不安全的原因:
HashMap初始容量为16,负载因子为0.75(3/4);当HashMap容量达到0.75*总容量时,会自动进行扩容,扩容时需要对所有的元素重新计算索引位置。
线程不安全的原因:扩容时会可能会形成环形的链表。
| |
| |->A->B
| | ===线程2执行结束===> | |->B->A
a. 线程1挂起时: e -> A, e.next -> B
b. 此时线程2开始执行,并完成: | |->B->A
c. 线程1继续执行: | |->B<=>A 此时A和B形成环路
2. CopyOnWriteArrayList的实现原理:
应用于多读少写的场景
原理:每次修改时会将原数据copy一份进行修改,然后在将指针指向新的数据
五. 类加载
1. 类加载的过程
a. 加载:查找并加载类的二进制数据
b. 链接-验证:保证加载类的正确性(文件格式、元数据、字节码、符号引用验证)
c. 链接-准备:分配内存初始化默认值(基本类型的static值一般为0,引用的静态类型一般为null;如果有final修饰,则会被赋予代码中的值,并放入方法区的常量池中)。类的实例变量的内存分配随着对象的实例化在堆上分配。
d. 链接-解析:符号引用解析为直接引用
e. 初始化:为类的静态变量初始化正确的值
3. 类加载有线程安全问题吗?
六. JVM虚拟机
1. JVM内存模型:
元空间(metaspace替代永久代)+ 堆(Heap)
堆:老年代+新生代(Eden + from + to)
survivor1和survivor2两个幸存区的大小一样,Eden区对象没有被回收掉时会在两个survivor中来回拷贝,当满足某个条件(例如拷贝次数)时就会拷贝到老年 代,survivor只是增加了对象在年轻代的逗留时间,增加来了垃圾回收的可能性。
2. JVM调优:
a. 堆内存大小设置(YOUNG+OLD),-Xmx设置最大堆内存,-Xms设置虚拟机启动时内存(一般将两个设置相同的值,减少系统运行过程中动态申请的开销)
b. 新生代、老年代大小设置:默认比例1:2,可以通过-XX:newSize和-XX:MaxNewSize控制新生代的大小,一般把newSize和MaxNewSizes设置为相同的值,防止年轻代的堆收缩。可以通过-XX:NewRatio设置新生代与老年代的比例(4表示新生代与老年代1:4)。
-XX:Xmn 设置年轻代大小
-XX:Xss 设置每个线程栈的大小(jdk1.4默认256k,jdk1.5默认1M,一般项目中设置为256k即可)
c. 选择合适的垃圾收集器
-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=20 吞吐量调优
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC 提高吞吐量,减少停顿
d.
七. 垃圾收集
并行收集算法:多线程进行垃圾收集,回收期间会暂停程序执行
并发收集算法:多线程进行垃圾收集,回收期间不会暂停程序执行(吞吐量相对较低)
1. 什么时候垃圾回收?
a. 年轻代的Eden区不够用时,触发YongGc
b. 老年代满时触发FullGC(同时回收年轻代和年老代)
c. 永久代满时触发FullGC,会导致Class、Method元信息的卸载
2. 系统什么时候OOM?
a. JVM 98%的时间都花费在内存回收时
b. 每次回收的内存小于2%时
3. GC算法
a. 引用计数:难处理循环引用
b. 复制算法:没有碎片,但内存利用率不高
c. 标记清除:先标记要回收的对象,然后统一回收(有碎片,内存利用率高)
d. 标记整理:标记、压缩,然后往一端移动存活的对象(没有碎片)
4. 垃圾收集器种类
新生代垃圾收集器:Serial、ParNew、Parallel Scanverge
老年代垃圾收集器:Serial Old、Parallel Old、CMS
回收整个java堆(新生代、老年代):G1
a. Serial串行收集器:复制算法,垃圾收集时必须暂停其他工作线程,Client模式下默认新生代收集器
b. ParNew收集器:复制算法,新生代并行收集器(Serial的多线程版本)
c. Parallel Scanverge并行回收:复制算法,追求高吞吐量、高效利用CPU
d. Serial Old收集器:标记整理算法
e. Paralle Old收集器:标记整理算法
f. CMS收集器:标记清除算法,以获取最短回收停顿为目标(并发收集器),无法处理浮动垃圾
g. G1收集器:标记整理算法
https://www.jianshu.com/p/883a682dd25e
5. 如何选择垃圾收集器:
a、单CPU或者小内存,单机程序 — -XX:+UseSerialGC
b、多CPU,需要大吞吐量,如后台计算型应用
-XX:+UseParallelGC + -XX:+UseParallelOldGC
c、多CPU,追求低停顿时间,快速响应如互联网应用
-XX:+UseParNewGC + -XX:+UseConcMarkSweepGC
八. OOM、CPU占用高等问题排查
1. OOM问题排查
a. java启动命令上加上-XX:+HeapDumpOnOutOfMemoryError参数
b. jmap到处dump文件,通过MAT工具分析
2. CPU占用高问题排查
a.使用top查看占用cpu高的进程
b. 使用top -Hp pid查看占用cpu高的线程
c. 使用jstatk导出处线程栈,分析对于的线程
3. tomcat假死问题排查
a. 排查nginx问题,可以查看nginx的access.log是否有请求访问日志
b. 排查nginx到tomcat的网络情况,查看localhost_access.log是否有请求日志
c. 排查JVM是否有内存溢出,检查日志是否有OOM
d. 排查JVM的GC情况,是否有长时间或频繁的GC
e. 检查linux的load情况,top命令查看
f. 检查应用程序是否有死锁,通过jstack命令分析
g. 排查TCP是否有大量的CLOSE_WAIT(被动关闭,即对方关闭tcp连接后,服务器程序自己进一步发出ack信号,导致资源一直不能释放)
4. 死锁问题分析
a. 通过jstack导出线程栈信息,在日志信息中搜索deadlock关键词
如何解决死锁问题:对多个资源、数据库表、对象加锁时,需要保持加锁的顺序一致;否则,可能会造成死锁
九. IO与NIO
十. JAVA零拷贝
a. 零拷贝是指用户态和内核态之间拷贝数据的次数为0
b. 普通的数据拷贝需要4次用户态与内核态的上下文切换,并且数据被复制了四次(例如:File --> Read Buffer --> JVM --> Sockert Buffer --> Socket)
NIO中的FileChannel拥有transferTo和transferFrom两个方法,可直接把FileChannel中的数据拷贝到另外一个Channel,或直接把另外一个Channel中的数据拷贝到FileChannel。
原理:transferTo将数据从指定的文件通道传输给可写文件通道(依赖底层操作系统对零拷贝的支持)
十一. 多线程
a. 为什么wait、notify、notifyAll这些方法不Thread中?
因为java提供的锁是对象级的,而不是线程级的
b. 线程状态
新建状态:Thread thread = new Thread();
就绪状态:thread.start();
运行状态:当cpu分配给该线程执行时才处于运行状态
阻塞状态:
死亡状态:
Mysql
1. Mysql查询时limit offset比较大时的性能问题 https://blog.csdn.net/fdipzone/article/details/72793837
优化方案:先根据索引查询出主键id,然后根据主键id关联出数据
知识点:
a. mysql一级索引、二级索引,以及innodb与myisam的索引区别
2. Mysql索引原理 https://www.jianshu.com/p/d90f6b028d0e
索引:索引是数据库管理系统中一个排序的数据结构(通常使用B+Tree)
Mysql引擎:Innodb和MyISAM,两种引擎的索引都是B+Tree数据
Innodb索引与MyISAM索引区别:
a. Innodb索引是聚集索引,数据文件本身就是主键索引,叶节点保存了完整的数据记录。MyISAM索引是非聚集索引,索引和数据分离
b. Innodb辅助索引叶节点data域 存储相应数据的主键值
3. MyISAM与Innodb的区别
1)InnoDB支持事务,MyISAM不支持。
2)MyISAM适合查询以及插入为主的应用,InnoDB适合频繁修改以及涉及到安全性较高的应用。
3)InnoDB支持外键,MyISAM不支持。
4)从MySQL5.5.5以后,InnoDB是默认引擎。
5)MyISAM支持全文类型索引,而InnoDB不支持全文索引。
6)InnoDB中不保存表的总行数,select count(*) from table时,InnoDB需要扫描整个表计算有多少行,但MyISAM只需简单读出保存好的总行数即可。 注:当count(*)语句包含where条件时MyISAM也需扫描整个表。
7)对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立联合索引。
8)清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表。MyisAM使用delete语句删除后并不会立刻清理磁盘空间,需要定 时清理,命令:OPTIMIZE table dept;
9)InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like ‘%lee%’)
10)Myisam创建表生成三个文件:.frm 数据表结构 、 .myd 数据文件 、 .myi 索引文件,Innodb只生成一个 .frm文件,数据存放在ibdata1.log
现在一般都选用InnoDB,主要是MyISAM的全表锁,读写串行问题,并发效率锁表,效率低,MyISAM对于读写密集型应用一般是不会去选用的。
应用场景:
* MyISAM不支持事务处理等高级功能,但它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
* InnoDB用于需要事务处理的应用程序,包括ACID事务支持。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能。
4. 数据库3范式
第一范式:属性的原子性约束,即要求字段不可拆分
第二范式:满足第一范式前提下,非主键字段要完全依赖主键字段,而不是依赖主键字段的一部分(常见于复合主键的情况)
第三范式:满足第二范式前提下,非主键字段不能出现传递依赖(比如某个字段a依赖于主键,而一些字段依赖字段a)
5. 事务四大特性
原子性:一个事务内的一组操作要么都成功,要么都失败
一致性:一个事务使数据从一种正确状态变更到另一种正确状态
隔离性:事务之间彼此隔离互不影响
持久性:事务一旦提交,其结果将是永久的,即便发生系统故障也能恢复
6. 事务隔离级别
读未提交:允许脏读,可以读取到其他事务未提交的数据
读已提交:只能读取到事务已经提交的数据(数据库默认级别)
可重复读:无论其他事务是否已经提交,当前事务读取的数据不受其他事务影响
串行化:事务串行化执行,读写操作会互相阻塞
注意:MySql数据库(Innodb引擎)默认使用可重复读
7. Mysql中的锁
* MyISAM支持表锁,InnoDB支持表锁和行锁,默认为行锁
* 表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低
* 行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高
8. Mysql死锁的原因及解决方法
解决方法:多个session加锁的顺序约定一致
9. delete、drop、truncate的区别
a. truncate和delete只删数据不删表结构,drop删除表结构和数据
b. delete数据DML,需要事务管理,commit后才生效。truncate和drop属于DDL,不需要事务管理,不可回滚
c. 删除速度:drop > truncate > delete
10. 多版本并发控制(MVCC)--乐观锁的一种实现方式
a. 每行数据都存在一个版本,每次数据更新都更新该版本
b. 修改时copy出数据随意更改,各事务之间无干扰
c. 保存时比较版本号,成功则commit;否则,rollback
注意:mvcc只适用innodb中的读已提交(RC)和可重复读(RR)
mvcc实现策略:每一行隐藏两个列(行创建时的版本号和删除时的版本号)
11. 如何进行SQL优化
a. 选择正确的数据库引擎(MyISAM、Innodb)
MyISAM:查询多、支持全文检索、不支持事务、表锁(update性能低,update时阻塞读)
Innodb:不支持全文检索、支持事务、行锁(update性能高)、数据安全性高
b. 优化字段的数据类型
原则:越小的列会越快(smallint比int小,date比datetime小)
c. 为搜索字段添加索引
d. 避免适用select *查询
e. 使用ENUM而不是varchar
f. 固定长度的表会更快。如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。固定长度容易计算偏移量
12. SQL优化技巧:
a. where表之间的连接必须写在其他where条件之前,可以过滤掉大量数据的条件必须写在where子句末尾
b. 用exists代替in、用not exists代替not in
c. 避免在索引列上使用函数计算
d. 避免在索引列上使用is null、is not null
13. exist和in
in是把外表和内表作hash join;exist对外表作loop循环,每次循环对表进行查询
如果内表较大则exist效率高;如果内表较小,则in效率较高;如果两个表数据量差不多,则效率差不多
14. char和varchar的区别
a. char是固定长度的,varchar是可变长度的
b. char(M)表示每个值要占固定M个字节,如果长度小于M,Mysql会自动用空格不足
varchar(M)每个值只占用刚好够用的字节再加上一个用来记录其长度的字节
15. MySql主从复制原理 https://blog.csdn.net/Marmara01/article/details/89570522
a. 主:binlog线程——记录下所有改变了数据库数据的语句,放进master上的binlong日志中
b. 从:io线程——在使用start slave之后,负责从master上拉取binlog内容,放进自己的relay log中
c. 从:sql执行线程——执行relay log中的语句;
16. Mysql复制线程有几个,以及它们之间的关联
a. Master上面的binlog dump线程
b. Slave上面的IO线程,从master上拉取binlog日志,并写入到relay log中
c. Slave上的Sql线程,读取relay log日志内容,并执行sql语句
d. 如果是多线程复制,Sql线程只做coordinator(调度),即读取relay log中的内容交给worker线程执行。
17. 事务是如何通过日志实现的
因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的
状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉
18. Mysql数据库cpu达到500%如何处理?
当 cpu 飙升到 500%时,先用操作系统命令 top 命令观察是不是 mysqld 占用导致的,如果不是,找出占用高的进程,并进行相关处理。如果是 mysqld 造成的, show processlist,看看里面跑的 session 情况,是不是有消耗资源的 sql 在运行。找出消耗高的 sql,看看执行计划是否准确, index 是否缺失,或者实在是数据量太大造成。一般来说,肯定要 kill 掉这些线程(同时观察 cpu 使用率是否下降),等进行相应的调整(比如说加索引、改 sql、改内存参数)之后,再重新跑这些 SQL。也有可能是每个 sql 消耗资源并不多,但是突然之间,有大量的 session 连进来导致 cpu 飙升,这种情况就需要跟应用一起来分析为何连接数会激增,再做出相应的调整,比如说限制连接数等
19. 主从一致性校验工具:checksum、mysqldiff、pt-table-checksum
20. Mysql中innodb的行锁是加在什么上实现的?
InnoDB是基于索引来完成行锁
例: select * from tab_with_index where id = 1 for update;
for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,
如果 id 不是索引键那么InnoDB将完成表锁,并发将无从谈起
21. explain出来的各种item的意义
id:每个被独立执行的操作的标志,表示对象被操作的顺序。一般来说, id 值大,先被执行;如果 id 值相同,则顺序从上到下。
select_type:查询中每个 select 子句的类型(SIMPLE、PRIMARY、UNION、UNION RESULT、SUBQUERY)
table:名字,被操作的对象名称,通常的表名(或者别名),但是也有其他格式。
partitions:匹配的分区信息。
type:连接类型()。
possible_keys:列出可能会用到的索引。
key:实际用到的索引。
key_len:用到的索引键的平均长度,单位为字节。
ref:表示本行被操作的对象的参照对象,可能是一个常量用 const 表示,也可能是其他表的
key 指向的对象,比如说驱动表的连接列。
rows:估计每次需要扫描的行数。
filtered:rows*filtered/100 表示该步骤最后得到的行数(估计值)。
extra:重要的补充信息
22. 分布式事务
a. 两阶段提交(2PC):
第一阶段:分别向参与者发送事务预处理请求,并返回是否成功的状态
第二阶段:事务协调者根据参与者返回的状态判断是否提交事务(第一阶段全部成功才提交)
问题:
性能问题:参与者本地事务提交或回滚后才会释放资源,对性能影响较大
协调者单点故障问题:协调者挂掉会导致参与者节点始终处于中间状态
丢失消息导致数据不一致:第二阶段提交时如果出现网络问题,可能导致只有一部分参与者收到消息
b. 三阶段提交(3PC):
第一阶段:询问参与者是否能完成本次事务
第二阶段:所有参与者执行事务,并返回是否成功的状态
第三阶段:事务协调者根据所有参与者返回的状态判断是否确认提交事务
2PC与3PC的区别:3PC对协调者和参与者都设置了超时机制,而2PC只有参与者才有超时机制,这样避免了协调者故障的问题
python(低)
RabbitMq
1. RabbitMq的好处:解耦、异步、削峰
2. RabbitMq中的Broker是什么?
broker是一个或多个erlang node的逻辑分组,并且node上运行着rabbitmq应用
3. 交换器种类:
direct:完全根据routingKey进行路由
fanout:交换器收到消息,广播到所有帮顶的队列上(与routingKey无关)
topic:可以使不同源头的消息路由到同一队列,routingKey支持通配符
header:可以根据数据中的key进行路由
4. 元数据:队列、交换机、绑定关系、vhost的定义
https://www.cnblogs.com/doit8791/p/10328402.html
5. 集群节点类型
磁盘节点:配置信息和元数据信息存储在磁盘上
内存节点:配置信息和元数据信息存储在内存中,性能远大于磁盘
注意:
a. 单节点系统必须是磁盘节点
b. rabbitmq要求集群中至少有一个磁盘节点,否则集群重启后元数据全都会丢失
如果磁盘节点全崩溃后:
a. 不能创建队列、交换器、绑定关系
b. 不能添加用户、更改权限
c. 不能添加和删除集群节点
6. 普通队列与镜像队列
普通队列:消息实体只存在于集群的一个节点上,其他节点上只存储队列的元数据
镜像队列:消息实体存在于集群的所有节点上,并且元数据存在于集群的所有节点;消息实体会主动在镜像队列之间进行同步
Redis
springcloud
1. 为什么要用springboot?
a. 独立运行:内嵌各种servlet容器、tomcat、jetty等
b. 简化配置
c. 自动配置
2. springboot核心配置:
1. bootstrap.yml 优先加在,不能被application.yml覆盖
2. application.yml
3. springboot核心注解
@SpringBootApplication用于启动类上,包含@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan
4. 自动配置的原理
5. springboot启动时运行特定代码
通过实现ApplicationRunner或CommandLineRunner接口
CommandLineRunner获取命令行参数??
ApplicationRunner获取应用启动的参数
6. springboot读取配置文件的方式
a. @ConfigurationProperties(prefix="info") //用于类上
b. @Value //用于属性上
c. @PropertySource(value={"xxx.properties"}) + @Value //不能支持yml配置
d. @PropertySource(value={"xxx.properties"}) + @ConfigurationProperties(prefix="info")
e. @Autowired
private Enviroment env; //上述的所有配置都可以通过注入Enviroment对象获取
7. springboot支持的日志框架:log4j2、logback(默认)
8. springboot热部署的方式
a. 依赖spring-boot-devtools
9. 多环境配置:启动参数spring.profiles.active
10. 单元测试
@RunWith(SpringRunner.class)
@SpringBootTest //启动测试
//==========================SpringCloud=============================
1. eureka自我保护机制:当eureka server短时间内丢失了过多的实例连接时,节点会进入自我保护模式,保护注册数据,不再删除注册数据;当故障恢复时,自动退出自我保护模式。
2. 什么是熔断?什么是服务降级?
隔离方式:线程池、信号量(默认10)
线程池隔离:请求对象与执行请求的对象解耦,通过线程实现隔离
信号量隔离:控制并发的请求量,防止线程大面积阻塞
熔断:当服务出现某个异常时,直接熔断整个服务,而不是一直等到服务线程超时
回退降级:
a. 执行run时抛出异常
b. 熔断器打开
c. 线程池或信号量超额
d. 命令执行超时
回退降级的方式:
a. fast fail(快速失败):直接抛异常
b. fast silent(无声失败):getFallback返回null或空集合
c. Fallback static:getFallback返回静态默认值
d. Fallback Stubbed: getFallback返回复合对象
3. Hystrix 底层的执行流程和步骤
a. 创建Command(HystrixCommand或HystrixObservableCommand)
b. 调用Command执行方法
hystrixCommand.execute() //同步调用
hystrixCommand.queue() //异步调用,获取Future返回结果
hystrixObservableCommand.observer()
hystrixObservableCommand.toObserver()
c. 检查是否开启缓存。如果开启了缓存并且缓存中有数据,则直接返回;否则,下一步。
d. 检查线程池/信号量是否已满
e. 执行Command
f. 断路健康监测
g. 调用fallback降级
https://blog.csdn.net/qq_25484147/article/details/83375225
https://blog.csdn.net/oldshaui/article/details/90675149
4. 雪崩效应解决方案
a. 硬件故障:多机房容灾、异地多活
b. 流量激增:服务自动扩容、流量控制
c. 缓存穿透:缓存预加载、缓存异步加载
d. 同步等待:资源隔离、MQ解耦
zookeeper
1. zookeeper介绍:zookeeper是一个分布式协调服务
读请求:可以被集群中的任意节点处理
写请求:同时会发给其他zookeeper机器,并且所有机器达成一致后才返回成功(集群集群增多,读的吞吐量提高,写的吞吐量下降)
2. zookeeper分布式一致性特点:顺序一致性、原子性、可靠性、实时性(最终一致性)
3. zookeeper提供了文件系统、通知机制两大功能
a. zk文件系统:一个多层级的节点命名空间,每个节点上都可以设置数据。在内存中维护了一个树状结构,每个节点存放数据的上限为1M(zk不能存放大量数据)
4. ZAB协议:是为分布式协调服务zookeeper专门设计的一种支持崩溃恢复的原子广播协议
5. 四种数据类型的节点:
a. 持久节点(persistent):除非手动删除,节点会一直存在zookeeper上
b. 临时节点:生命周期与客户端会话绑定,一旦客户端会话失效,客户端创建的临时节点被移除
c. 持久顺序节点:节点名后会追加一个由父节点维护的自增整型数字(拥有持久节点的性质)
d. 临时顺序节点:节点名后会追加一个由父节点维护的自增整型数字(拥有临时节点的性质)
任务调度
1. 系统组成:调度中心、执行器
2.工作原理:
a. 执行器根据配置的调度中心地址,自动注册到调度中心
b. 达到任务触发条件,调度中心下发任务
c. 执行器接收到任务后存入请求队列,任务基于线程池执行,执行结果存入队列
d. 执行器回调线程从结果队列中取出数据上报给调度中心
3. 调度中心支持多节点部署,基于数据库行锁保证同时一个任务只有一个调度中心节点触发调度。
4. 分片广播:一次任务调度将会广播给所有的执行器执行,可根据分片参数控制分片任务
5. 故障转移:如果执行器集群中某一台机器故障,则会自动切换到正常的调度器发送调度请求
6. 阻塞处理策略:如果执行器来不及执行任务,支持单机串行、丢弃后续调度、覆盖之前调度
7. 调度中心与执行器通信方式:http + hession (http能跨平台)
最近遇到的问题
1.Rabbitmq接收到不正确的数据报文时,不断的抛出异常
2.Mysql分页查询时,分页页数比较大时的性能问题