MyBatis
解释MyBatis
MyBatis是一个半自动化ORM框架,封装了JDBC,专注于SQL语句本身
优点:基于原生SQL、将SQL编写在XML文件与程序代码分离、支持映射标签
缺点:SQL编写工作量大、数据库移植性差
应用场景:灵活dao层的解决方案、性能要求较高的需求变更较多的
MyBatis和Hibernate的区别
MyBatis:是一个半自动ORM框架,移植性差,对于多数据库应用,需要编写多套SQL映射文件
Hibernate:映射关系强,数据库无关性好,代码少,效率高
通常一个xml映射文件都会对应一个dao接口,这个dao接口工作原理是什么
JDK动态代理,MyBatis运行时,将接口全限定命名拼接方法名作为key,定位唯一的MapperStatement对象,生成代理类对象拦截方法,转而执行MapperStatement对应的SQL
MyBatis是如何进行分页的,分页插件的原理
MyBatis是通过RowBounds进行分页,是基于结果集执行的内存分页
通过MyBatis提供的插件接口,实现自定义插件,在分页插件的拦截方法中拦截待执行SQL,并根据dialect重写SQL,添加物理分页参数和语句
如何执行批量插入
将ExecutorType.Batch作为参数传入openSession方法
MyBatis的一级、二级缓存
一级缓存:基于HashMap存储,作用域为Session,会话关闭,缓存清空,默认开启
二级缓存:基于HashMap存储,作用域为NameSpace,映射实体类需要实现序列化接口
当进行C/U/D操作后,select缓存会被clear
MyBatis的插件运行原理,以及如何编写一个插件
JDK动态代理,为待拦截接口生成代理类对象,会拦截ParameterHandler、StatementHandler、ResultSetHandler、Executor中的方法,转而执行拦截器方法
实现拦截器接口,添加@Intercepts注解、拦截签名,重写intercept方法
ZooKeeper
解释ZooKeeper
是一个分布式的、开源的分布式应用协调服务
可提供命名服务、集群管理、分布式锁等功能
为分布式提供一致性特性:
- 顺序一致性
- 原子性
- 单一视图
- 可靠性
- 最终一致性
ZAB协议
通过这个ZAB协议可以进行集群间的数据同步,保证数据一致性
启动时,如何进行Leader选举
- 服务器节点给自己投票,发送投票信息(SID,ZXID)给其它节点
- 接收某节点的投票信息,检查某节点是否为本轮投票,及是否是looking的状态
- 投票PK,如果别的节点的ZXID较大,则把自己的投票信息更新为别的节点的投票信息
- 如果ZXID相同,则比较SID,更新投票信息为SID较大的
- 统计投票,判断是否有过半节点收到相同投票信息
- 更新节点状态
节点之间如何同步数据的?
- 如果客户端连接了主节点,且发送了写请求
- Leader节点会执行两阶段提交协议同步给其它节点
Zookeeper的Watcher机制
ZooKeeper允许客户端向znode注册一个Watcher事件,当服务器的一些指定事件触发Watcher,服务器会发送一个事件通知给客户端,客户端根据Watcher通知状态和事件类型,在业务上做出改变
Zookeeper如何保证事务顺序一致性
采用一个全局递增的事务id,高32位为epoch标识Leader版本,新Leader产生就会自增一次,低32位是用来递增计数
Dubbo
解释Dubbo
Dubbo是一个高性能的分布式服务框架,用于远程服务调用、服务治理,它具有透明化的远程调用、负载均衡、服务注册于发现、可扩展性、服务治理等特性。
Dubbo工作原理
- 服务启动,服务提供者和服务消费者会根据配置信息连接到注册中心,分别向注册中心注册和订阅服务;
- 注册中心会根据订阅关系,去返回服务提供者的信息到服务消费者,同时,服务消费者会把服务提供者的信息缓存到本地,如果信息发送变更,消费者会收到注册中心的一个推送,去更新本地的缓存;
- 服务消费者会生成代理对象,同时根据负载均衡策略去选择一台目标的服务提供者,并定时向监控中心记录接口的调用次数和时间信息;
- 拿到代理对象后,服务消费者通过代理对象发起对接口的调用;
- 服务提供者收到请求后,会根据数据反序列化,然后通过代理调用具体接口的一个实现
Dubbo和Spring Cloud的区别
- Dubbo是SOA时代的产物,它的关注点主要在于服务的远程调用、流量分发、服务治理、流量控制等等方面;而Spring Cloud是诞生于微服务架构时代,它关注的是微服务整个生态的解决方案,另外,Spring Cloud依托于Spring、Spring Boot的生态,所以两个框架的目标是不一致的。
- Dubbo的底层使用的是Netty这样的NIO框架,是基于TCP进行传输,然后通过Hessian序列化的方式去完成的RPC的通信;而Spring Cloud是基于Http协议+Rest风格的一个接口去实现通信,相对来说,Http请求会有更大的一些报文,占用的带宽会更多,效率上比Dubbo更差一些,但Http相比RPC来说会更加灵活,服务提供方和服务调用方只需根据Http一个契约去通信即可。
Elasticsearch
解释Elasticsearch
Elasticsearch是一个开源的分布式搜索引擎,用于快速准确地存储和检索大量数据
Master选举
- 当候选节点发现包括自己在内的多数节点都认为集群中不存在Master节点时,开始发起选举
- 首先判断是否具有主节点资格,选取clusterStateVersion大的
- 如果状态相同,就选取nodeid最小的作为临时主节点
- 当某节点的投票数达到n/2+1时,则当选成为主节点
写入流程
- 数据写入内存buffer缓冲区同时写入translog,每隔一秒从内存缓冲区写入segment文件
- 并进入文件系统缓存,可供search,buffer被清空
- 当translog文件达到一定大小,用fsync将所有缓存数据刷入磁盘
- 清空现有的translog,创建一个新translog
Memcached
解释Memcached
Memcached是一个开源的、高性能的内存缓存软件。
作用:在规划好的内存中临时缓存数据库数据,达到减少业务对数据库的直接高并发访问,从而提升数据库访问性能,加速网站集群动态应用服务的能力
Memcached分布式集群如何实现
使用一致性哈希,加载所有MC的ip列表,对key做哈希,使数据分配到不同服务器,而且服务器重新分配的比例降到最低
Redis
解释Redis
Redis是一个完全开源的、遵守BSD协议、高性能的KV数据库
优势与特点:
- 支持持久化
- 支持事务
- 丰富数据类型
- 高性能:读110000次/s,写81000次/s
Redis集群原理
- 哨兵集群:高可用,当Master宕机时,会自动将一个Slave提升为Master继续提供服务
- 分片集群:可扩展,单个Redis服务器内存不够时,可使用cluster进行分片存储
说说Redis哈希槽
一共有16384个哈希槽,每个key通过CRC16校验后并对16384取模来决定存放在哪个哈希槽,集群中每个节点负责一部分的哈希槽
Redis回收进程如何工作
一个客户端执行了新指令,新增了数据,Redis会检查内存使用情况,如果超过了maxmemory,就根据指定策略进行回收
MySQL
BLOB和TEXT的区别
- blob是二进制存储;text是字符串存储
- blob无需字符集校验;text需要指定字符集
- blob区分大小写;text不区分大小写
SQL语句优化
- 查询优化
- where、group by、order by后字段使用索引
- 插入优化
- 批量插入
- 使用事务
RabbitMQ
解释RabbitMQ
RabbitMQ是采用高级消息队列协议的一种消息队列技术,最大的特点是消费者无需确定提供者的存在,实现了服务之间的解耦
优势:
- 持久化机制
- 提供者和消费者的解耦
- 高并发场景下,进行限流
- 异步处理
如何确保消息正确地发送至RabbitMQ?如何确保消息接收方消费了消息
发送方确认模式:将信道设置为confirm模式,则所有在信道上发布的消息都会被指派一个唯一id,一旦消息投递到目的队列或写入磁盘,就会返回一个ack,如果消息丢失,会返回nack
接受方确认机制:消费者收到每条消息后必须进行确认,确认后消息才能安全地从队列中移除;如果消息未确认前,消费者断开连接,RabbitMQ会认为未分发消息,重新分发消息给订阅的消费者;如果消息未确认,且未断开连接,RabbitMQ会认为消费者繁忙,不会给该消费者分发更多的消息
如何确保消息不丢失
将消息写入到磁盘的一个持久化日志文件中,当消息被投递到持久化交换机时,会在提交日志文件后再发送。
如果在消费前RabbitMQ宕机重启,RabbitMQ会自动重建交换机和队列并绑定,重新将日志文件中的消息发送到相关队列
MQ的缺点
- 系统复杂度提高
- 系统可用性降低
- 一致性问题
Kafka
解释Kafka
Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。
Kafka与传统MQ之间的关键区别
- Kafka的持久化日志可以被重复读取和无限期保留
- Kafka是一个分布式系统,以集群的方式运行,在内部通过复制数据提升容错和保证高可用
- 支持实时的流式处理
如何减少数据丢失
- 设置ack机制
- 设置同步刷盘策略:unclean_leader_election_enable=false
- 手动提交偏移量
Linux
在不重启机器的情况下,把所有正在运行的进程移除
disown -r
怎么查看一个Linux命令的概要与用法
whatis [命令]
Spring
Spring Framework
Spring是一个开源框架,旨在降低开发复杂度,他是轻量级的、松耦合的,它具有分层体系架构、允许集成其它框架
- AOP
- IOC
- 容器
- 事务
- MVC
Spring Boot
简化Spring框架初始搭建和开发过程
- 减少开发、测试时间
- 避免使用XML、更少的配置
- 避免大量导入Maven依赖和版本冲突
- 提供默认值快速开始开发
- 不需要单独配置Web服务器
Spring Cloud
它是一系列框架的有序集合,利用SpringBoot的开发便利性简化了分布式系统基础设施的开发
Spring Cloud Bus
它是基于消息代理的分布式系统消息总线,可以跨多实例刷新配置
Java基础
类加载机制原理
加载、验证、准备、解析、使用
运行时异常和受检异常
- 运行时异常:无法让程序恢复运行的异常
- 受检异常:程序需要捕获或处理的异常
sleep和yield
- sleep给其它线程运行机会不考虑优先级;yield给相同或更高优先级的线程运行机会
- sleep会进入阻塞状态,yield会进入就绪状态
- sleep方法声明抛出InterruptedException;yield方法没有声明抛出任何异常
直接缓冲区和非直接缓冲区
直接缓冲区:在物理内存申请一块空间,映射到用户程序和本地磁盘,不再经过内核地址空间和用户地址空间,用户程序与磁盘之间的存取通过这块空间进行
非直接缓冲区:数据需要在内核地址空间与用户地址空间,在操作系统和JVM之间进行来回拷贝
Serializable、Externalizable
Serializable:默认的序列化方式,高成本、脆弱且不安全
Externalizable:允许控制整个序列化过程,指定特定的二进制格式,增加安全机制
Java并发
多线程中的上下文切换
为了保证每个线程都能有执行的机会,就需要轮转使用CPU,不同线程之间切换使用CPU产生的数据就是上下文切换
死锁、活锁、饥饿
- 死锁:两个及两个以上的线程执行过程中,因争夺资源而造成相互等待的现象,无外力作用,它们都无法推进下去
- 活锁:一个任务没有被阻塞,某些条件没有满足,一直重试、失败……
- 饥饿:一个或多个线程因种种原因无法获得所需资源,导致一直无法执行
什么是原子操作?有哪些原子类
不受其它操作影响的操作任务单元
-
原子类:AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference
-
原子数组:AtomicIntegerArray、AtomicLongArray
-
原子属性更新器:AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
-
处理ABA问题:AtomicMarkableReference、AtomicStampedReference
Java并发api中的lock接口对比同步有什么优势
- 可以使锁更公平
- 可以使线程等待锁时,响应中断
- 可以在尝试获取锁,并在无法获取锁时立即返回或等待一段时间
FutureTask
一个可以取消的异步运算,包装了callable、runnable
只有运算完成结果才能取回,如果运算尚未完成get方法将会被阻塞
interrupt、interrupted和isInterrupted
- Interrupt:中断线程,将线程状态置为中断
- interrupted:查询线程中断状态,并清除原状态
- isInterrupted:查询线程中断状态