Java
-
java内存泄漏的原因
-
java为什么是单继承
-
java的引用机制
-
java8中hashmap的put方法(面试必问)
java8中hashmap改为红黑树加链表的结构存储数据,当链表的长度大于8的时候将链表转为红黑树
扩容进行了优化,不用重新计算hash值,用原hash值与新的table长度n-1进行位与运算,得出hash。如两个hash值A:11010、B:01010,当数组长度为10000时,他们都在1010桶,当table长度扩容到100000时,A的hash与table长度n-1位与得到11010,B还是01010。也就是说原hash值得上一位是1计算出来的位与结果就是之前的结果就是原结果加原数组长度,如果是0位与结果不变,还在原位置。
扩容方式进行了修改,解决了java7并发扩容导致链表闭环的问题,java7扩容后链表内容会倒置,java8不会
-
ConcurrentHashmap实现原理
java7中使用segment分段锁进行同步,相当于在hashmap结构上面增加了一个segment数组
java8中使用cas+sychronized进行同步,同时结构改为:数组+红黑树+链表 -
java7中并发操作hashmap的隐患
多线程扩容,主要的问题在于基于头插法的数据迁移,会有几率造成链表倒置,从而引发链表闭链,导致程序死循环,并吃满CPU
-
java8中Arraylist、hashmap的初始长度、扩容条件、扩容大小
arraylist在jdk1.8中进行了优化,默认为0,初次添加元素时扩容为10,为的是避免无用内存占用
hashmap默认容量大小为16,负载因子为0.75,扩容为*2 -
java7中加入的Files常用方法
-
java8中的Stream
-
stream需不需要反序列化
-
String为什么设置成final
这个最简单地原因,就是为了安全。
new HashSet();通过修改StringBuilder的value可以破坏HashSet键值的唯一性。所以千万不要用可变类型做HashMap和HashSet键值。
并发情况下,线程安全
使用字符串常量池可以节省内存空间,提高效率。 -
Interceptor与filter的区别
拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
JVM
-
jvm加载顺序
-
GC调优
-
JVM内存结构,堆结构
-
垃圾回收算法
-
两个线程使用同一个栈
多线程与并发
-
AQS(AbstractQueuedSynchronizer)
-
乐观锁与悲观锁
-
公平锁与非公平锁
公平锁:多个线程按照申请锁的顺序去获得锁,线程会直接进入队列去排队,永远都是队列的第一位才能得到锁。
优点:所有的线程都能得到资源,不会饿死在队列中。
缺点:吞吐量会下降很多,队列里面除了第一个线程,其他的线程都会阻塞,cpu唤醒阻塞线程的开销会很大。非公平锁:多个线程去获取锁的时候,会直接去尝试获取,获取不到,再去进入等待队列,如果能获取到,就直接获取到锁。
优点:可以减少CPU唤醒线程的开销,整体的吞吐效率会高点,CPU也不必取唤醒所有线程,会减少唤起线程的数量。
缺点:你们可能也发现了,这样可能导致队列中间的线程一直获取不到锁或者长时间获取不到锁,导致饿死。ReentrantLock默认非公平,构造参数设置为true为公平锁
-
AQS独占锁模式
-
AQS共享锁模式
-
自旋锁
-
双重检查锁
-
ReentrantReadWriteLock 原理
-
LockSupport.park说明
-
LockSupport.park与其他阻塞方式的区别
-
fork/join
-
线程池
-
Callable与Future
-
线程的生命周期
-
多线程顺序执行的实现
在子线程中通过join()方法指定顺序
在主线程中通过join()方法指定顺序
通过倒数计时器CountDownLatch实现
通过创建单一化线程池newSingleThreadExecutor()实现
使用CompletableFuture -
在静态方法和非静态方法上加 Synchronized的区别
-
阻塞队列
-
CountDownLatch应用
数据库
-
Innodb与myiSAM的区别
- InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
- InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
- InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。
- InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);
- Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;PS:5.7以后的InnoDB支持全文索引了
- MyISAM表格可以被压缩后进行查询操作
- InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁
- InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键),而Myisam可以没有
- Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI
-
Mysql的优化
- sql优化
- Mysql优化器
Explain语法:explain select … from … [where …]
- Mysql优化器
- 添加索引
- 分库分表
- 主从读写分离
- sql优化
-
Mysql主从、主备策略
-
binlog
-
Mysql分库分表
-
Mysql都有哪些索引
FULLTEXT
即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。
HASH
由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。
HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。
BTREE
BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。 -
Mysql不适用索引的情况(全表扫描)
1 如果MySQL估计使用索引比全表扫描更慢,则不使用索引。例如,如果列key均匀分布在1和100之间,下面的查询使用索引就不是很好:select * from table_name where key>1 and key<90;
2,用or分隔开的条件,如果or前的条件中的列有索引,而后面的列没有索引,那么涉及到的索引都不会被用到,例如:select * from table_name where key1=‘a’ or key2=‘b’;如果在key1上有索引而在key2上没有索引,则该查询也不会走索引
3,复合索引,如果索引列不是复合索引的第一部分,则不使用索引(即不符合最左前缀),例如,复合索引为(key1,key2),则查询select * from table_name where key2=‘b’;将不会使用索引
4,如果like是以‘%’开始的,则该列上的索引不会被使用。例如select * from table_name where key1 like ‘%a’;该查询即使key1上存在索引,也不会被使用
5,如果列为字符串,则where条件中必须将字符常量值加引号,否则即使该列上存在索引,也不会被使用。例如,select * from table_name where key1=1;如果key1列保存的是字符串,即使key1上有索引,也不会被使用。
6,WHERE字句的查询条件里有不等于号(WHERE column!=…),或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
7 where 子句中对字段进行 null 值判断 where mobile = null 此查询 不会走索引
8,in 和 not in 也要慎用,否则会导致全表扫描
9,不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。 -
数据库隔离级别
-
MySQL默认隔离级别为什么是Repeatable Read
-
MySQL排它锁与共享锁
- 共享锁: 又称为读锁,简称S锁,共享锁就是允许多个线程同时获取一个锁,一个锁可以同时被多个线程拥有,但是只能读不能修改。加共享锁可以使用select … lock in share
- 排他锁(eXclude Lock): 又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。加排他锁可以使用select …for update语句
mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型。所以加了排它锁的结果可以被再次查询,但是使用读锁时会阻塞。
-
MySQL中DATATIME与TIMESTAMP的区别
-
MySQL中Varchar与char的区别
-
Union与Unin all的区别
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;默认是根据主键升序排序
Union All:对两个结果集进行并集操作,包括重复行,不进行排序; -
为保证关系型数据库的性能,需要在数据库结构设计时考虑哪些因素
Spring全家桶
-
Spring事务传播行为
-
SpringAOP的实现
-
Spring三级缓存与循环依赖
-
SpringIOC的理解
-
SpringBean加载顺序
-
SpringBoot启动流程
-
SpringBoot的Starter手写需要注意什么
-
SpringBoot启动Tomcat原理
-
SpringBoot Bean加载优先级
微服务与分布式架构
-
Springcloud 主要组件
-
微服务架构的特点和适用场景
-
服务限流
-
ACID
-
Base理论
-
Ribbon怎么实现的负载均衡
-
Nacos配置热启动怎么实现的
-
Zuul、Feign、Ribbon、Hystrix超时时间
-
Redisson、zookeeper、redlock分布式锁的区别
-
强一致性、弱一致性、最终一致性
-
Euraka、Zookeeper、Nacos的区别(未整理完成)
CAP理论
CAP理论是分布式架构中重要理论
一致性(Consistency) (所有节点在同一时间具有相同的数据)
可用性(Availability) (保证每个请求不管成功或者失败都有响应)
分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
如果C是第一需求的话,那么会影响A的性能,因为要数据同步,不然请求结果会有差异,但是数据同步会消耗时间,期间可用性就会降低。
如果A是第一需求,那么只要有一个服务在,就能正常接受请求,但是对与返回结果变不能保证,原因是,在分布式部署的时候,数据一致的过程不可能想切线路那么快。
再如果,同事满足一致性和可用性,那么分区容错就很难保证了,也就是单点,也是分布式的基本核心,好了,明白这些理论,就可以在相应的场景选取服务注册与发现了Eureka Server 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka Client 在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其它节点。只要有一台 Eureka Server 还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。
zookeeper有个节点过半即可用原则,所以设置为奇数个节点能节省资源
-
Ribbon与Nginx的区别
-
eureka原理
-
链路
设计模式
Redis与缓存
-
缓存雪崩
1、在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
2、对于“Redis挂掉了,请求全部走数据库”这种情况,我们可以有以下的思路:
事发前:实现Redis的高可用(主从架构+Sentinel(哨兵) 或者Redis Cluster(集群)),尽量避免Redis挂掉这种情况发生。
事发中:万一Redis真的挂了,我们可以设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)
事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。 -
缓存击穿
1、由于请求的参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器(BloomFilter)或者压缩filter提前拦截,不合法就不让这个请求到数据库层!
2、当我们从数据库找不到的时候,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。
这种情况我们一般会将空对象设置一个较短的过期时间。 -
缓存同步
无论是双写模式还是失效模式,都会导致缓存的不一致问题。即多个实例同时更新会出事。怎么办?
- 上删除模式,先删除,稍后再删除一次
- 如果是用户纬度数据(订单数据、用户数据),这种并发几率非常小,不用考虑这个问题,缓存数据加 上过期时间,每隔一段时间触发读的主动更新即可
- 如果是菜单,商品介绍等基础数据,也可以去使用canal订阅binlog的方式(比较优秀)。
- 缓存数据+过期时间也足够解决大部分业务对于缓存的要求。
- 通过加锁保证并发读写,写写的时候按顺序排好队。读读无所谓。所以适合使用读写锁。(业务不关心 脏数据,允许临时脏数据可忽略);
总结:
我们能放入缓存的数据本就不应该是实时性、一致性要求超高的。所以缓存数据的时候加上过期时间,保 证每天拿到当前最新数据即可。
我们不应该过度设计,增加系统的复杂性 。
遇到实时性、一致性要求高的数据,就应该查数据库,即使慢点。 -
Redis限流
-
Redis集群
-
Redis事务
-
Redis分布式锁
-
Redis基础类型