JAVA刷题专栏:http://t.csdnimg.cn/9qscL
目录
一、Springcloud的工作原理
三、注册中心心跳是几秒
四、消费者是如何发现服务提供者的
五、多个消费者调⽤用同⼀接口,eruka默认的分配⽅式是什么
六、springboot常用注解,及其实现
七、spring的事务注解是什么?什么情况下事物才会回滚
八、spring事物的传播性和隔离级别
九、mysql的引擎有什么?他们的区别
十、innodb如何实现mysql的事务
十一、mysql索引
十二、b+树的原理理
十三、如何设计索引
十四、git和svn的区别
十五、git命令的一些底层原理以及流程
一、Springcloud的工作原理
- Eureka:服务发现与注册组件,用于实现微服务架构中的服务注册与发现。
- Ribbon:负载均衡组件,通过在客户端进行负载均衡,实现服务间的负载均衡调用。
- Feign:声明式的HTTP客户端,简化了服务间的调用方式。
- Hystrix:容错管理组件,提供服务的容错保护,防止故障在整个系统中蔓延。
- Zuul:API网关组件,用于在微服务架构中提供路由和过滤的功能。
|
二、SpringCloud用什么组件发请求
在Spring Cloud中,发送HTTP请求通常使用以下两种方式:
1. RestTemplate: - Spring提供的一个同步的HTTP客户端,它简化了与http服务的通信,并满足REST原则。它可以与Ribbon一起使用来提供客户端级别的负载均衡。
2. OpenFeign(或Feign): - 是一个声明性的Web服务客户端,它让编写Web服务客户端变得更加简单易行。使用Feign的话,你只需要创建一个接口并用注解的方式配置它即可。
- 在这两种方式中,Feign的风格更为接近Spring MVC,因此在一定程度上可以减少很多原始的HTTP客户端代码,让服务间的调用更为优雅和易于维护。而RestTemplate更为灵活,适合于需要更多控制HTTP 请求细节的场景。随着Spring Cloud的发展,RestTemplate正逐步被Feign和
WebClient (Spring 5中的一个异步、非阻塞的HTTP客户端新工具)所取代。
|
RestTemplate示例代码:
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://example.com/resource", String.class);
OpenFeign(或Feign)示例代码:
@FeignClient("service-name")
public interface MyClient {@RequestMapping(method = RequestMethod.GET, value = "/resource")String getResource();
}
三、注册中心心跳是几秒
Spring Cloud中的注册中心,比如Eureka, 不是通过固定的“心跳(心眺)”时间来工作的,而是依赖于几个可配置的参数来协同工作,其中包含心跳间隔、实例注册后的续约(续租)时间间隔以及服务端的清理间隔。下面是有关Eureka客户端和服务端的一些默认值:
- eureka.instance.lease-renewal-interval-in-seconds:客户端向注册中心发送心跳的时间间隔,默认值是30秒。这意味着每隔30秒,客户端都会向Eureka服务器发送一次“我还活着”的信号。
- eureka.instance.lease-expiration-duration-in-seconds:Eureka服务器在没有接收到客户端的续约(心跳)后等待多久将服务实例从注册表中移除,默认值是90秒。
- eureka.server.eviction-interval-timer-in-ms:服务端执行清理任务的时间间隔,默认是60秒。这是Eureka服务端用来检查和删除过期服务的时间间隔。
|
四、消费者是如何发现服务提供者的
- 当⼀一个服务实例例启动,会将它的ip地址等信息注册到eureka;
- 当a服务调⽤用b服务,a服务会通过Ribbon检查本地是否有b服务实例例信息的缓存;
- Ribbon会定期从eureka刷新本地缓存。
|
五、多个消费者调⽤用同⼀接口,eruka默认的分配⽅式是什么
1. RoundRobinRule - 轮询策略略,Ribbon以轮询的⽅方式选择服务器器,这个是默认值。所以示例例中所启动的两个服务会被循环访问; b. RandomRule:随机选择,也就是说Ribbon会随机从服务器器列列表中选择⼀一个进⾏行行访问;
2. BestAvailableRule - 最⼤大可⽤用策略略,即先过滤出故障服务器器后,选择⼀一个当前并发请求数最⼩小的;
3. WeightedResponseTimeRule - 带有加权的轮询策略略,对各个服务器器响应时间进⾏行行加权处理理,然后在采⽤用轮询的⽅方式来获取相 应的服务器器;
4. AvailabilityFilteringRule - 可⽤用过滤策略略,先过滤出故障的或并发请求⼤大于阈值⼀一部分服务实例例,然后再以线性轮询的⽅方式从 过滤后的实例例清单中选出⼀一个;
5. ZoneAvoidanceRule - 区域感知策略略,先使⽤用主过滤条件(区域负载器器,选择最优区域)对所有实例例过滤并返回过滤后的实例例 清单,依次使⽤用次过滤条件列列表中的过滤条件对主过滤条件的结果进⾏行行过滤,判断最⼩小过滤数(默认1)和最⼩小过滤百分⽐比(默 认0),最后对满⾜足条件的服务器器则使⽤用RoundRobinRule(轮询⽅方式)选择⼀一个服务器器实例例。
|
六、springboot常用注解,及其实现
1. @Bean: 注册Bean - 默认使⽤方法名作为id,可以在后面定义id如@Bean("xx");
- 默认为单例
- 可以指定init方法和destroy方法:
- 对象创建和同仁完成,调用初始化方法
- 单实例bean在容器销毁的时候执行destroy方法
- 多实例bean,容器关闭是不会调用destroy方法
2. @Scope: Bean作用域 - 默认为单例
- 类型
- singleton单实例(默认值):ioc容器启动时会调用⽅法创建对象放到ioc容器器中,以后每次获取就是直接从容器中拿实例;
- prototype多实例:ioc容器启动不会创建对象,每次获取时才会调用方法创建实例;
- request同一次请求创建一个实例;
- session同一个session创建一个实例。
3. @Value: 给变量赋值 - @Value注解是一种常用的方式,用于将外部配置值注入到Spring管理的Beans中。这个注解可以用来引入普通字符串、系统属性、环境变量、配置文件中的属性等。
- 代码示例(在下面)
- 方式
- 基本数字
- 可以写SpEL(Spring EL表达式):#{}
- 可以写${},取出配置⽂文件中的值(在运行环境变量里面的值)
4. @Autowired: 自动装配 - 默认优先按照类型去容器中找对应的组件:BookService bookService = applicationContext.getBean(BookService.class);
- 默认一定要找到,如果没有找到则报错。可以使用@Autowired(required = false)标记bean为非必须的。
- 如果找到多个相同类型的组件,再根据属性名称去容器中查找。
- @Qualifier("bookDao2")明确的指定要装配的bean。
- @Primary:让spring默认装配⾸首选的bean,也可以使⽤用@Qualifier()指定要装配的bean。
5. @Profile: 环境标识 - Spring为我们提供的可以根据当前环境,动态的激活和切换一系列列组件的功能;
- @Profile指定组件在哪个环境才能被注册到容器中,默认为"default"@Profile("default")。
- 激活⽅方式:
- 运行时添加虚拟机参数:-Dspring.profiles.active=test
- 代码方式
|
3. @Value给变量赋值示例代码
@Component
public class SomeClass {// 注入application.properties或application.yml中的属性值@Value("${some.property.name}")private String propertyValue;// 注入系统属性的值@Value("${system.property}")private String systemProperty;// 注入环境变量的值@Value("${env.VARIABLE_NAME}")private String environmentVariable;// 给变量赋予一个默认值,如果配置没有这个值的话@Value("${some.property.name:defaultValue}")private String propertyWithDefaultValue;// ...
}
七、spring的事务注解是什么?什么情况下事物才会回滚
- spring事务实现机制:
- 事务注解@transactional;
- 默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务。
- @Transactional 只能应用到 public 方法才有效:只有@Transactional 注解应用到 public ⽅法,才能进行事务管理理。这是因为在使用 Spring AOP 代理时,Spring 在调用在图 1 中的 TransactionInterceptor 在⽬标⽅法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke ⽅法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取表 1. @Transactional 注解的事务属性配置属性信息) 的 computeTransactionAttribute ⽅法。
|
八、spring事物的传播性和隔离级别
七个事传播属性:
- PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
- PROPAGATION_SUPPORTS -- ⽀持当前事务,如果当前没有事务,就以非事务方式执⾏。
- PROPAGATION_MANDATORY -- ⽀持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATIONREQUIRESNEW -- 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATIONNOTSUPPORTED -- 以⾮事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER -- 以⾮事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATIONNESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与 PROPAGATIONREQUIRED类似的操作。
|
五个隔离级别:
- ISOLATION_DEFAULT:这是PlatfromTransactionManager的默认隔离级别,它使用数据库默认的事务隔离级别。
- ISOLATION_READ_UNCOMMITTED:这是事务的最低隔离级别。在这个级别下,一个事务可以读取到另一个事务未提交的数据。这种隔离级别可能会导致脏读、不可重复读和幻像读。
- ISOLATION_READ_COMMITTED:这个隔离级别保证了一个事务修改的数据只有在该事务提交后才能被其他事务读取。也就是说,其他事务不能读取该事务未提交的数据。这种隔离级别可以防止脏读,但可能会导致不可重复读和幻像读。
- ISOLATION_REPEATABLE_READ:这个隔离级别可以防止脏读和不可重复读。它保证了一个事务不能读取另一个事务未提交的数据,并且在同一个事务中,多次读取同一数据的结果是一致的。然而,这种隔离级别可能会导致幻像读。
- SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行,因此可以防止脏读、不可重复读和幻像读。
|
关键词:
九、mysql的引擎有什么?他们的区别
a. InnoDB: - ⽀持事务处理
- ⽀持外键
- ⽀持行锁
- 不不支持FULLTEXT类型的索引(在Mysql5.6已引入)
- 不保存表的具体行数,扫描表来计算有多少行
- 对于AUTO_INCREMENT类型的字段,必须包含只有该字段的索引
- DELETE 表时,是⼀⾏⼀行的删除
- InnoDB 把数据和索引存放在表空间⾥面
- 跨平台可直接拷贝使用
- 表格很难被压缩
b. MyISAM: - 不⽀支持事务,回滚将造成不不完全回滚,不不具有原⼦性
- 不支持外键
- ⽀持全⽂文搜索
- 保存表的具体行数,不带where时,直接返回保存的行数
- DELETE 表时,先drop表,然后重建表
- MyISAM 表被存放在三个文件 。frm ⽂件存放表格定义。 数据⽂文件是MYD (MYData) 。 索引文件是MYI (MYIndex)引伸
- 跨平台很难直接贝
- AUTO_INCREMENT类型字段可以和其他字段一起建⽴联合索引
- 表格可以被压缩
c. 选择: - 因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原子性要求低。那么MyISAM最好的选择。 且MyISAM恢复速度快。可直接⽤用备份覆盖恢复。如果系统读少,写多的时候,尤其是并发写⼊高的时候。InnoDB就是⾸选了。 两种类型都有⾃己优缺点,选择那个完全要看⾃己的实际情况。
|
十、innodb如何实现mysql的事务
- 事务进⾏过程中,每次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恢复数据。
|
十一、mysql索引
MySQL索引是数据库性能优化的重要方面,它们在数据量大的情况下能够极大地提高查询效率。以下是一些关于MySQL索引的关键点:
1. 索引的类型: - 单列索引:仅包含单个列的索引,适用于只涉及一个列的查询。
- 复合索引:包含两个或更多列的索引,适用于查询条件涉及多个列的情况。
- 唯一索引:保证索引列的每行数据都必须唯一。
- 主键索引:表中每行的唯一标识,是一种特殊的唯一索引。
- 全文索引:仅适用于MyISAM和InnoDB引擎(MySQL 5.6及以上版本),用于全文搜索。
- 空间索引:主要用于空间数据类型,如GIS数据。
2. 索引的原理: - 索引提高数据检索的效率,原理类似于书本的目录。MySQL中最常见的索引类型是B-Tree索引,适用于全值匹配、值的范围或值的前缀匹配。另一种主要索引类型是哈希索引,它适用于等值比较。
3. 索引的使用: - 查询优化器会根据查询语句和可用的索引来决定是否使用索引。可以通过EXPLAIN命令查看查询是否使用了索引。
4. 索引的创建和管理: - 在创建索引时,可以选择相应的字段和索引类型。但创建索引是有代价的,它会增加磁盘空间的使用,并且在插入、更新和删除数据时可能会降低性能,因为索引也需要维护。
5. 索引的建议: - 不要在数据变化很频繁的列上创建索引。
- 对于查询中经常出现的列或条件,应考虑创建索引。
- 复合索引应根据查询的WHERE子句和JOIN的顺序来确定列的顺序。
- 索引的选择性(不重复值的数量与总行数的比例)越高,索引的效果越好。
- 尽量使用覆盖索引(查询列直接在索引中),这样可以避免回表查询提高效率。
6. 索引的陷阱: 使用索引并不总是提升性能。在以下情况中,MySQL可能不会使用索引: - 使用LIKE操作符以通配符开头的字符串(如'%abc')。
- 如果MySQL估计需要扫描的表行数超过总行数的一定比例,它可能认为顺序扫描整个表更快。
- 数据类型不一致时(例如,在字符串列上的数字比较时,需要类型转换)。
- 在索引列上使用函数或表达式(这会使得MySQL无法利用索引)。
|
十二、b+树的原理理
b-tree
- B-tree 利用了磁盘块的特性进行构建的树。每个磁盘块一个节点,每个节点包含了很关键字。把树的节点关键字增多后树的层级比原来的二叉树少了,减少数据查找的次数和复杂度。
- B-tree巧妙利利⽤了磁盘预读原理理,将一个节点的⼤小设为等于一个页(每页为4K),这样每个节点只需要一次I/O就可以全载入。
- B-tree 的数据可以存在任何节点中。
|
b+tree
- B+tree 是 B-tree 的变种,B+tree 数据只存储在叶⼦节点中。这样在B树的基础上每个节点存储的关键字数更多,树的层级更少 所以查询数据更快,所有指关键字指针都存在叶子节点,所以每次查找的次数都相同所以查询速度更稳定;
|
十三、如何设计索引
设计MySQL索引需要认真考虑查询模式、数据特性和业务需求。以下是设计MySQL索引的步骤:
1. 理解业务逻辑: - 首先,理解应用的业务逻辑和查询需求是设计索引的前提。这包括了解那些查询频率高,哪些数据经常一起查询,以及哪些操作的性能是关键。
2. 分析查询语句: - 收集和分析最常用的查询语句,尤其是SELECT、UPDATE和DELETE语句。理解哪些列被用作WHERE子句、JOIN条件、ORDER BY或GROUP BY子句,这些列是创建索引的重要候选。
3. 考虑数据的选择性: - 选择性指的是字段值的唯一程度。高选择性的字段(即有很多唯一值)是索引的良好候选,因为它们可以更有效地过滤数据。
4. 选择索引类型: - 根据数据类型和查询模式选择合适的索引类型。例如,对于全文搜索,使用全文索引;对于地理空间数据,使用空间索引。
5. 考虑创建复合索引: - 当查询条件涉及多个列时,考虑创建复合索引。复合索引的列顺序十分重要,通常应将选择性最高的列放在最前面。
6. 留意列的数据类型: - 使索引列尽可能紧凑,这通常意味着使用更小的数据类型,比如INT而不是BIGINT,如果可能的话。
7. 避免冗余和无用的索引: - 创建索引时要避免冗余,不要为表中的每一列都创建索引。同样,定期审查并移除不再使用的索引,避免浪费空间和减慢写操作。
8. 使用数据库工具和命令: - 利用
EXPLAIN 命令或其他优化器工具分析查询语句的执行计划以确认索引的效果。
|
十四、git和svn的区别
Git和SVN(Apache Subversion)都是版本控制系统,它们用于追踪源代码的变更历史。尽管他们的目标相同,但是它们在设计原理、特性和使用方式上有很多不同。
1. 分布式与集中式: - Git 是一个分布式版本控制系统(DVCS)。意味着每个开发人员的本地副本都是仓库的完整副本,包括所有的历史记录。这样,开发者可以在本地执行许多操作,如提交、分支、查看历史等,而无需网络连接。
- SVN 是一个集中式版本控制系统(CVCS)。所有的文件和历史记录存储在中央服务器上。当开发人员想要提交或获取最新的更改时,他们需要连接到这个服务器。开发者在本地只有工作副本,并不包括项目的完整历史。
2. 支持离线工作: - 由于Git是分布式的,开发者可以在离线时完成许多版本控制任务。
- SVN则需要与中央服务器通讯进行大多数操作,这在离线时往往不可能。
3. 网络需求与性能: - Git 的大部分操作都在本地完成,因此通常比SVN更快,特别是在提交上。而且,Git只需要同步更改,所以在克隆或推送到远程时通常需要的带宽更少。
- SVN 操作,尤其是提交更改,需要与服务器通信。这可能会慢一些,特别是对于带宽受限或网络延迟较大的用户。
4. 分支和合并: - Git 对分支和合并的支持更先进,分支操作非常快速且是轻量级的,因为Git会处理整个项目的快照。
- SVN 的分支是通过在服务器上复制整个项目来实现的,这可以更加消耗时间和空间。虽然SVN在新版本中改进了分支和合并的处理,但它在简单性和性能方面与Git相比仍有所不足。
5. 存储方式: - Git 使用内容寻址文件存储和SHA-1哈希来保证数据的完整性和一致性。
- SVN 采用一种类似文件系统的方法保存数据,并在每次提交时增加修订版号。
6. 数据安全和完整性: - Git 极其注重数据的安全和完整性。每次提交都有相应的校验和,而且如果数据发生丝毫改变,就能通过校验值立即发现。
- SVN 存储数据安全也很重视,但由于集中式存储的设计,如果中央服务器出现问题,可能会存在单点故障的风险。
7. 学习曲线: - Git 功能强大,但有时被认为学习曲线较陡峭,因为它提供了更多的命令和操作选项。
- SVN 的概念和日常使用相对简单直接,对于不熟悉分布式版本控制的用户来说,可能更容易上手。
8. 可移植性和权限管理: - Git 由于是分布式的,可以很容易地复制/克隆整个仓库。而SVN则需要导出或备份特定的文件和元数据。
- SVN 提供了内置的访问控制列表(ACL)来更细粒度地设置权限,而在Git中,这通常通过第三方工具或层次进行管理。
|
十五、git命令的一些底层原理以及流程
Git 工作流程
Git的工作流程大致可以分为以下几个步骤: - 工作区(Working Directory):进行文件的修改。
- 暂存区(Staging Area/Index):将需要提交的更改添加到暂存区。
- 仓库(Repository/History):提交更新到本地仓库的历史记录中。
- 远程仓库(Remote Repository):将本地仓库的更改推送到远程仓库。
|
Git 底层原理
1. 对象存储: Git的核心是一个简单的键值对存储。你可以向Git仓库插入任何类型的内容,它会返回一个唯一的键,该键可以在之后用来再次取出该内容。这种存储系统建立在几种对象之上: - Blob:存储文件数据,不包含文件名信息或结构。
- Tree:类似于目录,包含文件名并指向Blob对象(或其他Tree),它可以构建出目录层次结构。
- Commit:指向某一特定项目快照的Tree对象。它包含作者信息、提交信息和指向前一次提交(父提交)的指针。
- Tag:用于标记特定的提交,比如为项目的版本发布打标签。
2. 索引: - 借助索引文件(index),Git暂存操作的信息都会在这个文件中被记录。索引文件包含了工作目录内容的快照,以及下一个提交时的内容。
3. 引用: - 引用或“ref”是指向数据(通常是一个commit对象)的指针。本地分支、远程分支、标签都是引用。
4. HEAD: - HEAD是一个指针,指向当前分支的最新提交,它代表工作目录的最新快照。在每次提交时,它会随着新的提交而更新。
|
Git 命令流程
一个简单的流程,以展示文件从工作区到暂存区再到存储库的过程是这样的: - 修改文件:
你在工作目录中修改文件。 - 暂存文件:
使用 git add <file> 将文件更改添加到暂存区。这实际上将文件快照放在暂存区等待提交。 - 提交更新:
使用 git commit -m "Your commit message" 将暂存区中的快照提交到本地仓库。Git此时会创建一个新的提交对象,指向暂存区的快照,并将HEAD指针指向这个新的提交。 - 推送到远程仓库:
使用 git push 命令将本地仓库的更改发送到远程仓库。这会同步你的本地提交到远程仓库。
|
Git 分支和合并的原理
- 从原理上说,当你在Git中创建分支时,Git创建了一个新的可移动的指针。当你提交时,分支指针(即HEAD指针)会随着每次提交向前移动。当合并两个分支时,Git会尝试自动合并更改。如果有冲突,Git会停止合并并要求你解决这些冲突。合并完成后,会创建一个新的commit对象,指向两个父提交——一个是合并的分支的最后提交,另一个是当前分支在合并前的最后提交。
- Git的最重要的特征之一就是几乎所有的操作都是本地进行的,绝大多数命令都不需要网络连接到远程服务器。Git的速度之快和对离线操作的支持也是基于这一特性。
|