南猫猫猫猫猫

导航

知识

RocketMQ
消息队列是一种先进先出的数据结构,它是异步调用,分布式架构
MQ的主要作用
1.解耦(高内聚,低耦合)
2.消峰限流
3.数据分发(异步)
MQ的缺点
1.系统可用性降低
2.系统复杂度提高了
3.一致性问题
数据的传递 我们把数据传到消息队列,消费者可以在消费队列里直接获取数据
创建消息,指定Topic.Tag.消息体
1基本的消息通知
2.异步通知
3.消费消息 日志使用,这个不在乎发送结果
4.延时消息
5.批量消息

MQ的执行流程
Name Server: 名称服务充当路由消息的提供者,两个功能:接收broker的请求,注册broker的路由信息,接收client(producer/consumer)的请求,根据某个topic获取其到broker的路由信息NameServer没有状态,可以横向扩展。每个broker在启动的时候会到NameServer注册;Producer在发送消息前会根据topic到NameServer获取路由(到broker)信息;Consumer也会定时获取topic路由信息。

Broker:消息中转角色,负责存储消息,转发消息。可以理解为消息队列服务器,提供了消息的接收、存储、拉取和转发服务。broker是RocketMQ的核心,它不不能挂的,所以需要保证broker的高可用。
broker分为 Master Broker 和 Slave Broker,一个 Master Broker 可以对应多个 Slave Broker,但是一个 Slave Broker 只能对应一个 Master Broker。
Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。
每个Broker与Name Server集群中的所有节点建立长连接,定时注册Topic信息到所有Name Server。Broker 启动后需要完成一次将自己注册至 Name Server 的操作;随后每隔 30s 定期向 Name Server 上报 Topic 路由信息。

生产者:与 Name Server 集群中的其中一个节点(随机)建立长链接(Keep-alive),定期从 Name Server 读取 Topic 路由信息,并向提供 Topic 服务的 Master Broker 建立长链接,且定时向 Master Broker 发送心跳。

消费者:与 Name Server 集群中的其中一个节点(随机)建立长连接,定期从 Name Server 拉取 Topic 路由信息,并向提供 Topic 服务的 Master Broker、Slave Broker 建立长连接,且定时向 Master Broker、Slave Broker 发送心跳。Consumer 既可以从 Master Broker 订阅消息,也可以从 Slave Broker 订阅消息,订阅规则由 Broker 配置决定。

WebSocket
服务端(后台)
后台基本上就是配置好用户名密码,url,
这里要和前端定义好,传什么是什么意思?
然后写个工具类调用就行,把要传递的消息放进去。
客户端(前台)
在组件加载时,加载客户端
1.判断浏览器支持websocket,
建立连接,做一些错误处理,还有收到消息的回调方法,对窗口的监听,还有关闭websocket连接
2还有就是对消息的获取
准备:加载maven依赖
定时器
1.在这个类上面加上@EnableScheduling
然后在需要的方法上面加上注解@Scheduled 添加定时任务 (coon表达式)
秒 分 时 日 月 星期
2. 我们使用的是把定时任务写在数据库中,然后在执行定时任务之后,他会查询一次数据库,确定下一次的定时任务开始时间?他可以循环读取数据库中的执行周期,还有要执行什么任务
具体执行的话就是有一个SecheduledTaskReistrar通过这个实现动态的定时任务注册
任务的执行线程
Trigger 任务触发器
通过CornTrigger来获取数据库记录,更新触发器,返回下一次的执行时间
然后把新的任务注册到定时任务里
Springcloud
一、Eureka 相当于zookeeper 服务的注册与发现
他有服务端和客户端
客户端: 我们每一个服务上面都有Eureka客户端。然后把我们的服务相关信息注册到eureka服务端上(有单独的服务端)(包括机器地址和端口号)
服务端:相当于注册中心。里面有注册表,保存机器地址,所以不同客户端之间通过服务端调用
二、Feign (类似于dubbo)
这个主要是用来操作一个服务调用另一个服务的
这个过程中,被调用方就是消费者端
实现起来也比较简单,加注解在消费端,直接调用就可以,然后feign底层会根据注解和指定的服务建立连接,发起请求获取响应还有解析,这些都是由feign来完成的
实现原理(运用了动态代理)
1.我们对一个接口定义了FeignClient注解,那么feign就对这个接口创建了动态代理,
2然后这个动态代理会根据@RequestMapping注解,来动态构造请求的服务地址
3.然后就是请求这个地址,解析响应
三、Ribben
主要作用就是负载均衡,默认就是轮询
他会从Eureka里面获取到注册列表,然后找到服务位置,根据负载均衡的算法来请求服务
四、hystrix
主要是用来做熔断,隔离,限流,还有服务降级
线上环境会有这种情况,有个服务卡了,超时了,或者挂了,其他服务的很多线程调用这个服务就会出错,这样就导致整个系统没有一个多余线程处理请求,这个就是雪崩现象,服务之间的调用不做保护和隔离的话,很可能一个服务挂掉就会产生连锁反应,导致别的服务挂掉
这样的情况下就需要给服务间调用做处理,于是有了hystrix,他会搞很多小线程池,然后让这些小线程来请求服务,返回结果,他就相当于中间的过滤区,如果服务挂了,那么就不会在那里继续等待,而是直接返回了。(当然这里的返回他会记录哪些服务没有执行,哪些值没有记录!!!有个故障数据库)
五、Zuul网关(相当于nginx)
我们不必去记录数据库的地址,和服务名称,我们直接调用Zuul然后网关会根据请求,分发到不同服务------------
Spring
Aop
以切入的方式将业务逻辑功能应用到每一层结构中(可以理解为类方法,类方法也是一种对象的行为实现)
主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理,将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。解决代码复用问题
IoC控制反转
就是由spring来负责控制对象的生命周期和对象间的关系
所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制
bean注入的方式
annotation注解装配
XML
构造函数的参数来自动装配
不常用
autodetect模式
no模式它属于不使用自动装配
数据库
表设计(三大范式)
1nf 字段都是不可再分的原子值,属性具有原子性,不能再分解。主要是为了查询的速度,比如一个存着全部详细地址,然后有个查询是要查北京的,那么我们把城市取出来,这样我们会查的更快
2nf 在第一范式前提下,除主键外的每一列都必须完全依赖于主键 (claimid)如果不是完全依赖主键,就用联合索引(比如案件号和结案id)
3nf 在二的前提下除开主键的其他列之间不能传递依赖 a-b b-c a-c 这个只能通过主键来相互关联 如果有多的那么大概率是冗余字段
但是我们在实际工作中不必完全遵守第三范式,为了提高查询效率,适当留下冗余字段也是可以的
数据库链接
1.注册驱动 class.forName()
2.获取数据库连接 DriverManager.connection
3.创建statement语句对象
4.执行sql 用上面的对象执行sql语句 executequary
5.处理返回结果 ResultSet方法 对游标进行操作
6.关闭链接 释放资源
Redis
Redis锁和zk锁
set key
成功返回1
失败返回0
核心就是解决资源竞争问题,找一个公共的东西,然后把能访问住这个东西的线程限制住
redission 开源中间件
主要用他的锁
直接在需要的地方加锁,结束时候减锁
还可以设置过期时间,续命
看门狗
redis 执行完之后,剩下所有线程抢锁,可能一个刚来的就抢到了锁,所有线程抢锁几率是一样的
Zk锁
每个线程一个子结点,在系统里可以看到,有001.002.003.....可以按请求顺序执行,有个排队的机制,watcher一个节点结束之后销毁结点,然后通知下一个,号最小的,执行下一个节点
zk性能比redis锁性能慢
一个内存操作,一个需要创建结点,然后用完删除,慢在这里
每个线程一个子结点,在系统里可以看到,有001.002.003.....可以按请求顺序执行,有个排队的机制,watcher一个节点结束之后销毁结点,然后通知下一个,号最小的,执行下一个节点
zk性能比redis锁性能慢
一个内存操作,一个需要创建结点,然后用完删除,慢在这里

Redis的持久化机制
RDB,AOF,混合式。RDB是快照文件,反映的是Redis在某一时刻的数据状态,缺点是当数据继续变化时,RDB无法持久化新的数据变化。AOF记录的是所有的操作日志,当从AOF持久化文件中恢复数据到REDIS时,会依次执行所有日志记录,但是缺点是多条hset或者set记录仅有最后一条能反映最终状态,因此中间状态有浪费内存之嫌,当然可以通过设置rewrite的阀值,压缩多余的中间状态记录。最后是混合式,从redis4.x引入,是比较推荐的持久化方法,先用RDB记录当前快照,再用AOF记录追加的数据变化
缓存和数据库不一致
1.像读多写稀有的,用分布式事物解决
2.先写数据库,再更新redis ①数据会有时差,②redis出问题导致数据没更新到缓存 这个用canal来完成(mysql有主从同步,他们同步的是binlog,这里canal模拟出一个同步,把binlog同步到redis)
3.也可以用mq先处理,请求过来走mq,然后mq发消息给接收消息的
①redis是缓存,更倾向于稍微有时差
②减少db操作
③真要落地,可以用canal
redis主从不一致
1.redis默认是弱一致性,他的主从是异步的同步,肯定会有主从不一致情况
2.用分布式锁的话不能用主从集群(要用单实例/分片集群/redlock)所以 直接用redisson就行了
3.在配置中提供了必须有多少个client连接能同步,可以手动配置同步因子,这样趋向于强一致性
redis持久化
1.单机的话是aof rdb 再加上主从同步,其实开了主从复制aof和rdb不用都可以
2. 高版本中aof是将命令写到日志文件中,但是他这样会消耗机器性能,写一条日志中加一条命令,也会让文件越来越大,这就有个重写的步骤了,把指令压缩,重复的数据过滤掉,只留下生成指令
3. redis4版本之后多了混合持久化,之前生成指令过程太复杂了,把之前的重写步骤变成了直接用rdb放到aof文件头部,所以现在就是rdb+aof ,提高了性能
setnx(待补充)
1.原子性操作(不存在的情况下完成了创建)
2如果做分布式锁 就用set k v nx ex(注意过期时间和避免死锁)

缓存穿透、缓存击穿、缓存雪崩的解决方案
缓存穿透
指查询一个一定不存在的数据,如果从存储层查不到 数据则不写入缓存,这将导致这个不存在的数据每次请求都要到DB去查询,可能导致DB挂掉。要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。
解决方案:
查询返回的数据为空,人把这个空结果进行缓存,但过期的时间会比较短
布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被子这个bitmap拦截掉,从而避免了对DB的查询

缓存击穿
对于设置了过期时间的 key,缓存在某个时间点过期的时候,恰好这时间点对这个 Key 有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把 DB 压垮。
解决方案:
使用互斥锁:当缓存失效时,不立即去 load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db 的操作并回设缓存,否则重试 get 缓存的方法。
永远不过期:物理不过期,但逻辑过期(后台异步线程去刷新)
缓存雪崩
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。与缓存击穿的区别:雪崩是很多 key,击穿是某一个key 缓存。
解决方案:
缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就时将缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

redis为啥这么快
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
使用多路 I/O 复用模型,非阻塞 IO;
使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

redis过期策略?
定期删除+惰性删除。
定期删除:每隔一段时间删除
惰性删除:获取的时候判断是否过期

Redis 怎么保证高可用、有哪些集群模式?
主从,哨兵,集群
1.主从复制
1.开启配置
在 slave 直接执行命令:slaveof
在 slave 配置文件中加入:slaveof
使用启动命令:--slaveof
2.建立套接字(socket)连接 3.发送PING命令 4.身份验证 5.发送CAPA(同步复制的能力)6.数据同步 7.命令传播出现故障需要手动更改配置

2.哨兵
哨兵(Sentinel) 是 Redis 的高可用性解决方案,由多个哨兵监控主服务器。监控的主服务器故障的时候,可以将从服务器升级为主服务器

3.集群
哨兵模式的缺点就是所有的数据都放在一台服务器上,无法比较好的进行水平扩展。
集群模式:
去中心化,将数据按槽存储分布在多个 Redis 节点上。集群共有 16384 个槽,每个节点负责处理部分槽。
所有的 Redis 节点彼此互联,通过 PING-PONG 机制来进行节点间的心跳检测。
主节点故障时,从节点向所有有投票的主节点发起选举,获得票数>2n+1则升级为主节点.

单例多例
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例)
singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。 结论:二个变量指向一个对象
prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new 结论:每次访问bean,均创建一个新实例
Mysql
映射 id
设置别名,返回列的别名和Model中的属性一致,所以可以映射。

MybatisPlus 为什么用 和mysql什么区别
Nacos 怎么样配置自动刷新
Refresh-enable : true
读取配置文件的类上,需加上@RefreshScope注解
何为悲观锁、乐观锁
1、悲观锁
顾名思义,就是比较悲观的锁,总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
2、乐观锁
反之,总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
二、悲观锁和乐观锁应用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
Linux查询日志命令 tail –f cat less vim
微服务和集群区别
分布式事物
项目介绍
shell脚本定时删除数据
查询日志命令
微服务和集群区别
微服务 服务之间是隔离的,不同模块之间的升级和bug不会影响到其他模块 他不一定分散在多个服务器上,也可能在同一个服务器
集群 多台的服务器部署相同的应用,对外提供访问,他的重点是多台服务器业务相同
分布式事物
一次大的操由不同的小操作组成,他们分布在不同服务器上,而且属于不同应用,分布式事物保证的是这些事物要么都成功要么都失败,从本质上说,就是为了保证不同数据库的数据一致性
跨服务的事物(回滚)
能不能手写单例模式 怎么保证单例不被其他人(使用?修改)
mysql查询第二页的语句
分组查询 以名称分组,分组>80的
string如果去掉final能不能快(底层)
字符串的数组,新增的话,快不快
stringbuilder为什么快(底层)
mongodb作用
悲观锁乐观锁
怎么用悲观锁实现行锁(手写)
redis 怎么用的
为什么这么快
亿级表怎么设计??? 分库分表怎么做???
分库分表 分为垂直拆分和水平拆分。
水平拆分 就是从业务字段里面选一个拆分阶段,然后在写的时候根据这个字段生成分表的编号,读的时候也根据这个查询条件去哪个表里边查询。
当查询字段没有分表字段时候,可以建立一个索引表,只存储分表字段和查询字段的映射关系。然后根据其他字段查到对应的分表字段。再去相应的分表查询。
冷热数据 热数据是变更比较频繁的数据,冷数据是全量数据,分别保存 然后热数据的话是定时的清理。 就像我们的所有的案件有上亿条。我们一般只会查看最近的案件,所以直接查询热库就好了。冷库的话可以选择es或者hive

Sql优化
尽量避免使用子查询,避免函数索引,用IN来替换OR,
LIKE前缀%号、双百分号、_下划线查询非索引列或*无法使用到索引,如果查询的是索引列则可以
读取适当的记录LIMIT M,N,而不要读多余的记录
避免数据类型不一致,避免随机取记录,禁止不必要的ORDER BY排序
分组统计可以禁止排序sort,总和查询可以禁止排重用union all
批量INSERT插入,不要使用NOT等负向查询条件,尽量不用select *,优化Group By语句

Join语句的优化
避免索引失效
1.最佳左前缀法则如果索引了多列,要遵守最左前缀法则,查询从索引的最左前列开始并且不跳过索引中的列。
2.不在索引列上做任何操作计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。
3.存储引擎不能使用索引中范围条件右边的列。
4.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致))
5.mysql在使用不等于(!= 或者 <>)的时候无法使用索引会导致全表扫描。
6.is null, is not null 也无法使用索引,在实际中尽量不要使用null。
7.like 以通配符开头(‘%abc..’)mysql索引失效会变成全表扫描的操作。
所以最好用右边like 'abc%'。如果两边都要用,可以用select age from user where username like '%abc%',其中age是必须是索引列,才可让索引生效
假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用,类似于不能使用范围条件右边的列的索引
8.字符串不加单引号索引失效
9.少用or,用它来连接时会索引失效
10.尽量避免子查询,而用join
11、在组合索引中,将有区分度的索引放在前面
如果没有区分度,例如用性别,相当于把整个大表分成两部分,查找数据还是需要遍历半个表才能找到,使得索引失去了意义。
避免在 where 子句中对字段进行 null 值判断

String、StringBuffer、StringBuilder的区别
这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面。
从运行速度、执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多

再来说线程安全
  在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
  如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
(一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞)
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

总结:平时使用时优先使用stringBuilder ,
如果有并发要求,线程安全要求,用stringBuffer
如果这个字符串不经常修改,用string

1、哪些情况下的对象会被垃圾回收机制处理掉?
利用可达性分析算法,虚拟机会将一些对象定义为 GC Roots,从 GC Roots 出发沿着引用链
向下寻找,如果某个对象不能通过 GC Roots 寻找到,虚拟机就认为该对象可以被回收掉。
1.1 哪些对象可以被看做是 GC Roots 呢?
1)虚拟机栈(栈帧中的本地变量表)中引用的对象;
2)方法区中的类静态属性引用的对象,常量引用的对象;
3)本地方法栈中 JNI(Native 方法)引用的对象;

1.2 对象不可达,一定会被垃圾收集器回收么?
即使不可达,对象也不一定会被垃圾收集器回收,1)先判断对象是否有必要执行 finalize()方法,对象必须重写 finalize()方法且没有被运行过。2)若有必要执行,会把对象放到一个队列中,JVM 会开一个线程去回收它们,这是对象最后一次可以逃逸清理的机会。

8、Java 中实现多态的机制是什么?
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译时不确定,在运行期间才确定,一个引用变量到底会指向哪个类的实例。这样就可以不用修改源程序,就可以让引用变量绑定到各种不同的类实现上。
Java 实现多态有三个必要条件:
继承、重定、向上转型,在多态中需要将子类的引用赋值给父类对象,只有这样该引用才能够具备调用父类方法和子类的方法。

14、String 为什么要设计成不可变的?
1)字符串常量池需要 String 不可变。因为 String 设计成不可变,当创建一个 String 对象时,若此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。 如果字符串变量允许必变,会导致各种逻辑错误,如改变一个对象会影响到另一个独立对象。
2)String 对象可以缓存 hashCode。字符串的不可变性保证了 hash 码的唯一性,因此可以缓存 String 的 hashCode,这样不用每次去重新计算哈希码。在进行字符串比较时,可以直接比较 hashCode,提高了比较性能;
3)安全性。String 被许多 java 类用来当作参数,如 url 地址,文件 path 路径,反射机制所需的 Strign 参数等,若 String 可变,将会引起各种安全隐患。

HTTP 和 https 区别?

  1. HTTP 明文传输,数据都是未加密的,安全性较差,HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好。
  2. 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。
  3. HTTP 页面响应速度比 HTTPS 快,主要是因为 HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包,而 HTTPS 除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包。
  4. http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
  5. HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS比 HTTP 要更耗费服务器资源。

红黑树原理?
(1) 红黑树的性质:红黑树是一个二叉搜索树。在每个节点增加了一个存储位记录节点
的颜色,可以是 RED,也可以是 BLACK,通过任意一条从根到叶子简单路径上颜色
的约束,红黑树保证最长路径不超过最短路径的两倍,加以平衡。性质如下:
i. 每个节点颜色不是黑色就是红色
ii. 根节点的颜色是黑色的
iii. 如果一个节点是红色,那么他的两个子节点就是黑色的,没有持续的红节点
iv. 对于每个节点,从该节点到其后代叶节点的简单路径上,均包含相同数目的黑色节点。

BeanFactory 和 ApplicationContext 有什么区别
BeanFactory 可以理解为含有 bean 集合的工厂类。BeanFactory 包含了种 bean 的定义,以便在接收到客户端请求时将对应的 bean 实例化。
BeanFactory 还能在实例化对象的时生成协作类之间的关系。此举将 bean 自身与 bean 客户端的配置中解放出来。BeanFactory 还包含了 bean 生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。
从表面上看,application context 如同 bean factory 一样具有 bean 定义、bean 关联关系的设置,根据请求分发 bean 的功能。但 application context 在此基础上还提供了其他的功能。
提供了支持国际化的文本消息
统一的资源文件读取方式
已在监听器中注册的 bean 的事件

Spring Bean 的生命周期
Spring Bean 的生命周期简单易懂。在一个 bean 实例被初始化时,需要执行一系列的初始化操作以达到可用的状态。同样的,当一个 bean 不在被调用时需要进行相关的析构操
作,并从 bean 容器中移除。
Spring bean factory 负责管理在 spring 容器中被创建的 bean 的生命周期。Bean 的生命周期由两组回调(call back)方法组成。
初始化之后调用的回调方法。
销毁之前调用的回调方法。
Spring 框架提供了以下四种方式来管理 bean 的生命周期事件:
InitializingBean 和 DisposableBean 回调接口
针对特殊行为的其他 Aware 接口
Bean 配置文件中的 Custom init()方法和 destroy()方法
@PostConstruct 和@PreDestroy 注解方式

Spring IOC 如何实现
Spring 中的 org.springframework.beans 包和 org.springframework.context 包构成了 Spring 框架 IoC 容器的基础。BeanFactory 接口提供了一个先进的配置机制,使得任何类型的对象的配置成为可能。ApplicationContex 接口对 BeanFactory(是一个子接口)进行了扩展,在 BeanFactory 的基础上添加了其他功能,比如与 Spring 的 AOP 更容易集成,也提供了处理 messageresource 的机制(用于国际化)、事件传播以及应用层的特别配置,比如针对 Web 应用的WebApplicationContextorg.springframework.beans.factory.BeanFactory 是 Spring IoC 容器的具体实现,用来包装和管理前面提到的各种 bean。BeanFactory 接口是 Spring IoC 容器的核心接口。

说说 Spring AOP
面向切面编程,在我们的应用中,经常需要做一些事情,但是这些事情与核心业务无 关,比如,要记录所有 update方法的执行时间时间,操作人等等信息,记录到日志,
通过 spring 的 AOP 技术,就可以在不修改 update
的代码的情况下完成该需求。

Spring AOP 实现原理
Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类。
如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,
那么它是无法使用 CGLIB 做动态代理的。

动态代理(cglib 与 JDK)
JDK 动态代理类和委托类需要都实现同一个接口。也就是说只有实现了某个接口的类可以使用 Java 动态代理机制。但是,事实上使用中并不是遇到的所有类都会给你实现一个接
口。因此,对于没有实现接口的类,就不能使用该机制。而 CGLIB 则可以实现对类的动态
代理。

Spring 事务实现方式
1、编码方式
所谓编程式事务指的是通过编码方式实现事务,即类似于 JDBC 编程实现事务管理。
2、声明式事务管理方式
声明式事务管理又有两种实现方式:基于 xml 配置文件的方式;另一个实在业务方法上进行@Transaction 注解,将事务规则应用到业务逻辑中

Spring 事务底层原理
a、划分处理单元——IOC由于 spring 解决的问题是对单个数据库进行局部事务处理的,具体的实现首相用 spring中的 IOC 划分了事务处理单元。并且将对事务的各种配置放到了 ioc 容器中(设置事务管理器,设置事务的传播特性及隔离机制)。
b、AOP 拦截需要进行事务处理的类Spring 事务处理模块是通过 AOP 功能来实现声明式事务处理的,具体操作(比如事务实行的配置和读取,事务对象的抽象),用 TransactionProxyFactoryBean 接口来使用 AOP功能,生成 proxy 代理对象,通过 TransactionInterceptor 完成对代理方法的拦截,将事务处理的功能编织到拦截的方法中。读取 ioc 容器事务配置属性,转化为 spring 事务处理需要的内部数据结构(TransactionAttributeSourceAdvisor),转化为TransactionAttribute 表示的数据对象。
c、对事物处理实现(事务的生成、提交、回滚、挂起)spring 委托给具体的事务处理器实现。实现了一个抽象和适配。适配的具体事务处理器:DataSource 数据源支持、hibernate 数据源事务处理支持、JDO 数据源事务处理支持,JPA、JTA 数据源事务处理支持。这些支持都是通过设计PlatformTransactionManager、AbstractPlatforTransaction 一系列事务处理的支持。为常用数据源支持提供了一系列的 TransactionManager。
d、结合PlatformTransactionManager 实现了 TransactionInterception 接口,让其与TransactionProxyFactoryBean 结合起来,形成一个 Spring 声明式事务处理的设计体系。如何自定义注解实现功能创建自定义注解和创建一个接口相似,但是注解的 interface 关键字需要以@符号开头。 注解方法不能带有参数;注解方法返回值类型限定为:基本类型、String、Enums、Annotation 或者是这些类型的数组;注解方法可以有默认值;注解本身能够包含元注解,元注解被用来注解其它注解。

Spring MVC 运行流程
1.spring mvc 将所有的请求都提交给 DispatcherServlet,它会委托应用系统的其他模块
负责对请求 进行真正的处理工作。
2.DispatcherServlet 查询一个或多个 HandlerMapping,找到处理请求的 Controller.
3.DispatcherServlet 请请求提交到目标 Controller
4.Controller 进行业务逻辑处理后,会返回一个 ModelAndView
5.Dispathcher 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 对象指定
的视图对象
6.视图对象负责渲染返回给客户端。

Spring MVC 启动流程
在 web.xml 文件中给 Spring MVC 的 Servlet 配置了 load-on-startup,所以程序启动的时候会初始化 Spring MVC,在 HttpServletBean 中将配置的 contextConfigLocation
属性设置到 Servlet 中,然后在 FrameworkServlet 中创建WebApplicationContext,
DispatcherServlet 根据 contextConfigLocation 配置的 classpath 下的 xml 文件初始化了Spring MVC 总的组件。

Spring 的单例实现原理
Spring 对 Bean 实例的创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是ConcurrentHashMap 对象。

Spring 框架中用到了哪些设计模式

代理模式—在 AOP 和 remoting 中被用的比较多。
单例模式—在 spring 配置文件中定义的 bean 默认为单例模式。
模板方法—用来解决代码重复的问题。比如. RestTemplate, JmsTemplate,
JpaTemplate。
前端控制器—Spring 提供了 DispatcherServlet 来对请求进行分发。
视图帮助(View Helper )—Spring 提供了一系列的 JSP 标签,高效宏来辅助将分散的代码
整合在视图里。
依赖注入—贯穿于 BeanFactory / ApplicationContext 接口的核心理念。
工厂模式—BeanFactory 用来创建对象的实例。

mysql 数据库中,什么情况下设置了索引但无法使用?
(1) 索引的作用:在数据库表中对字段建立索引可以大大提高查询速度。
(2) Mysql 索引类型:
a) 普通索引
b) 唯一索引:唯一索引列的值必须唯一允许有空值,如果是组合索
引,则列值的组合必须唯一:
c) 主键索引:一种特殊的唯一索引,不允许有空值,一般在创建表
的时候创建主键索引:
d) 组合索引:
为了进一步榨取 MySQL 的效率,就要考虑建立组合索引。就是
将 name, city, age 建到一个索引里:代码如下:
ALTER TABLE mytable ADD INDEX name_city_age
(name(10),city,age);
(3) 什么情况下有索引,但用不上?
a) 如果条件中有 OR,即使其中有部分条件带索引也不会使用。注
意:要想使用 or,又想让索引生效,只能将 or 条件中的每个列
都加上索引。
b) 对于多了索引,不是使用的第一部分,则不会使用索引。
c) Like 查询以%开头,不使用索引
d) 存在索引列的数据类型隐形转换,则用不上索引,比如列类型是
字符串,那一定要在条件中将数据使用引号引用起来,否则不使
用索引
e) Where 子句里对索引列上有数学运算,用不上索引
f)
Where 子句中对索引列使用函数,用不上索引
g) Mysql 估计使用全表扫描要比用索引快,不使用索引
(4) 什么情况下不推荐使用索引?
a) 数据唯一性差的字段不要使用索引
b) 频繁更新的字段不要使用索引
c) 字段不在 where 语句中出现时不要添加索引,如果 where 后含
IS NULL/IS NOT NULL/LIKE ‘%输入符%’等条件,不要使用索引
d) Where 子句里对索引使用不等于(
<>),不建议使用索引,效果一般
sql 语句优化会不会,说出你知道的?
(1) 避免在列上做运算,可能会导致索引失败
(2) 使用 join 时应该小结果集驱动大结果集,同时把复杂的 join 查询拆分成多个 query,
不然 join 越多表,会导致越多的锁定和堵塞。
(3) 注意 like 模糊查询的使用,避免使用%%
(4) 不要使用 select * 节省内存
(5) 使用批量插入语句,节省交互
(6) Limit 基数比较大时,使用 between and
(7) 不要使用 rand 函数随机获取记录
(8) 避免使用 null,建表时,尽量设置 not nul,提高查询性能
(9) 不要使用 count(
id),应该使用 count(
*)
(10) 不要做无谓的排序,尽可能在索引中完成排序
(11) From 语句中一定不要使用子查询
(12) 使用更多的 where 加以限制,缩小查找范围(13) 合理运用索引
(14) 使用 explain 查看 sql 性能

B 树和 B+树的区别,为什么 MySQL 要使用 B+树
B 树:
(1)关键字集合分布在整颗树中;
(2)任何一个关键字出现且只出现在一个结点中;
(3)搜索有可能在非叶子结点结束;
(4)其搜索性能等价于在关键字全集内做一次二分查找;
B+树:
(1)有 n 棵子树的非叶子结点中含有 n 个关键字(b 树是 n-1 个),这些关键字不保存数据,只用来索引,所有数据都保存在叶子节点(b 树是每个关键字都保存数据);
(2)所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,
且叶子结点本身依关键字的大小自小而大顺序链接;
(3)所有的非叶子结点可以看成是索引部分,结点中仅含其子树中的最大(或最小)
关键字;
(4)通常在 b+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点;
(5)同一个数字会在不同节点中重复出现,根节点的最大元素就是 b+树的最大元素。
B+树相比于 B 树的查询优势:(1)B+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;
(2)B+树查询必须查找到叶子节点,B 树只要匹配到即可不用管元素位置,因此 B+
树查找更稳定(并不慢);
(3)对于范围查找来说,B+树只需遍历叶子节点链表即可,B 树却需要重复地中序遍

分布式框架dubbo的好处,不⽤dubbo可不可以。为什么要使⽤分布式
1、dubbo好处:
1、远程通讯: 提供对多种基于⻓连接的NIO框架抽象封装, 包括多种线程模型,序列化,以及“请求-响应”模式的信息交换⽅
式。
2、软负载均衡及容错机制: 提供基于接⼝⽅法的透明远程过程调⽤,包括多协议⽀持,以及软负载均衡,失败容错,地址路由,
动态配置等集群⽀持。
可在内⽹替代F5等硬件负载均衡器,降低成本,减少单点。
3、服务⾃动注册与发现: 基于注册中⼼⽬录服务,使服务消费⽅能动态的查找服务提供⽅,使地址透明,使服务提供⽅可以平滑
增加或减少机器 。
4、提供完善的管理控制台dubbo-admin与简单的控制中⼼dubbo-monitor
5、Dubbo提供了伸缩性很好的插件模型,很⽅便进⾏扩展(ExtensionLoader)
2、不⽤dubbo可不可以:可以,使⽤springcloud。

dubbo的优势
1.单一应用架构,当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的 数据访问框架(ORM)是关键。
2.垂直应用架构,当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的 Web框架(MVC)是关键。
3.分布式服务架构,当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的 分布式服务框架(RPC)是关键。
4.流动计算架构当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的 资源调度和治理中心(SOA)是关键。

1、dubbo由于是二进制的传输,占用带宽会更少
2、springCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大
3、dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决
4、springcloud的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级
5、dubbo的注册中心可以选择zk,redis等,springcloud的注册中心用eureka或者Consul

3、分布式作⽤:
a. 系统之间的耦合度⼤⼤降低,可以独⽴开发、独⽴部署、独⽴测试,系统与系统之间的边界⾮常明确,排错也变得相当容易,
开发效率⼤⼤提升。
b. 系统之间的耦合度降低,从⽽系统更易于扩展。我们可以针对性地扩展某些服务。假设这个商城要搞⼀次⼤促,下单量可能会
⼤⼤提升,因此我们可以针对性地提升订单系统、产品系统的节点数量,⽽对于后台管理系统、数据分析系统⽽⾔,节点数量维
持原有⽔平即可。
c. 服务的复⽤性更⾼。⽐如,当我们将⽤户系统作为单独的服务后,该公司所有的产品都可以使⽤该系统作为⽤户系统,⽆需重
复开发。

dubbo与zookeeper 两者作为注册中⼼的区别,假如注册中⼼挂了,消费者还能调⽤服务吗,⽤什么调⽤的

  1. 注册中⼼对等集群,任意⼀台宕掉后,会⾃动切换到另⼀台
  2. 注册中⼼全部宕掉,服务提供者和消费者仍可以通过本地缓存通讯
  3. 服务提供者⽆状态,任⼀台 宕机后,不影响使⽤
  4. 服务提供者全部宕机,服务消费者会⽆法使⽤,并⽆限次重连等待服务者恢复

介绍下springcloud各个组件?springcloud的注册中⼼除了eureka还可以⽤什么?
springcloud的⼯作原理
springcloud由以下⼏个核⼼组件构成:
Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉
取注册表,从⽽知道其他服务在哪⾥
Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从⼀个服务的多台机器中选择⼀台
Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
Hystrix:发起请求是通过Hystrix的线程池来⾛的,不同的服务⾛不同的线程池,实现了不同服务调⽤的隔离,避免了服务雪崩
的问题
Zuul:如果前端、移动端要调⽤后端系统,统⼀从Zuul⽹关进⼊,由Zuul⽹关转发请求给对应的服务
注册中⼼还可以⽤zookeeper。

posted on 2022-09-27 10:46  南猫猫猫猫猫  阅读(84)  评论(0编辑  收藏  举报