作者: 瞿云康,英文名jacksonKang,是一名努力成长中的Java爱好者 。 本文出处: http://mayiyk.cn/article/6 本文为昨天Java面试题整理的第二篇,这个系列的文章主要把一些常见的java面试题目整理发给大家,希望能在大家以后的面试中提供一些帮助。
一想到你在关注我就忍不住有点紧张
一、http协议超文本传输协议由三部分组成,分别是:请求行,消息报文,请求正文,基于请求与响应模式,无状态的、应用层的协议。与https的区别在于a:通信明文不加密,内容可以被窃听,b:不验证通信方身份,可能遭到伪装,c:无法验证报文的完整性,可能别篡改。
解决分布式系统之间的消息传递。例如用户注册,发送消息给中间件,然后让邮件服务和短信服务自己去消息中间件里面去取消息,然后取到消息后再对自己做对应的业务操作。
a:异步处理,b:应用的解耦,c:流量的削峰,d:日志的处理(大数据的日志处理非他莫属,非常强大),e:纯粹的消息通信
https://www.cnblogs.com/Jansens520/p/8624708.html
https://blog.csdn.net/ll666634/article/details/78615505 (代码)
加密机制:
安全认证机制:
事物是作为单个逻辑单元执行的一组操作,要么全部成功,要么全部失败。共四个特性:
CAP定理
XA:oracle与DB2商业性数据实现了其接口,事物管理器作为全局的调度者,负责各个本地资源的提交和回滚。 缺点:XA无法满足高并发场景。mysql的xa实现没有记录preare日志。主备切换会导致数据库数据不一致。
MQ:高并发场景下,将一个分布式事物拆分成消息事物(A系统的本地操作+发消息+B系统的本地操作),其中B系统的操作由消息驱动,只要消息事物成功,那么A操作一定成功,消息也一定发出去了。这时候B再去执行操作,如果本地操作失败,消息会重投,直到B操作成功。因此牺牲了一致性,换来性能的提升。
TCC编程模式(最大补偿策略):将整个业务逻辑变成三块, try confirm cancle三个操作,try阶段去扣除库存,confirm去更新订单状态,如果订单失败则进入cancle阶段,会去恢复库存,这种模式并不能更好的复用,不同业务场景所写的代码不一样,复杂度也不一样。
事务的四个属性:持久性、原子性、隔离性、一致性。其中一致性是最基本的属性,其他三个属性都是为了保证一致性而存在的。所谓一致性是指数据处于一种有意义的状态,这种状态是语义上的而不是语法上的。例如转账过程中的一致性。
在数据库实现场景中,一致性可以分为数据库外部一致性和数据库内部一致性。前者由外部应用的编码来保证,即某个应用在执行转账的数据库操作时,必须在同一个事务内部调用对账户A和账户B的操作,㐊数据库本身能解决的。后者有数据库来保证,即在同一个事务内部的一组操作必须全部执行成功,这是事务处理的原子性。
为了实现原子性,需要通过日志,将所有对数据库的更新操作都写入日志,如果一个事务中的一部分操作成功,但以后的操作无法继续,则通过回溯日志,将已经操作成功的操作撤销,从而达到全部操作失败的目的。典型场景是,数据库系统崩溃后重启,此时数据库处于不一致的状态,必须先执行一个crash recovery的过程,读取日志进行redo(重演将所有已经执行但未成功写入到磁盘的操作,保证持久性),再对所有到崩溃时尚未成功提交的事务进行undo(撤销所有执行了一部分但尚未提交的操作,保证原子性)。crash recovery结束后,数据库恢复到一致性状态。
在多个事务并行进行的情况下,即时保证了每一个事务的原子性,仍然可能导致数据的不一致的结果。对此引入了隔离性,即保证每一个事务能够看到的数据总是一致的,好像其他并发事务并不存在一样。实现隔离性有两种典型锁:
一种是悲观锁,即当前事务将所有涉及操作的对象加锁,操作完成后释放给其他对象使用。为了尽可能提高性能。发明了各种粒度,各种性质的锁,为了解决死锁问题,又发明了两阶段锁协议等一些列技术。
乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。数据版本,为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新,否则认为是过期数据。实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳。
对于每条消息,MQ内部生成一个全局唯一、与业务无关的消息ID:inner-msg-id。当MQ-server接收到消息时,先根据inner-msg-id判断消息是否重复发送,再决定是否将消息落地到DB中,这样有了这个作为去重的依据能保证一条消息只能一次落地DB。
场景:集群部署一个应用需要部署到多台机器上做到负载均衡。
基于数据库实现:在数据库创建一张表,表中包含方法名字段,并在方法名上创建索引并做唯一约束,想要执行某个方法,就使用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁。缺点:a:影响可用性及性能,需要双机部署,数据同步,主备切换。b:不具备可重入性。c:没有锁失效机制。服务器宕机表中数据没有删除。增加记录有效时间字段,需要定时任务清除这些失效数据。d:不具备阻塞特性,获取不到返回失败,需要循环多次去获取。e:依赖数据库资源开销及性能。
基于redis实现:1、获取锁的时候,使用setnx加锁,使用expire命令为锁添加一个超时时间,锁的value值为一个随机生成的uuid。2、获取锁的时候还设置一个获取超时的时间,若超过时间则放弃获取锁。3、释放锁判断是否是此uuid 如果是则删除,释放锁。优点:很多缓存服务都是集群部署避免单点问题,提供了很多实现分布式锁的方法。性能好实现起来方便。缺点:通过超时时间来控制锁的失效时间不是十分靠谱。
Zookeeper实现:性能上不如缓存实现的分布式锁,需要了解其原理。
工作流是多个参与者,按照某种预定义的规则,传递业务信息,进行审核的一个框架,23张表
要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。
我们可以使用命令设置MySQL为非autocommit模式:
乐观锁相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做
使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容
Reader类的read()方法返回类型为int :作为整数读取的字符(占两个字节共16位),范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1
字节流与字符流主要的区别是他们的的处理方式
运行时异常也叫非检查异常,比如常见的NullPointException,ClassCastException。这种异常可以不使用try...catch进行处理,但是如果有异常产生,则异常将由JVM进行处理。与其相对的,检查异常是强制需要用户处理的异常。
面试准备:
https://blog.csdn.net/u011958281/article/details/77098013
https://blog.csdn.net/sinat_35512245/article/details/60325685
https://blog.csdn.net/weixin_40096176/article/details/80605626
推荐阅读:java面试题整理(一)
加入知数堂
挑战50万+年薪!
点“在看”给我一朵小黄花