银盛支付Java中级

1. 说说springcloud的⼯作原理

1655976037341

springcloud由以下⼏个核⼼组件构成:

Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉

取注册表,从⽽知道其他服务在哪⾥

Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从⼀个服务的多台机器中选择⼀台

Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求

Hystrix:发起请求是通过Hystrix的线程池来⾛的,不同的服务⾛不同的线程池,实现了不同服务调⽤的隔离,避免了服务雪崩

的问题

Zuul:如果前端、移动端要调⽤后端系统,统⼀从Zuul⽹关进⼊,由Zuul⽹关转发请求给对应的服务

2. ⽤什么组件发请求

在Spring Cloud中使⽤Feign, 我们可以做到使⽤HTTP请求远程服务时能与调⽤本地⽅法⼀样的编码体验,开发者完全感知不到

这是远程⽅法,更感知不到这是个HTTP请求。

3. 注册中心心跳是几秒

1、Eureka的客户端默认每隔30s会向eureka服务端更新实例,注册中⼼也会定时进⾏检查,发现某个实例默认90s内没有再收到

⼼跳,会注销此实例,这些时间间隔是可配置的。

2、不过注册中⼼还有⼀个保护模式(服务端在短时间内丢失过多客户端的时候,就会进⼊保护模式),在这个保护模式下,他

会认为是⽹络问题,不会注销任何过期的实例。

4. 消费者是如何发现服务提供者的

1655976084493

a. 当⼀个服务实例启动,会将它的ip地址等信息注册到eureka;

b. 当a服务调⽤b服务,a服务会通过Ribbon检查本地是否有b服务实例信息的缓存;

c. Ribbon会定期从eureka刷新本地缓存。

5. 多个消费者调用同⼀接⼝,eruka默认的分配方式是什么

a. RoundRobinRule:轮询策略,Ribbon以轮询的⽅式选择服务器,这个是默认值。所以示例中所启动的两个服务会被循环访问;

b. RandomRule:随机选择,也就是说Ribbon会随机从服务器列表中选择⼀个进⾏访问;

c. BestAvailableRule:最⼤可⽤策略,即先过滤出故障服务器后,选择⼀个当前并发请求数最⼩的;

d. WeightedResponseTimeRule:带有加权的轮询策略,对各个服务器响应时间进⾏加权处理,然后在采⽤轮询的⽅式来获取相

应的服务器;

e. AvailabilityFilteringRule:可⽤过滤策略,先过滤出故障的或并发请求⼤于阈值⼀部分服务实例,然后再以线性轮询的⽅式从

过滤后的实例清单中选出⼀个;

f. ZoneAvoidanceRule:区域感知策略,先使⽤主过滤条件(区域负载器,选择最优区域)对所有实例过滤并返回过滤后的实例

清单,依次使⽤次过滤条件列表中的过滤条件对主过滤条件的结果进⾏过滤,判断最⼩过滤数(默认1)和最⼩过滤百分⽐(默

认0),最后对满⾜条件的服务器则使⽤RoundRobinRule(轮询⽅式)选择⼀个服务器实例。

6. 说说常⽤的springboot注解,及其实现?

a. @Bean:注册Bean

i. 默认使⽤⽅法名作为id,可以在后⾯定义id如@Bean(“xx”);

ii. 默认为单例。

iii. 可以指定init⽅法和destroy⽅法:

  1. 对象创建和赋值完成,调⽤初始化⽅法;

  2. 单实例bean在容器销毁的时候执⾏destroy⽅法;

  3. 多实例bean,容器关闭是不会调⽤destroy⽅法。

b. @Scope:Bean作⽤域

i. 默认为singleton;

ii. 类型:

  1. singleton单实例(默认值):ioc容器启动时会调⽤⽅法创建对象放到ioc容器中,以后每次获取就是直接从容器中拿

实例;

  1. prototype多实例:ioc容器启动不会创建对象,每次获取时才会调⽤⽅法创建实例;

  2. request同⼀次请求创建⼀个实例;

  3. session同⼀个session创建⼀个实例。

c. @Value:给变量赋值

i. 代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import org.springframework.beans.factory.annotation.Value; 
public class Person extends BaseEntity{ 
     @Value("xuan")
    private String name;
    @Value("27")
    private int age;
    @Value("#{20-7}")
    private int count;
    @Value("$person.nickName}")
	private String nickName;
}

i. ⽅式:

  1. 基本数字

  2. 可以写SpEL(Spring EL表达式):#{}

  3. 可以写${},取出配置⽂件中的值(在运⾏环境变量⾥⾯的值)

d. @Autowired:⾃动装配

i. 默认优先按照类型去容器中找对应的组件:BookService bookService = applicationContext.getBean(BookService.class);

ii. 默认⼀定要找到,如果没有找到则报错。可以使⽤@Autowired(required = false)标记bean为⾮必须的。

iii. 如果找到多个相同类型的组件,再根据属性名称去容器中查找。

iv. @Qualifier(“bookDao2”)明确的指定要装配的bean。

v. @Primary:让spring默认装配⾸选的bean,也可以使⽤@Qualifier()指定要装配的bean。

e. @Profile:环境标识

i. Spring为我们提供的可以根据当前环境,动态的激活和切换⼀系列组件的功能;

ii. @Profile指定组件在哪个环境才能被注册到容器中,默认为"default"@Profile(“default”)。

iii. 激活⽅式:

  1. 运⾏时添加虚拟机参数:-Dspring.profiles.active=test

  2. 代码⽅式:

7. spring的事务注解是什么?什么情况下事物才会回滚

a. spring事务实现机制:

1655976217403

b. 事务注解@transactional;

c. 默认情况下,如果在事务中抛出了未检查异常(继承⾃ RuntimeException 的异常)或者 Error,则 Spring 将回滚事务。

d. @Transactional 只能应⽤到 public ⽅法才有效:只有@Transactional 注解应⽤到 public ⽅法,才能进⾏事务管理。这是因为

在使⽤ Spring AOP 代理时,Spring 在调⽤在图 1 中的 TransactionInterceptor 在⽬标⽅法执⾏前后进⾏拦截之前,

DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept ⽅法或 JdkDynamicAopProxy 的 invoke ⽅法会间接调

⽤ AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取表 1. @Transactional 注解的事务属性配置属性信息)

的 computeTransactionAttribute ⽅法。

8. 说说spring事物的传播性和隔离级别

a. 七个事传播属性:

  1. PROPAGATION_REQUIRED – ⽀持当前事务,如果当前没有事务,就新建⼀个事务。这是最常⻅的选择。

  2. PROPAGATION_SUPPORTS – ⽀持当前事务,如果当前没有事务,就以⾮事务⽅式执⾏。

  3. PROPAGATION_MANDATORY – ⽀持当前事务,如果当前没有事务,就抛出异常。

  4. PROPAGATIONREQUIRESNEW – 新建事务,如果当前存在事务,把当前事务挂起

  5. PROPAGATIONNOTSUPPORTED – 以⾮事务⽅式执⾏操作,如果当前存在事务,就把当前事务挂起。

  6. PROPAGATION_NEVER – 以⾮事务⽅式执⾏,如果当前存在事务,则抛出异常。

  7. PROPAGATIONNESTED – 如果当前存在事务,则在嵌套事务内执⾏。如果当前没有事务,则进⾏与 PROPAGATIONREQUIRED类似的操作。

b. 五个隔离级别:

  1. ISOLATION_DEFAULT 这是⼀个PlatfromTransactionManager默认的隔离级别,使⽤数据库默认的事务隔离级别.

  2. 另外四个与JDBC的隔离级别相对应:

  3. ISOLATIONREADUNCOMMITTED 这是事务最低的隔离级别,它充许别外⼀个事务可以看到这个事务未提交的数据。这种

隔离级别会产⽣脏读,不可重复读和幻读。

  1. ISOLATIONREADCOMMITTED 保证⼀个事务修改的数据提交后才能被另外⼀个事务读取。另外⼀个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻读。

  2. ISOLATIONREPEATABLEREAD 这种事务隔离级别可以防⽌脏读,不可重复读。但是可能出现幻读。它除了保证⼀个事务不能读取另⼀个事务未提交的数据外,还保证了避免不可重复读。

  3. ISOLATION_SERIALIZABLE 这是花费最⾼代价但是最可靠的事务隔离级别。事务被处理为顺序执⾏。除了防⽌脏读,不可重复读外,还避免了幻读。

c. 关键词:

1655976292097

1、脏读(新增或删除):脏读就是指当⼀个事务正在访问数据,并且对数据进⾏了修改,⽽这种修改还没有提交到数据库 中,这时,另外⼀个事务也访问这个数据,然后使⽤了这个数据;

  • Mary的原工资为1000,财务人员将Mary的工资改为了8000(但未提交事务)
  • Mary读取自己的工资,发现自己的工资变为了8000,欢天喜地!
  • 而财务发现操作有误,回滚了事务,May的工资又变为了1000像这样,Mary记取的工资数8000是一个脏数据。

2、不可重复读(修改):是指在⼀个事务内,多次读同⼀数据。在这个事务还没有结束时,另外⼀个事务也访问该同⼀数据。那么,在第⼀个事务中的两次读数据之间,由于第⼆个事务的修改,那么第⼀个事务两次读到的的数据可能是不⼀样的。这样在⼀个事务内两次读到的数据是不⼀样的,因此称为是不可重复读。(解决:只有在修改事务完全提交之后才可以读取数据,则可以避免该问题);

  • 在事务1中,May读取了自己的工资为1000,操作并没有完成
  • 在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务.
  • 在事务1中,Mary再次读取自己的工资时,工资变为了2000

3、幻读(新增或删除):是指当事务不是独⽴执⾏时发⽣的⼀种现象,例如第⼀个事务对⼀个表中的数据进⾏了修改,这种修改涉及到表中的全部数据⾏。同时,第⼆个事务也修改这个表中的数据,这种修改是向表中插⼊⼀⾏新数据。那么,以后就会发⽣操作第⼀个事务的⽤户发现表中还有没有修改的数据⾏,就好象发⽣了幻觉⼀样(解决:如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可避免该问题)。

目前工资为1000的员工有10人。

  • 事务1,读取所有工资为1000的员工。
  • 这时事务2向employee表插入了一条员工记录,工资也为1000
  • 事务1再次读取所有工资为1000的员工共读取到了11条记录。

9. mysql的引擎有什么?他们的区别

a. InnoDB:

  1. ⽀持事务处理

  2. ⽀持外键

  3. ⽀持⾏锁

  4. 不⽀持FULLTEXT类型的索引(在Mysql5.6已引⼊)

  5. 不保存表的具体⾏数,扫描表来计算有多少行

  6. 对于AUTO_INCREMENT类型的字段,必须包含只有该字段的索引

  7. DELETE 表时,是一行一行的删除

  8. InnoDB 把数据和索引存放在表空间⾥⾯

  9. 跨平台可直接拷⻉使⽤

  10. 表格很难被压缩

b. MyISAM:

  1. 不⽀持事务,回滚将造成不完全回滚,不具有原⼦性

  2. 不⽀持外键

  3. ⽀持全⽂搜索

  4. 保存表的具体⾏数,不带where时,直接返回保存的⾏数

  5. DELETE 表时,先drop表,然后重建表

  6. MyISAM 表被存放在三个⽂件 。frm ⽂件存放表格定义。 数据⽂件是MYD (MYData) 。 索引⽂件是MYI (MYIndex)引伸

  7. 跨平台很难直接拷⻉

  8. AUTO_INCREMENT类型字段可以和其他字段⼀起建⽴联合索引

  9. 表格可以被压缩

c. 选择:因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原⼦性要求低。那么MyISAM最好的选择。且MyISAM恢复速度快。可直接⽤备份覆盖恢复。如果系统读少,写多的时候,尤其是并发写⼊⾼的时候。InnoDB就是⾸选了。两种类型都有⾃⼰优缺点,选择那个完全要看⾃⼰的实际类弄。

10. innodb如何实现mysql的事务

1655976478758

事务进行过程中,每次sql语句执⾏,都会记录undo log和redo log,然后更新数据形成脏⻚,然后redo log按照时间或者空间等条件进⾏落盘,undo log和脏⻚按照checkpoint进⾏落盘,落盘后相应的redo log就可以删除了。此时,事务还未COMMIT,如果发⽣崩溃,则⾸先检查checkpoint记录,使⽤相应的redo log进⾏数据和undo log的恢复,然后查看undo log的状态发现事务尚未提交,然后就使⽤undo log进⾏事务回滚。事务执⾏COMMIT操作时,会将本事务相关的所有redo log都进行落盘,只有所有redo log落盘成功,才算COMMIT成功。然后内存中的数据脏⻚继续按照checkpoint进⾏落盘。如果此时发生了崩溃,则只使⽤redo log恢复数据。

11.mysql索引谈⼀谈

12.说说b+树的原理

a. B-tree:

1655976533760

B-tree 利⽤了磁盘块的特性进⾏构建的树。每个磁盘块⼀个节点,每个节点包含了很关键字。把树的节点关键字增多后树的层级⽐原来的⼆叉树少了,减少数据查找的次数和复杂度。

B-tree巧妙利⽤了磁盘预读原理,将⼀个节点的⼤⼩设为等于⼀个⻚(每⻚为4K),这样每个节点只需要⼀次I/O就可以完全载入。

B-tree 的数据可以存在任何节点中。

  1. B+tree:

1655976558697

B+tree 是 B-tree 的变种,B+tree 数据只存储在叶⼦节点中。这样在B树的基础上每个节点存储的关键字数更多,树的层级更少

所以查询数据更快,所有指关键字指针都存在叶⼦节点,所以每次查找的次数都相同所以查询速度更稳定;

13. 让你设计⼀个索引,你会怎么设计

a. mysql默认存储引擎innodb只显式⽀持B树索引,对于频繁访问的表,innodb会透明建⽴⾃适应hash索引,即在B树索引基础上建⽴hash索引,可以显著提⾼查找效率,对于客户端是透明的,不可控制的,隐式的。

14. 还问了git和svn的区别

1、Git是分布式的,⽽Svn不是;

2、GIT把内容按元数据⽅式存储,⽽SVN是按⽂件

3、分⽀不同:git分⽀切换很⽅便;svn分⽀就是版本库的另外⼀个⽬录;

4、GIT没有⼀个全局的版本号,⽽svn有,SVN的版本号实际是任何⼀个相应时间的源代码快照。

5、GIT的内容完整性要优于SVN(GIT的内容存储使⽤的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和⽹络问题

时降低对版本库的破坏。)

15. git命令的⼀些底层原理以及流程

https://www.jianshu.com/p/2b47a3078a46

a. git init:使⽤git init初始化⼀个新的⽬录时,会⽣成⼀个.git的⽬录,该⽬录即为本地仓库。⼀个新初始化的本地仓库是这样的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
- HEAD
- branches
- config
- description
- hook
- objects
- - info
- - pack
- refs
- - heads
- - tags
  • description⽤于GitWeb程序
  • config配置特定于该仓库的设置(还记得git config的三个配置级别么)
  • hooks放置客户端或服务端的hook脚本
  • HEAD传说中的HEAD指针,指明当前处于哪个分⽀
  • objectsGit对象存储⽬录
  • refsGit引⽤存储⽬录
  • branches放置分⽀引⽤的⽬录
  • 其中description、config和hooks这些不在讨论中,后⽂会直接忽略。

b. git add:Git commit之前先要通过git add添加⽂件:

1655976714924

可以看到,多了⼀个index⽂件。并且在objects⽬录下多了⼀个9f的⽬录,其中多了⼀个

4d96d5b00d98959ea9960f069585ce42b1349a⽂件。

其实9f4d96d5b00d98959ea9960f069585ce42b1349a就是⼀个Git对象,称为blob对象。

c. git commit:

1655976729455