Java后端开发⼯程师⾯试⼋股⽂
说说mysql InnoDB索引结构
mysql InnoDB索引结构是基于B+树的,B+树叶⼦节点保存真实数据,⾮叶⼦节点保存索引数据,辅助索引是保存主键然后需要回主键索引表才能拿到真实数据。
基于B+树的结构需要⼀个主键来做⽐较建⽴B+树的,当我们建表不指定主键时mysql也会隐藏⼀个整形隐藏列主键ID作为聚集索引,
因为数据时保存在磁盘中的,读取的时候需要⼀页⼀页的读出来,当使⽤B+树的时候。⾮叶⼦节点就专门保存主键的,每读取⼀页就可以读取很多的主键,索引很⼴的范围,
相同的数据会使得树更矮,每次查询可以更少的进⾏磁盘IO操作,少⼀层就可以少⼀次IO操作,
同时因为数据是基于主键进⾏排序聚集的,所以当范围查询的时候就很⽅便,IO⼀页数据就可以读取⼀定范围的数据⽽不⽤多页IO。可以有效的减少磁盘IO操作。
说说事务隔离级别
先说说不同的事务操作⼀条数据会出现什么问题,不同事务操作同⼀条数据由严重程度会出现脏写、脏读、不可重复读、幻读四种后果。sql标准中定义了四种隔离级别,未提交读、已提交读、可重复读、可串⾏化。其中脏写是⽆论如何都不允许发⽣的,
所以未提交读可以脏读不可重复读幻读不可以脏写,已提交读可不可重复读幻读不可脏读脏写,可重复读可幻读不可脏读脏写不可重复读,可串⾏化是这些情况读不允许发⽣。
mysql这四种隔离级别都可以⽀持,其中默认是可重复读隔离级别。mysql对于隔离级别的⽀持是基于MVCC和gay锁的。未提交读、已提交读、可重复读根据隔离级别进⾏版本的选择,可串⾏化就通过加间隙锁进⾏防⽌幻读。
说话mysql的redo、undo分别有什么⽤
redo⽇志,磁盘的IO是⽐较慢的,为了加快操作对数据的操作,mysql对磁盘的数据进⾏缓存,所有操作会先在内存中操作,之后使⽤后台线程统⼀的去刷新数据到磁盘中持久化。
这个操作会出现当没来得及刷新的时候宕机就丢失没刷新部分的修改,不符合事务的持久性。
因为磁盘操作是以页未单位进⾏操作的,所以⼀旦事务提交就刷⼀次磁盘不现实,会导致很慢,事务可能只修改⼀丢丢就刷新整页或者事务更新涉及好⼏页内容更加慢。
所以mysql就进⾏redo⽇志的记录,记录修改的物理信息,什么页码修改位置等等信息。每次进⾏修改都⽣成⼀条⽇志,当修改页被持久化到磁盘后就删除⽇志,
这样设计后,可以先保存进⾏redo⽇志的持久化,redo⽇志⽂件⼩,⽽且顺序IO操作,持久化很⽅便很快,之后数据页修改很多后慢慢进⾏磁盘持久化,这样会使IO操作得到更⼤的收益,宕机后只需要更加redo⽇志进⾏恢复即可
undo⽇志,redo⽇志是记录物理页的修改记录,undo⽇志是记录每条数据的修改记录,每⾏对数据进⾏增删改都会记录⼀条undo⽇志。记录哪条事务修改,还记录指向其他修改记录的指针形成⼀个版本链。当事务需要回滚时就可以根据undo⽇志进⾏回滚。
说说MVCC机制
undo⽇志会记录数据的修改,并且会⽤⼀列保存上⼀个版本的undo⽇志指针,这样就会形成⼀条版本链条,链头就是最新的数据。
有了这个undo⽇志后,每次查询都根据当前环境⾥⾯事务的提交情况进⾏取版本链⾥⾯的某⼀个版本即可。
⽐如假设当前隔离级别是可重复读,当需要读取某⼀条数据时,会获取事务第⼀次查询时环境的事务
提交情况,查看需要读取数据的修改事务是否满⾜要求,
(获取当前环境事务提交情况有或者当前事务活跃ID列表,活跃中最⼩ID,下⼀个事务ID等信息,因为事务ID是递增的,所以当修改事务ID ⼩于活跃最⼩ID时可以认为该事务在当前事务⽣成前就已经提交了)
如果不满⾜,⽐如修改该条数据的该事务没有提交,则顺着版本链下⼀个版本的数据继续判断,知道到合适的版本返回。
通过这个MCVV机制可以⼀个时间同时多个事务对同⼀条数据进⾏操作,提⾼系统性能。
说说mysql的锁机制
mysql中锁按粒度可以分为表级锁和⾏级锁,表级锁⼜可以细分为共享锁、独占锁、独占意向锁,共享意向锁,⾏级锁也可以细分为共享锁、独占锁、间隙锁。
表级锁和⾏级锁就是分别对表和⾏锁定的,共享锁、独占锁也好理解就是共享可以多个事务获取释放,独占只有⼀个事务获取锁,增删改会⾃动加锁⾏级独占锁,查可以指定锁。对记录的操作不会⾃动获取表级锁。
意向锁是作⽤是当要加⾏级锁时需要给表加意向锁,之后当要进⾏表级锁时需要先判断是否还有意向锁,有则说明还有⾏级锁没有释放不能锁表。间隙锁作⽤是对锁定的⾏前⾯间隙进⾏锁定,不允许在⾏前⾯间隙插⼊数据,间隙锁只是为了防⽌出现幻读⽽已。
mysql是通过在内存中⽣成⼀个锁结构实现的,每次访问表或者记录前先去内存中寻对应的锁结构,之后根据锁类型进⾏获取锁或者等待。
说说mybaits原理
⾸先,之前Java连接数据库jdk有定义⼀套规范JDBC,但是这个规范使⽤起来太⿇烦,
流程⼤概有加载驱动、连接数据库、执⾏sql、处理结果、释放资源。
特别是sql是以字符串的形式进⾏传参的,
所以在写sql时需要在代码⾥进⾏各种字符串的拼接,使⽤连接池也很不⽅便等等,严重影响开发的效率,
所以mybatis就是基于此诞⽣。mybatis时对JDBC的增加,底层还是调⽤的JDBC接⼝,但是做⼀些⽅便开发者进⾏数据库操作的事情,⽐如
通过mapper⽂件进⾏sql的编写,
⼀是进⾏sql和业务代码解耦,⼆是提供很多⽅便实⽤标签给开发者编写sql总⽐字符串拼接⽅便,三开发时通过接⼝的⽅式进⾏访问数据库,mybatis会⾃动通过动态代理⽣成接⼝的代理,接⼝被调⽤时执⾏相应的sql返回结果。
将数据库返回结果⾃动与Java对象进⾏映射,还⽀持如理驼峰命名这种命名习惯进⾏转换,省去了很多⿇烦。
内置⼀个连接池的⽀持,不⽤开发者⾃⼰实现连接池。
通过⼀⼆级缓存机制提⾼访问性能
mybatis中#{}和${}区别?
使⽤#{}是进⾏预编译处理的,也就是话⽆论传什么值都直接加单引号作为参数的值传递,传⼊命令什么的都当作字符串处理,⽽${}是直接进⾏字符串拼接的,假设传⼊⼀些命令是会被执⾏的
mybatis中⼀⼆级缓存的⼯作机制?
⾸先这个缓存是未了减少进⾏数据库的查询次数进⾏缓存的,前提是当查询条件查询参数⼀样⽽且期间没有进⾏增删改时返回的结果时⼀样的
所以可以进⾏缓存,下次再查时直接取缓存的数据加快查询速度。
⼀级缓存时会话级别的,不同的sqlsession是不共享缓存的。
⼆级缓存是可以跨会话的,作⽤空间是namespace级别,不同的sqlsession操作同⼀个mapper是可以共享缓存的,但是⼀个mapper操作多个表的情况就会有误所以还是有局限的。
⼀级缓存默认开的,⼆级默认关闭,当查询是先去查⼆级缓存没有再查⼀级缓存。
说说⼀个请求从输⼊URL到展⽰页⾯的全过程
1、根据域名进⾏解析IP,先查本地是否⼜缓存,再到DNS服务器,⼀直往上知道到对应的IP为⽌,
2、进⾏TCP连接,确认可以进⾏通讯
3、发起http请求,携带请求头、请求体等等信息
4、服务器进⾏处理并返回http报⽂
5、浏览器根据返回的html、css等进⾏解析渲染页⾯
6、结束连接,四次挥⼿
说说TCP和UDP的区别
最主要的区别是TCP定位是做⼀个可靠的传输,⽽UDP则是定位更加快速的传输数据但是相对不可靠的。
TCP是⾯向连接的,每次通讯都需要进⾏握⼿连接,结束通讯需要挥⼿告别,每次传输需要确认送达,还有重传机制等保证TCP的可靠性但是UDP就没那么多机制,直接指向⽬的地址后发送数据就不管,不⽤连接也不⽤确认,所以数据报⽂相对TCP更加简单,传输速度也因为没有那么⿇烦的T机制所以相对更加快
所以TCP优点就是靠谱,缺点就是只能点对点传输且较慢相同数据开销较⼤,UDP优点就是可以⼀对多传输且速度相对较快相同数据开销较⼩,但是不可靠会出现丢包的情况
说说为什么要三次握⼿、四次挥⼿
第⼀次握⼿确定客户端能发送数据,第⼆次握⼿确定服务器能接受数据和发送数据,第三次握⼿是确定客户端能接受数据
第⼀次挥⼿确定客户端不在发送数据,第⼆次挥⼿确定服务端不再接受数据,第三次挥⼿确定服务端不再发送数据,第四次挥⼿确定客户端不在接受数据
说说HTTPS原理
https是⼀个加密传输协议,通过加密算法对报⽂进⾏加密传输。https是通过⾮对称加密算法确认传输的密钥后使⽤对称加密算法进⾏信息的加密传输。、
⾸先https协议通信开始会涉及第三⽅服务器做证书的验证,⾸先客户端向服务器发起请求,服务器返回证书和公钥给客户端,之后客户端向权威机构去验证服务端发送的公钥和证书是否正确
如果正确⽆误,客户端⽣成⼀个随机数后⽤公钥进⾏加密发送,因为公钥加密只有私钥能解密,私钥只有服务器拥有,所以只有服务器额能解密得到客户端的随机数
现在客户端和服务端都拥有了⼀个随机数作为加密钥匙,并且只有服务器和客户端拥有,所以接下来的数据传输都是基于这个钥匙进⾏对称加密,⼀⽅加密⼀⽅解密即可,因为钥匙只有双⽅拥有所以其他⼈是解不了的。
redis使⽤场景
redis是⼀个内存数据库,性能⾮常的⾼,数据类型也⾮常丰富,
所以⼀般使⽤作为⼀个缓存中间件,因为当每个请求都全部打到数据库的话,因为数据库是需要进⾏磁盘IO操作的,⼤量请求会造成很⼤压⼒可能会直接卡死,所以需要redis做⼀个中间缓存层没必要就不操作数据库分担压⼒。
也可以⽤来做分布式锁、共享session、热榜、计数限流、队列这些,都是基于redis的单线程⾼性能的纯内存的数据库进⾏扩展使⽤。
说说redis为什么快
redis是纯内存操作不涉及IO操作,redis是单线程的不涉及线程的上下⽂切换,使⽤多路IO复⽤模型处理⽹络请求⾼效处理IO,
说说redis怎么保证⾼可⽤
主从复制,哨兵机制,使⽤哨兵定时获取节点的运⾏状况、发送当前状态给各个节点,当主节点挂掉时选举新的主节点。
说说redis有哪些数据类型
string,最基本也是最常⽤的类型,底层是通过SDS结构维护⼀个字节数组实现,所以是⼆进制安全的,也就是说保存什么图⽚序列化对象啥的都可以,输⼊什么输出就是什么。因为操作的原⼦性常⽤⼀下计数的场景,计数访问数、⾃增ID⽣成等
java加密方式有哪些hash,是⼀个键值对的结构,类似Java⾥⾯的hashmap,底层也是类似hashmap的实现⽤数组+链表的⽅式实现。hash类型很适合保存对象,所以经常拿来保存缓存数据之类的,
set,⽆序不重复的集合,底层基于hashtable实现的,将hashtable中的value为空实现。因为具备不重复特性可以⽤来去重、交集并集计算等场景
sort zet,有序不重复的集合,底层基于跳跃表实现,查询效率可以达到logn。不重复且有序的⼀般⽤来做排⾏榜等的功能
list,是⼀个链表,底层⽤双向链表实现。可以⽤来做消息队列
说说redis的持久化
redis有两种持久化机制,⼀种是RDB也就是快照的形式,既将某个时间内内存⾥⾯的所有数据进⾏保存。⼀种是AOF也就是追加的⽅式,每只执⾏⼀条修改命令都将命令追加到磁盘AOF⽂件⾥⾯。
两种⽅式各有优点,RDB的⽅式就是实时性不好,不可能实时都进⾏快照保存的,这样影响性能。AOF的⽅式实时性更好,但是因为每条修改命令都持久化,所以恢复的时候更加耗时。
⽬前redis已经⽀持两种混合的机制,兼顾两种的优点和弥补各⾃的缺点,既隔⼀段时间就进⾏⼀次快照持久化,间隔期间就进⾏AOF的⽅式持久化。
说说redis的事务
redis事务实际上是将命令打包成⼀个队列,之后按顺序取执⾏命令且执⾏结束之前不会被打断。只保证了执⾏的顺序,当命令执⾏失败后会继续执⾏接下来的命令不会结束事务,已经执⾏的命令也不会被回滚。
说说缓存穿透、缓存击穿、缓存雪崩
击穿,既当某⼀个缓存热点数据突然过期时,所有对该数据的访问请求会直接打到数据库,导致数据库的压⼒过⼤。解决⽅案做⼀个锁的⽅案,当缓存查寻为null时只允许⼀个线程访问数据库并且将数据进⾏缓存,之后其他线程在从缓存中取数据。
穿透,既当某⼀个数据为空时,因为为空所以没有缓存,当这个数据访问量⼤时会⼤量的请求打到数据库即使查询结果都会空也会导致数据库的压⼒过⼤,解决⽅案可以将为空的数据也进⾏缓存key,也
可以使⽤布隆过滤器,将所有可能存在的数据哈希到⼀个⾜够⼤的bitmap 中,⼀个⼀定不存在的数据会被 这个bitmap拦截掉。
缓存雪崩,既当所有缓存同时失效时⼤量请求全部进⼊数据库的情况。⼀般解决⽅案有随机设置缓存过期时间均摊分配失效时间,也可以⽤队列或者加锁的⽅式限制访问数据库的线程数,也可以使⽤双缓存的⽅式主缓存没有就去备缓存取。
说说redis的内存删除和淘汰策略
删除策略有两种,⼀是惰性删除,既当数据被访问时再检查如果过期就删除,如果永远不被访问就过期也永远不删除,⼆⼗定期删除,既周期性的去清理过期的数据。两种⽅法各有好处所以redis组合着使⽤
redis也提供8种内存淘汰策略,保证缓存都是有⽤的数据。就是从设置过期时间的数据集、所有数据集种lru、lfu、随机的淘汰数据六种。还有挑选要过期的淘汰和从不淘汰两种

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。