知识点总结
InnoDB的行锁
(1)共享锁(S):用法lock in share mode,又称读锁,容许一个事务去读一行,阻止其余事务取得雷同数据集的排他锁。若事务T对数据对象A加上S锁,则事务T能够读A但不能批改A,其余事务只能再对A加S锁,而不能加X锁,直到T开释A上的S锁。这保障了其余事务能够读A,但在T开释A上的S锁之前不能对A做任何批改。 (2)排他锁(X):用法for update,又称写锁,容许获取排他锁的事务更新数据,阻止其余事务获得雷同的数据集共享读锁和排他写锁。若事务T对数据对象A加上X锁,事务T能够读A也能够批改A,其余事务不能再对A加任何锁,直到T开释A上的锁。在没有索引的状况下,InnoDB只能应用表锁
Spring的事务流传级别
(1)REQUIRED(默认):反对应用以后事务,如果以后事务不存在,创立一个新事务。 (2)SUPPORTS:反对应用以后事务,如果以后事务不存在,则不应用事务。 (3)MANDATORY:强制,反对应用以后事务,如果以后事务不存在,则抛出Exception。 (4)REQUIRES_NEW:创立一个新事务,如果以后事务存在,把以后事务挂起。 (5)NOT_SUPPORTED:无事务执行,如果以后事务存在,把以后事务挂起。 (6)NEVER:无事务执行,如果以后有事务则抛出Exception。 (7)NESTED:嵌套事务,如果以后事务存在,那么在嵌套的事务中执行。如果以后事务不存在,则体现跟REQUIRED一样。
- Redis与Mysql双写一致性计划
先更新数据库,再删缓存。数据库的读操作的速度远快于写操作的,所以脏数据很难呈现。能够对异步延时删除策略,保障读申请实现当前,再进行删除操作
- 索引B+树的叶子节点都能够存哪些货色?
可能存储的是整行数据,也有可能是主键的值。B+树的叶子节点存储了整行数据的是主键索引,也被称之为聚簇索引。而索引B+ Tree的叶子节点存储了主键的值的是非主键索引,也被称之为非聚簇索引
- 分代回收
(1)HotSpot JVM把年老代分为了三局部:1个Eden区和2个Survivor区(别离叫from和to)。个别状况下,新创建的对象都会被调配到Eden区(一些大对象非凡解决),这些对象通过第一次Minor GC后,如果依然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会减少1岁,当它的年龄减少到肯定水平时,就会被挪动到年轻代中。 (2)因为年老代中的对象根本都是朝生夕死的,所以在年老代的垃圾回收算法应用的是复制算法,复制算法的根本思维就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块下面。复制算法不会产生内存碎片。 (3)在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。紧接着进行GC,Eden区中所有存活的对象都会被复制到“To”,而在“From”区中,仍存活的对象会依据他们的年龄值来决定去向。年龄达到肯定值(年龄阈值,能够通过-XX:MaxTenuringThreshold来设置)的对象会被挪动到年轻代中,没有达到阈值的对象会被复制到“To”区域。通过这次GC后,Eden区和From区曾经被清空。这个时候,“From”和“To”会替换他们的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎样,都会保障名为To的Survivor区域是空的。Minor GC会始终反复这样的过程,直到“To”区被填满,“To”区被填满之后,会将所有对象挪动到年轻代中。
- 线程之间如何通信?
(1)利用最根本的synchronized (2)利用synchronized、notify、wait (3)while轮询的形式 (4)利用Lock和Condition (5)利用volatile (6)利用AtomicInteger (7)利用CyclicBarrier (8)利用PipedInputStream (9)利用BlockingQueue
- redis并发竞争key的解决方案
(1)分布式锁+工夫戳 (2)利用音讯队列
- 如何防止(预防)死锁?
毁坏“申请和放弃”条件:让过程在申请资源时,一次性申请所有须要用到的资源,不要一次一次来申请,当申请的资源有一些没空,那就让线程期待。不过这个办法比拟浪费资源,过程可能常常处于饥饿状态。还有一种办法是,要求过程在申请资源前,要开释本人领有的资源。 毁坏“不可抢占”条件:容许过程进行抢占,办法一:如果去抢资源,被回绝,就开释本人的资源。办法二:操作系统容许抢,只有你优先级大,能够抢到。 毁坏“循环期待”条件:将零碎中的所有资源对立编号,过程可在任何时刻提出资源申请,但所有申请必须依照资源的编号程序提出(指定获取锁的程序,程序加锁)
- 高并发零碎的设计与实现
在开发高并发零碎时有三把利器用来爱护零碎:缓存、降级和限流。 (1)缓存:缓存比拟好了解,在大型高并发零碎中,如果没有缓存数据库将分分钟被爆,零碎也会霎时瘫痪。应用缓存不单单可能晋升零碎访问速度、进步并发访问量,也是爱护数据库、爱护零碎的无效形式。大型网站个别次要是“读”,缓存的应用很容易被想到。在大型“写”零碎中,缓存也经常扮演者十分重要的角色。比方累积一些数据批量写入,内存外面的缓存队列(生产生产),以及HBase写数据的机制等等也都是通过缓存晋升零碎的吞吐量或者实现零碎的保护措施。甚至消息中间件,你也能够认为是一种分布式的数据缓存。 (2)降级:服务降级是当服务器压力剧增的状况下,依据以后业务状况及流量对一些服务和页面有策略的降级,以此开释服务器资源以保障外围工作的失常运行。降级往往会指定不同的级别,面临不同的异样等级执行不同的解决。依据服务形式:能够拒接服务,能够提早服务,也有时候能够随机服务。依据服务范畴:能够砍掉某个性能,也能够砍掉某些模块。总之服务降级须要依据不同的业务需要采纳不同的降级策略。次要的目标就是服务尽管有损然而总比没有好。 (3)限流:限流能够认为服务降级的一种,限流就是限度零碎的输出和输入流量已达到爱护零碎的目标。一般来说零碎的吞吐量是能够被测算的,为了保证系统的稳固运行,一旦达到的须要限度的阈值,就须要限度流量并采取一些措施以实现限度流量的目标。比方:提早解决,回绝解决,或者局部回绝解决等等。
- 高并发零碎的限流如何实现?
常见的限流算法有计数器、漏桶和令牌桶算法。漏桶算法在分布式环境中消息中间件或者Redis都是可选的计划。发放令牌的频率减少能够晋升整体数据处理的速度,而通过每次获取令牌的个数减少或者加快令牌的发放速度和升高整体数据处理速度。而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的。
JVM有哪些回收算法
1)援用计数法 (2)复制算法 (3)标记-革除算法 (4)标记-整顿算法 (5)分代收集算法
- 垃圾收集器有哪些?
(1)Serial收集器 (2)ParNew 收集器 (3)Parallel Scavenge 收集器 (4)Serial Old收集器 (5)Parallel Old收集器 (6)CMS收集器 (7)G1收集器 (8)ZGC
- 常见的分布式事务计划有哪些?
(1)两阶段提交计划 (2)eBay 事件队列计划 (3)TCC 弥补模式 (4)缓存数据最终一致性
- 运行时数据区域(内存模型)
(1)程序计数器:程序计数器是一块较小的内存空间,它能够看作是以后线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过扭转这个计数器的值来选取下一条须要执行的字节码指令,分支、循环、跳转、异样解决、线程复原等根底性能都须要依赖这个计数器来实现。是线程公有”的内存。 (2)Java虚拟机栈:与程序计数器一样,Java虚拟机栈(Java Virtual Machine Stacks)也是线程公有的,它的生命周期与线程雷同。虚拟机栈形容的是Java办法执行的内存模型:每个办法在执行的同时都会创立一个栈帧 ,用于存储局部变量表、操作数栈、动静链接、办法进口等信息。每一个办法从调用直至执行实现的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 (3)本地办法栈:本地办法栈(Native Method Stack)与虚拟机栈所施展的作用是十分类似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java办法(也就是字节码)服务,而本地办法栈则为虚拟机应用到的Native办法服务。 (4)Java堆:对于大多数利用来说,Java堆是Java虚拟机所治理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创立。此内存区域的惟一目标就是寄存对象实例,简直所有的对象实例都在这里分配内存。 (5)办法区(1.8叫元数据):办法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、动态变量、即时编译器编译后的代码等数据。
- CAS操作ABA问题
如果在这段期间它的值已经被改成了B,起初又被改回为A,那CAS操作就会误认为它素来没有被扭转过。Java并发包为了解决这个问题,提供了一个带有标记的原子援用类“AtomicStampedReference”,它能够通过管制变量值的版本来保障CAS的正确性
- 为什么抉择B+树作为索引构造?
(1)Hash索引:Hash索引底层是哈希表,哈希表是一种以key-value存储数据的构造,所以多个数据在存储关系上是齐全没有任何程序关系的,所以,对于区间查问是无奈间接通过索引查问的,就须要全表扫描。所以,哈希索引只实用于等值查问的场景。而B+ 树是一种多路均衡查问树,所以他的节点是人造有序的(左子节点小于父节点、父节点小于右子节点),所以对于范畴查问的时候不须要做全表扫描 (2)二叉查找树:解决了排序的根本问题,然而因为无奈保障均衡,可能进化为链表。 (3)均衡二叉树:通过旋转解决了均衡的问题,然而旋转操作效率太低。 (4)红黑树:通过舍弃严格的均衡和引入红黑节点,解决了 AVL旋转效率过低的问题,然而在磁盘等场景下,树依然太高,IO次数太多。 (5)B+树:在B树的根底上,将非叶节点革新为不存储数据纯索引节点,进一步升高了树的高度;此外将叶节点应用指针连接成链表,范畴查问更加高效。
- 脏读和幻读是什么?
(1)脏读是指当一个事务正在拜访数据,并且对数据进行了批改。而这种批改还没有提交到数据库中,这时,另外一个事务也拜访了这个数据,而后应用了这个数据。 (2)幻读是指当事务不是独立执行时产生的一种景象,例如第一个事务对一个表中的数据进行了批改,这种批改波及到了表中的全副数据行。同时,第二个事务也批改了这个表中的数据,这种批改是向表中插入一行新数据。那么,当前就会产生操作第一个事务的用户发现表中还有没有批改的数据行,就如同产生了幻觉一样。
- 如何解决Redis缓存雪崩,缓存穿透问题?
缓存雪崩: (1)应用 Redis 高可用架构:应用 Redis 集群来保障 Redis 服务不会挂掉 (2)缓存工夫不统一,给缓存的生效工夫,加上一个随机值,防止个体生效 (3)限流降级策略:有肯定的备案,比方共性举荐服务不可用了,换成热点数据举荐服务 缓存穿透: (1)在接口做校验 (2)存null值(缓存击穿加锁) (3)布隆过滤器拦挡: 将所有可能的查问key 先映射到布隆过滤器中,查问时先判断key是否存在布隆过滤器中,存在才持续向下执行,如果不存在,则间接返回。 布隆过滤器将值进行屡次哈希bit存储,布隆过滤器说某个元素在,可能会被误判。布隆过滤器说某个元素不在,那么肯定不在。
- Redis的长久化机制
redis为了保障效率,数据缓存在了内存中,然而会周期性的把更新的数据写入磁盘或者把批改操作写入追加的记录文件中,以保证数据的长久化。 Redis的长久化策略有两种: (1)RDB:快照模式是间接把内存中的数据保留到一个dump的文件中,定时保留,保留策略。 当Redis须要做长久化时,Redis会fork一个子过程,子过程将数据写到磁盘上一个长期RDB文件中。当子过程实现写临时文件后,将原来的RDB替换掉。 (2)AOF:把所有的对Redis的服务器进行批改的命令都存到一个文件里,命令的汇合。 应用AOF做长久化,每一个写命令都通过write函数追加到appendonly.aof中。aof的默认策略是每秒钟fsync一次,在这种配置下,就算产生故障停机,也最多失落一秒钟的数据。 毛病是对于雷同的数据集来说,AOF的文件体积通常要大于RDB文件的体积。依据所应用的fsync策略,AOF的速度可能会慢于RDB。 Redis默认是快照RDB的长久化形式。
- 三次握手
(1)第一次握手:建设连贯时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,期待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。 (2)第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时本人也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态; (3)第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送结束,客户端和服务器进入ESTABLISHED(TCP连贯胜利)状态,实现三次握手。
- Kafka音讯是采纳Pull模式,还是Push模式?
Kafka最后思考的问题是,customer应该从brokes拉取音讯还是brokers将音讯推送到consumer,也就是pull还push。在这方面,Kafka遵循了一种大部分音讯零碎独特的传统的设计:producer将音讯推送到broker,consumer从broker拉取音讯。push模式下,当broker推送的速率远大于consumer生产的速率时,consumer恐怕就要解体了。最终Kafka还是选取了传统的pull模式。Pull模式的另外一个益处是consumer能够自主决定是否批量的从broker拉取数据。Pull有个毛病是,如果broker没有可供生产的音讯,将导致consumer一直在循环中轮询,直到新音讯达到。为了防止这点,Kafka有个参数能够让consumer阻塞晓得新音讯达到。
- HashMap相干
(1)在jdk1.8之后,HashMap除了数组+链表之外,援用了红黑树。须要阐明对于援用了红黑树的 HashMap 如何put一个元素,以及链表是在何时转化为红黑树的。比方,首先须要晓得这个元素落在哪一个数组里,获取hashcode后并不是对数组长度取余来确定的,而是高下位异或求与来失去的。这个中央首先得晓得异或求与是做什么样的运算的。 (2)之后说一下在HashMap中的实现,比方hashcode无符号右移16位后和原hashcode做异或运算,这相当于把hashcode的高16位拿过去和hashcode的低16位做异或运算,因为无符号右移后后面说的16位都补零,这就是后面说的 "高下位异或“,进而是“求与”,和谁求与呢,和数组长度减1 求与。说到这里起码可能证实你是看过源码的,接下来说说你的思考,比方咱们晓得对于hashmap 初始化容量决定了数组大小,个别咱们对于数组这个初始容量的设置是有法则的,它应该是 2^n 。这个初始容量的设置影响了HashMap的效率,那又波及到影响HashMap效率的次要因素,比方初始容量和负载因子。
- 手写一个基于懒汉式的双重检测的单例。
(1)单例有三个比拟要害的点,一是公有构造方法,防止内部new出对象;二是保障唯一性;三是提供一个全局拜访点。 (2)另外,懒汉式双重检测的实现形式 有三点须要留神的中央,一是全局拜访点必须是动态的,外界应用能够通过类间接调用,二是在进入锁之后还须要校验,三是保留单例对象的公有变量肯定要用volatile润饰,这个中央能够多说一些,比方volatile避免指令重排序,保障内存可见性(JVM层面和CPU层面能够别离说)。
- RPC原理
(1)为什么会呈现RPC? RPC(Remote Procedure Call Protocol)——近程过程调用协定。 一般来说,本人写程序而后本地调用,这种程序的特点是服务的生产方和提供方。当咱们进入公司时,面对的很可能就是成千上万的服务提供方,这时候就须要应用RPC来进行近程服务调用。RPC将原来的本地调用转变为调用远端的服务器上的办法,给零碎的解决能力和吞吐量带来了近似于无限度晋升的可能。 (2)RPC的组成 ①客户端:服务的调用方 ②客户端存根:寄存服务端的地址音讯,再将客户端的申请参数打包成网络音讯,③而后通过网络近程发送给服务方。 ④服务端:真正的服务提供者。 ⑤服务端存根:接管客户端发送过去的音讯,将音讯解包,并调用本地的办法。
- Redis缓存回收机制
(1)数据过期: ①定时删除策略:Redis启动一个定时器监控所有的key,一旦有过期的话就进行删除(遍历所有key,十分消耗CPU) ②惰性删除策略:获取key的时候判断是否过期, 过期则进行删除 Redis采纳的形式:①(随机抓取一部分key进行检测)+② (2)内存淘汰: ①noeviction:当内存不足以包容新写入数据时,新写入操作会报错。(Redis 默认策略) ②allkeys-lru:当内存不足以包容新写入数据时,在键空间中,移除最近起码应用的 Key。(LRU举荐应用) ③allkeys-random:当内存不足以包容新写入数据时,在键空间中,随机移除某个 Key。 ④volatile-lru:当内存不足以包容新写入数据时,在设置了过期工夫的键空间中,移除最近起码应用的 Key。这种状况个别是把 Redis 既当缓存,又做长久化存储的时候才用。 ⑤volatile-random:当内存不足以包容新写入数据时,在设置了过期工夫的键空间中,随机移除某个 Key。 ⑥volatile-ttl:当内存不足以包容新写入数据时,在设置了过期工夫的键空间中,有更早过期工夫的 Key 优先移除。不举荐。如果没有对应的键,则回退到noeviction策略。
- Redis主从同步
(1)主从复制作用 ①数据冗余 ②故障复原(服务冗余) ③负载平衡 ④读写拆散(主节点写操作、从节点读操作) (2)主从复制过程 ①连贯建设阶段 步骤1:保留主节点信息 步骤2:建设socket连贯 步骤3:发送ping命令 步骤4:身份验证 步骤5:发送从节点端口信息 ②数据同步阶段 从节点向主节点发送psync命令 依据主从节点以后状态的不同,能够分为全量复制和局部复制 ③命令流传阶段 主从节点进入命令流传阶段;在这个阶段主节点将本人执行的写命令发送给从节点,从节点接管命令并执行,从而保障主从节点数据的一致性。 (3)介绍全量复制和局部复制 ①全量复制:用于首次复制或其余无奈进行局部复制的状况,将主节点中的所有数据都发送给从节点,是一个十分重型的操作。 ②局部复制:用于网络中断等状况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。须要留神的是,如果网络中断工夫过长,导致主节点没有可能残缺地保留中断期间执行的写命令,则无奈进行局部复制,仍应用全量复制。 (4)主从复制毛病:故障复原无奈自动化;写操作无奈负载平衡;存储能力受到单机的限度。
- 为什么会有哨兵机制?
在主从复制的根底上,哨兵实现了自动化的故障复原。
- 哨兵机制作用?
(1)监控(Monitoring):哨兵会一直地查看主节点和从节点是否运作失常。 (2)主动故障转移(Automatic failover):当主节点不能失常工作时,哨兵会开始主动故障转移操作,它会将生效主节点的其中一个从节点降级为新的主节点,并让其余从节点改为复制新的主节点。 (3)配置提供者(Configuration provider):客户端在初始化时,通过连贯哨兵来取得以后Redis服务的主节点地址。 (4)告诉(Notification):哨兵能够将故障转移的后果发送给客户端。
- 哨兵机制节点组成?
它由两局部组成,哨兵节点和数据节点: (1)哨兵节点:哨兵零碎由一个或多个哨兵节点组成,哨兵节点是非凡的redis节点,不存储数据。 (2)数据节点:主节点和从节点都是数据节点。
- 哨兵机制原理?
(1)定时工作:每个哨兵节点保护了3个定时工作。定时工作的性能别离如下:通过向主从节点发送info命令获取最新的主从构造;通过公布订阅性能获取其余哨兵节点的信息;通过向其余节点发送ping命令进行心跳检测,判断是否下线。 (2)主观下线:在心跳检测的定时工作中,如果其余节点超过肯定工夫没有回复,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主观下线绝对应的是主观下线。 (3)主观下线:哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其余哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到肯定数值,则对该主节点进行主观下线。 (4)选举领导者哨兵节点:当主节点被判断主观下线当前,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。监督该主节点的所有哨兵都有可能被选为领导者,选举应用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有批准过其余哨兵,则会批准A成为领导者。选举的具体过程这里不做详细描述,一般来说,哨兵抉择的过程很快,谁先实现主观下线,个别就能成为领导者。 (5)故障转移:选举出的领导者哨兵,开始进行故障转移操作,该操作大体能够分为3个步骤: ①在从节点中抉择新的主节点:抉择的准则是,首先过滤掉不衰弱的从节点;而后抉择优先级最高的从节点(由slave-priority指定);如果优先级无奈辨别,则抉择复制偏移量最大的从节点;如果仍无奈辨别,则抉择runid最小的从节点。 ②更新主从状态:通过slaveof no one命令,让选出来的从节点成为主节点;并通过slaveof命令让其余节点成为其从节点。 ③将曾经下线的主节点(即6379)设置为新的主节点的从节点,当6379从新上线后,它会成为新的主节点的从节点。
- 哨兵机制毛病
写操作无奈负载平衡;存储能力受到单机的限度。(Redis集群解决了该状况)
- Zookeeper锁是如何实现的?
个别应用Curator进行应用Zookeeper锁,例如有两个客户端A和客户端B,首先A先在锁节点下创立例如01子节点的锁,而后再获取节点信息,发现自己的01节点排名第一,那么就取得锁。 客户端B也须要获取锁,当初锁节点下创立例如02的子节点,而后再获取锁节点信息,发现锁节点信息为[01,02],并不排第一,因而获取不到锁,客户端B会在他的程序节点的上一个程序节点加一个监听器。 当客户端A应用完锁,删除01节点,客户端B获取到01删除的监听,而后发现自己的02节点排名第一,那么就获取到锁。
- JVM内存模型
(1)程序计数器:线程公有,用来程序跳转,流程管制 (2)办法区(1.8叫元数据区):线程共享,用于存储类信息、常量、动态变量等信息 (3)Java虚拟机栈:线程公有,用于办法调用Java 虚拟机栈会呈现两种谬误:StackOverFlowError 和 OutOfMemoryError (4)堆:线程公有,次要的内存区域,存储对象实例,垃圾回收次要针对这一块。 (5)本地办法栈:线程共享,本地办法被执行的时候,在本地办法栈也会创立一个栈帧,用于寄存该本地办法的局部变量表、操作数栈、动静链接、进口信息。
- G1和CMS垃圾回收器
G1和CMS垃圾回收器 (1)CMS收集器:是一种以获取最短回收进展工夫为指标的收集器。 过程: ①初始标记:标记GC Roots能间接关联到的对象,须要在safepoint地位暂停所有执行线程。---->STW ②并发标记:进行GC Roots Tracing,遍历完从root可达的所有对象。该阶段与工作线程并发执行。 ③从新标记:修改并发标记期间因用户程序持续运作而导致标记产生表动的那一部分对象的标记记录。须要在safepoint地位暂停所有执行线程。--->STW ④并发革除: 开启用户线程,同时 GC 线程开始对为标记的区域做打扫。 长处:并发收集、低进展。 毛病: ①CMS收集器对CPU资源十分敏感。 ②CMS收集器无奈解决浮动垃圾(Floating Garbage)。 ③CMS收集器是基于标记-革除算法,该算法毛病都有:标记和革除效率低/产生大量不间断的内存碎片。 ④进展工夫是不可预期的。 (2)G1收集器:从新定义了堆空间,突破了原有的分代模型,将堆划分为一个个区域。这么做的目标是在进行收集时不用在全堆范畴内进行,这是它最显著的特点。 过程: ①初始标记:标记GC Roots 能够间接关联的对象,该阶段须要线程进展然而耗时短。---->STW ②并发标记:寻找存活的对象,能够与其余程序并发执行,耗时较长。 ③最终标记:并发标记期间用户程序会导致标记记录产生变动(好比一个阿姨一边清理垃圾,另一个人一边扔垃圾)虚构机会将这段时间的变动记录在Remembered Set Logs 中。最终标记阶段会向Remembered Set合并并发标记阶段的变动。这个阶段须要线程进展,也能够并发执行---->STW ④筛选回收:对每个Region的回收老本进行排序,依照用户自定义的回收工夫来制订回收打算 长处: ①空间整合:G1应用Region独立区域概念,G1利用的是标记复制法,不会产生垃圾碎片 ②分代收集:G1能够本人治理新生代和老年代 ③并行于并发:G1能够通过机器的多核来并发解决 STW进展,缩小进展工夫,并且可不进展java线程执行GC动作,可通过并发形式让GC和java程序同时执行。 ④可预测进展:G1除了谋求进展工夫,还建设了可预测进展工夫模型,能让制订的M毫秒工夫片段内,耗费在垃圾回收器上的工夫不超过N毫秒 毛病: G1 须要记忆集 (具体来说是卡表)来记录新生代和老年代之间的援用关系,这种数据结构在 G1 中须要占用大量的内存,可能达到整个堆内存容量的 20% 甚至更多。而且 G1 中保护记忆集的老本较高,带来了更高的执行负载,影响效率。
- wait/await和sleep区别
(1)两者最次要的区别在于:sleep 办法没有开释锁,而 wait 办法开释了锁 。 (2)两者都能够暂停线程的执行。 (3)wait 通常被用于线程间交互/通信,sleep 通常被用于暂停执行。 (4)wait() 办法被调用后,线程不会主动昏迷,须要别的线程调用同一个对象上的 notify() 或者 notifyAll() 办法。sleep() 办法执行实现后,线程会主动昏迷。或者能够应用 wait(long timeout)超时后线程会主动昏迷。
- Redis的LRU过期策略的具体实现 Redis的LRU具体实现
用栈的模式会导致执行select *的时候大量非热点数据霸占头部数据,所以须要改良。 Redis每次按key获取一个值的时候,都会更新value中的lru字段为以后秒级别的工夫戳。Redis初始的实现算法很简略,随机从dict中取出五个key,淘汰一个lru字段值最小的。 在3.0的时候,又改良了一版算法,首先第一次随机选取的key都会放入一个pool中(pool的大小为16),pool中的key是按lru大小顺序排列的。接下来每次随机选取的keylru值必须小于pool中最小的lru才会持续放入,直到将pool放满。放满之后,每次如果有新的key须要放入,须要将pool中lru最大的一个key取出。淘汰的时候,间接从pool中选取一个lru最小的值而后将其淘汰。
- 哪些对象能够作为GC Roots?
(1)虚拟机栈(栈帧中的本地变量表)中援用的对象。 (2)办法区中类动态属性援用的对象。 (3)办法区中常量援用的对象。 (4)本地办法栈中JNI(即个别说的Native办法)援用的对象。
- ConcurrentHashMap的数据结构
在JDK1.7版本中,ConcurrentHashMap保护了一个Segment数组,Segment这个类继承了重入锁ReentrantLock,并且该类外面保护了一个 HashEntry<K,V>[] table数组,在写操作put,remove,扩容的时候,会对Segment加锁,所以仅仅影响这个Segment,不同的Segment还是能够并发的,所以解决了线程的平安问题,同时又采纳了分段锁也晋升了并发的效率。在JDK1.8版本中,ConcurrentHashMap摒弃了Segment的概念,而是间接用Node数组+链表+红黑树的数据结构来实现,并发管制应用Synchronized和CAS来操作,整个看起来就像是优化过且线程平安的HashMap。
- tcp和udp的长处与毛病
(1)TCP的长处: 牢靠,稳固 TCP的牢靠体现在TCP在传递数据之前,会有三次握手来建设连贯,而且在数据传递时,有确认、窗口、重传、拥塞管制机制,在数据传完后,还会断开连接用来节约系统资源。 (2)TCP的毛病: 慢,效率低,占用系统资源高,易被攻打 TCP在传递数据之前,要先建连贯,这会耗费工夫,而且在数据传递时,确认机制、重传机制、拥塞管制机制等都会耗费大量的工夫,而且要在每台设施上保护所有的传输连贯,事实上,每个连贯都会占用零碎的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻打。 (3)UDP的长处: 快,比TCP稍平安 UDP没有TCP的握手、确认、窗口、重传、拥塞管制等机制,UDP是一个无状态的传输协定,所以它在传递数据时十分快。没有TCP的这些机制,UDP较TCP被攻击者利用的破绽就要少一些。但UDP也是无奈防止攻打的,比方:UDP Flood攻打…… (4)UDP的毛病: 不牢靠,不稳固 因为UDP没有TCP那些牢靠的机制,在数据传递时,如果网络品质不好,就会很容易丢包。 基于下面的优缺点,那么: 什么时候应该应用TCP: 当对网络通讯品质有要求的时候,比方:整个数据要准确无误的传递给对方,这往往用于一些要求牢靠的利用,比方HTTP、HTTPS、FTP等传输文件的协定,POP、SMTP等邮件传输的协定。 在日常生活中,常见应用TCP协定的利用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、SSH QQ文件传输。什么时候应该应用UDP: 当对网络通讯品质要求不高的时候,要求网络通讯速度能尽量的快,这时就能够应用UDP。 比方,日常生活中,常见应用UDP协定的利用如下: QQ语音 QQ视频 TFTP。
- HashMap原理
(1)hashMap 是非线程平安的, hashMap 1.7的底层实现为数组(table[])+链表(LinkList-->Entry),hashmap 1.8底层为数组+链表/红黑树(当链表长度达到阈值TREEIFY_THRESHOLD(默认为8)时,会转化为红黑树)
- HashMap的put和resize的过程
(1)put过程: ①查看数组是否须要初始化 ②依据key计算hashcode ③依据hashcode计算出桶地位 ④遍历链表,查看key值与链表节点的key值是否相等,如果相等的话,那么进行笼罩旧值,并返回旧值。1.8的话须要先查看链表长度是否达到阈值,如果达到阈值,先进行红黑树转化而后再进行查看扩容。 ⑤新增的时候须要查看是否须要扩容,须要扩容的话进行两倍扩容,扩容实现后进行插入新值。 (2)resize过程: resize扩容须要从四个方面来进行答复: ①什么时候触发resize? 当容量超过以后容量(默认容量16)乘以负载因子(默认0.75)就会进行扩容,扩容大小为以后大小的两倍(扩大问题,为啥是两倍:通过限度length是一个2的幂数,h & (length-1)和h % length后果是统一的)。 ②resize是如何hash的:h & (length-1) ③resize是如何进行链表操作的:应用头插法进行数据插入,每次新put的值放在头部 ④并发操作下,链表是如何成环的:HashMap的环:若以后线程此时取得ertry节点,然而被线程中断无奈继续执行,此时线程二进入transfer函数,并把函数顺利执行,此时新表中的某个地位有了节点,之后线程一取得执行权继续执行,因为并发transfer,所以两者都是扩容的同一个链表,当线程一执行到e.next = new table[i] 的时候,因为线程二之前数据迁徙的起因导致此时new table[i] 上就有ertry存在,所以线程一执行的时候,会将next节点,设置为本人,导致本人相互应用next援用对方,因而产生链表,导致死循环。
- 线程池有哪些类型
①FixedThreadPool:创立可重用固定线程数的线程池。 ②SingleThreadPool:创立只有一个线程的线程池。 ③CachedThreadPool:一个可依据须要创立新线程的线程池,如果现有线程没有可用的,则创立一个新线程并增加到池中,如果有被应用完然而还没销毁的线程,就复用该线程。终止并从缓存中移除那些已有 60 秒钟未被应用的线程。因而,长时间放弃闲暇的线程池不会应用任何资源。 ④ScheduledThreadPool:创立一个线程池,它可安顿在给定提早后运行命令或者定期地执行。
- ConcurrentHashMap分段锁原理
(1)ConcurrentHashMap采纳了分段锁技术,其中Segement继承了RecentLock,当ConcurrentHashMap进行get、put操作时,均是同步的。各个Segement之间的get、put操作能够进行并发,即当一个线程拜访ConcurrentHashMap的Segement时,不会影响对其余Segement的拜访。
- B-树和B+树区别
1)B-树和B树是一个概念,是多路搜寻树(相比于二叉搜寻树,IO次数更少)。B-树的个性: ①关键字汇合散布在整颗树中; ②任何一个关键字呈现且只呈现在一个结点中; ③搜寻有可能在非叶子结点完结; ④其搜寻性能等价于在关键字选集内做一次二分查找; ⑤其最底搜寻性能为O(logN) (2)B+树是B-树的变体,也是一种多路搜寻树 B+的个性: ①所有关键字都呈现在叶子结点的链表中(浓密索引),且链表中的关键字恰好是有序的; ②不可能在非叶子结点命中; ③非叶子结点相当于是叶子结点的索引(稠密索引),叶子结点相当于是存储(关键字)数据的数据层; ④更适宜文件索引零碎; (3)B+树的劣势: ①繁多节点存储更多的元素,使得查问的IO次数更少。 ②所有查问都要查找到叶子节点,查问性能稳固。 ③所有叶子节点造成有序链表,便于范畴查问。
- Mysql数据库索引原理
(1)MyISAM索引实现:MyISAM引擎应用B+Tree作为索引构造,叶节点的data域寄存的是数据记录的地址。 (2)Innodb索引实现: ①第一个重大区别是InnoDB的数据文件自身就是索引文件。MyISAM索引文件和数据文件是拆散的,索引文件仅保留数据记录的地址。而在InnoDB中,表数据文件自身就是按B+Tree组织的一个索引构造,这棵树的叶节点data域保留了残缺的数据记录。这个索引的key是数据表的主键,因而InnoDB表数据文件自身就是主索引。 ②第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都援用主键作为data域。
- 组合索引怎么应用?最左匹配的原理。
1)组合索引怎么应用? 例如组合索引(a,b,c),组合索引的失效准则是: 从前往后顺次应用失效,如果两头某个索引没有应用,那么断点后面(范畴值也算断点,orderby不算断点,用到索引)的索引局部起作用,断点前面的索引没有起作用; (2)最左匹配的原理:以最右边的为终点任何间断的索引都能匹配上
- Spring生命周期
Bean 的生命周期概括起来就是 4 个阶段: (1)实例化(Instantiation) (2)属性赋值(Populate) (3)初始化(Initialization) (4)销毁(Destruction)
- Spring几种scope区别?
(1)singleton:Spring的IOC容器中只有一个实例bean,该值为scope的默认值 (2)prototype:每次getBean时都会创立一个新的实例 (3)request:每次申请都会创立一个实体bean (4)session:每次session申请时都会创立一个实体bean (5)globalsession:每个全局的HTTP Session,应用session定义的Bean都将产生一个新实例。
- Spring AOP实现有哪几种实现
接口代理和类代理会有什么区别? (1)Spring AOP有两种实现,均为动静代理: ①JDK动静代理:基于反射进行动静代理,外围类是InvocationHandker类和Proxy类,被代理的类必须实现接口 ②CGLIB动静代理:被代理类无需实现接口,次要实现MethodInterceptor接口即可实现代理 (2)Spring AOP如果代理的类存在接口,优先应用JDK动静代理,否则应用CGLIB动静代理。
欢送搜寻关注自己与敌人共同开发的微信面经小程序【大厂面试助手】和公众号【微瞰技术】