什么是反射?
JAVA反射机制是在运行状态中,对于任意一个类,谁都能够知道这个类的所有属性和方法,
对于任意一个对象都能调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.
反射的原理
jvm通过字节码class文件,生成响应的对象,就像正常生成一个对象一样,都是源于字节码class文件.
获取对象的方式
1. 对象调用getClass方法 2. 用类名.Class获取,性能优 3.使用class对象的静态方法forName方法获取,抛出classNotFoundException异常,使用最多在大多数框架中使用.
JVM
主要由字节码指令集,寄存器,栈,垃圾回收集,存储方法域
生命周期
随着java程序开始而开始,程序结束而结束
JVM进程
1.守护线程: jvm自己使用的线程,比如垃圾回收(GC)
2.普通线程: java程序的线程,只要JVM中有普通线程在执行,JVM就不会停止
JVM多线程运行原理
通过线程轮流切换,并分配处理期执行时间,为各线程之间切换后能恢复到正确位置,每个线程都有独立的计算器
多线程优势
1.发挥多核CPU优势,充分利用CPU同时完成多个任务而互不干扰
2.防止阻塞,效率高,一条线程阻塞不会影响其他线程
3.便与建模,逐步拆分,便于项目完成
创建线程的方式
- 继承Thread类创建线程类,编写简单,不能继承其他类
- 通过Runnable接口,更好的体现了面向编程的思想
- 通过Callable和Future创建
- 通过线程池来创建
Java线程的生命周期
新建 就绪 运行 阻塞 销毁
并发编程的三要素
原子性 可见性 有序性
实现可见性的方法
synchronized或lock保证同一时刻只有一个线程获取锁执行代码,锁释放前把最新值刷新到主内存
什么是线程池
提前创建若干线程,有任务时线程池线程则会处理任务,处理完成后不会销毁,如果想频繁使用创建和销毁线程就可以考虑使用线程池来提高系统性能
四种线程池的创建方法
- newCachedThreadPool创建一个可缓存线程池
- newScheduledThreadPool创建一个定长线程池,支持定时及周期性执行任务
- newFixedThreadPool创建一个定长线程池,可控制线程最大并发数
- newSimleThreadExecutor创建一个单线程化线程池,只会用唯一的工作线程来执行
线程池的优点
- 重用存在的线程,减少创建对象锁的开销
- 有效控制最大并发线程数,提高系统资源使用率,避免堵塞
- 提供定时执行,定期执行,单线程,并发数控制等功能
线程锁的作用
用来控制线程同步的,保证在多线程环境下控制synchronized代码不被多个线程同时执行,关键字可以加方法上也可以加载一段代码上
sleep方法和wait方法有什么区别?
相同点: 都可以用来放弃CPU一定的时间
不同点: 如果线程持有某个对象的监视器,sleep不会放弃这个对象的监视器,wait会放弃
多线程同步的几种方法
- Synchronized关键字
- Lock锁实现
- 分布式锁
Java死锁
java死锁是一种编程情况,其中两个或多个线程被永久阻塞
死锁原因: 在申请锁时发生了交叉闭环
避免解决方法: 审查这几个对象的类中的所有方法,是否存在着导致锁依赖环路的可能性,总之避免在一个方法中调用其他对象的延时方法和同步方法
怎么唤醒一个阻塞线程
因调用wait(),sleep(),join()方法而阻塞中断线程,并通过抛出InterPtedException来唤醒,如果是IO阻塞,我们也无能为力,因为IO是操作系统实现的java代码是无法接触到操作系统的
Java中用到的线程调度算法?
抢占式,一个线程用完CPU后,系统根据数据线程优先级,饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行
Session和Cookie的区别
- 存储位置不同 1.cookie的数据信息存放在客户端浏览器上。2.session的数据信息存放在服务器上。
- 存储容量 1.单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。2. 对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
- 存储方式不同 1.cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据 2. session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
- 隐私策略 1. cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的。 2.session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。
- 有效期 1.session存储在服务器上,对客户端是透明对,不存在敏感信息泄漏的风险。 2.. session不能达到长期有效的效果
- 服务器压力 1. cookie保存在客户端,不占用服务器资源,对于并发用户十分多的网站,cookie是很好的选择 2. session是保存在服务器端,每个用户都会产生一个session ,并发访问的用户十分多,会产生大量的session,耗费大量的内存
不同的服务器怎么共享session
- 通过mysql共享session
- 通过cookie共享session
- 通过服务器之间的数据同session
- 通过NFS共享session
- 通过redis共享session
- 通过memcache同步session
集合
1.Java集合拥有两个父接口: Collection和Map; Collection有3个常用子接口: List Set Queue
2.List又拥有两个常用实现类: ArrayList和LInkedList; Set又拥有两个实现类:HashSet TreeSet
3.Map有两个常用实现类: HashMap和HashTable
什么是HashMap?
MySQL
数据库存储引擎
InnoDB(B+树)是聚集索引,底层存储结构为B+树,树的每个节点对应innodb的一个page,page大小是固定的,一般设为16k,其中非叶子节点只有键值,叶子结点包含完成数据
使用场景:
- 经常更新的表,适合处理多重并发的更新请求
- 支持事务
- 外键约束,只有他支持外键
- 可以从灾难中恢复(通过 bin-log 日志等)
- 支持自动增加列属性 auto_increment
MyIASM是一种静态索引但它是MySQL默认的引擎,
缺点: 它没有提供对数据库事务的支持,也不支持行级锁和外键,因此做添加和更新数据是即写操作需要锁定整个表,效率便会更低一些
优点: 它执行读取操作的速度很快,而且不用占用大量的内存和存储资源,在设计之初就预想数据组织成有固定长度的记录,按顺序存储的
索引
作用:
- 索引(Index)是帮助MySQL高效获取数据的数据结构
- 加速表与表之间的连接,使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间
常见的查询算法: 顺序查找, 二分查找, 二叉排序树查找, 哈希散列法, 分块查找, 平衡多路搜索树B树(B-tree),索引是对数据库表中一个或多个列的值进行排序的结构,建立索引有助于快速获取信息,
MySQL的四种不同的索引:
- 主键索引
- 唯一索引 可以确保每一行数据的唯一性
- 普通索引
- 全文索引
索引并非越多越好,创建索引也需要耗费资源,
缺点:
- 增加了数据库的存储空间,
- 在插入和删除时需要花费较多的时间维护索引
优点:
- 索引加快数据库的检索速度
- 索引降低了插入,删除和修改等维护任务的速度
- 通过使用索引,可以再查询的过程中使用优化隐藏器,提高系统的性能
- 索引需要占用物理和数据空间
常见的索引原则
- 选择唯一索引,唯一索引的值是唯一的,可以快速的通过该索引来确定某条记录
- 如果索引的值很长,那么查询的速度会受到影响,尽量使用前缀来索引
- 如果索引字段的值很长,最好使用值的前缀来索引
- 删除不再使用或者很少使用的索引
- 最左前缀匹配原则是非常重要的原则
- 尽量的扩展索引,不要新建索引
什么时候创建索引???
- 在最频繁使用的、用以缩小查询范围的字段上建立索引。
- 在频繁使用的、需要排序的字段上建立索引
- 主键自动建立唯一索引
- 查询中统计或分组字段()
- 查询中与其他表关联的字段,外键关系建立索引
- 单键/组合索引的选择问题,组合索引性价比更高
什么情况下不适合建立索引?
查询中很少涉及的列或者重复值比较多的列,以及一些特殊的数据类型,比如文本字段(text)等
数据库的三大范式
- 第一范式: 每个列都不可以再拆分, 确保每列的原子性
- 第二范式:在第一范式的基础上,非主键列完全依赖于主键,而不能是依赖于主键的一部分, 要求每个表只描述一件事情
- 第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键, 表中的列不存在对非主键列的传递依赖
在设计数据库的时候,要尽量遵守第三范式,如果不遵守,必须有足够的理由.比如性能,事实上我们经常会为了数据库的性能而妥协数据库的设计
SQL优化
- 查询语句中不要使用select *
- 尽量减少子查询,使用关联查询(left join,right join,inner join)替代
- 减少使用IN或者NOT IN ,使用exists, not exists或者关联查询语句代替
- or的查询尽量用union或者union all 代替
- 尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描
- 尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃索引而进行全表扫描, 如:select from t where num is null可以再num上设置默认值0, 确保表中num列没有null值,然后这样查询: select id from t where num=0
- 避免在索引列上使用计算
- 避免使用消耗资源的操作, distint, union, union all
- 对查询进行优化,应尽量避免全表扫描,首先考虑在where及order by涉及的列上建立索引
- 尽量全值匹配,select * from student where ID=“20151001” and name=“zhangsan” and age=“23”;(id,age,name都是索引,建议写到where后面的这个判断后面)
- 当索引多列时,尊重左前缀法则,带头大哥不能死,中间兄弟不能挂. 索引原则-最佳左前缀法则
什么是内联接,左外联接,右外联接??
内链接是(Inner Join):匹配2张表中相关联的记录
左外联接(Left Outer Join): 除了匹配2张表中相关联的记录外,还会匹配左表中剩余的记录,右表中未匹配的字段用null表示
右外联接(Right Outer Join): 除了匹配2张表中相关联的记录外,还会匹配右表中剩余的记录,左表中未匹配的字段用NUll表示,在判定左表和右表时,要根据表名出现在Outer join的左右位置关系
事务
四大特性:
- 原子性:是不可分割的最小单位,要么成功,要么失败
- 一致性:当事务提交后,数据会持久化保存数据
- 隔离性:多个事务之间,相互独立
- 持久性:事务操作前后,数据总量不变
事务提交的两种方式:
- 自动提交:MySql默认就是自动提交, 一条增删改语句会自动提交一次事务
- 手动提交:Oracle数据库默认是手动提交, 需要先开启事务,再手动提交
事务的隔离级别
概念:多个事物之间隔离的,相互独立的,但是多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别,就可以解决这些问题
存在问题:
脏读: 一个事务读取到另一个事务中没有提交的数据
解决方法: 如果在第一个事务提交前,任何其他生物不可读取其修改过的值,则可以避免该问题
不可重复读: 在同一个事务中,两次读取到的数据不一样
解决方法: 如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题
幻读: 一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改
解决方法: 如果在操作事务完成数据处理之前,任何其他事物都不可以添加新数据,则可以避免该问题
隔离级别:
- Read uncommitted(未授权读取,读未提交): 事务B读取到了事务A未提交的数据
- Read committed(授权读取,读已提交): 读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行
- Repeatable read(可重复度): 可重复度是指在一个事务内,多次读同一事务
- Serializable(序列化): 它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行
注意!!!
隔离级别从小到大安全性越来越高,但效率越来越低
行锁和表锁
行锁:访问数据库时锁定整个行数据,防止并发错误。
表锁:访问数据库时锁定整个表数据,防止并发错误。
区别:
行锁:锁力度小,开销大,加锁慢,会出现死锁,发生锁冲突概率大,并发高。
表锁:锁力度大,开销小,加锁快,不会出现死锁,发生锁冲突概率低,并发低。
行锁和表锁应用场景:
行锁适用于高并发环境下对于事物完整性高的系统;表锁适用于并发性不高,以查询为主,更新少。
面向对象
面向对象的优点:
- 提高的了代码的可扩展性
- 提高了代码的可维护性
- 面向对象的封装,继承,多态
如何理解面向对象??
世间万物皆对象, 对象有具体的实例化,任何方法或者属性都要写在对象(类)里面,就是不断的创建对象使用对象指挥对象做事
StringBuffer,StringBuilder的区别?
- String是不可变的字符串常量对象,就是字符串序列底层是现实char数组,因为是数组所以定长(一旦定义长度就固定不变)
- StringBuffer线程安全的可变字符串,底层时显示一个"可变长的数组",数据安全效率低
- StringBuilder用作替换StringBuffer,JDK1.5新增类,县城不安全的可变字符串,效率高
Error和Exception有什么区别?
- Error表示恢复不是不可能但很困难的情况下的一种严重问题,比如说内存溢出,不可能指望程序能处理这样的情况
- Exception表示一种设计或实现问题,也就是说,它表示如果程序运行正常,从不会发生的情况
Spring
设计模式
- 简单工厂模式又叫静态工厂方法(StaticFactory)模式: 实质是有一个工厂类根据传入的参数,动态决定应该创建哪一个产品类, spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的表示来获得bean对象,单是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定
- 工厂方法模式: 应用程序有自己的工厂独享来创建bean,如果将应用程序自己的工厂对象交给Spring管理,那么Spring管理的就不是普通的bean而是工厂bean
- 单例模式: 保证一个类仅有一个实例,并提供一个访问它的全局访问点,spring中的单列模式完成了后半句话,即提供了全局的访问点BeanFactory,但没有从构造器级别去控制单例,这是因为Spring管理的是任意的Java对象
- 适配器模式: 在Spring的AOP中,使用的Advice(通知)来增强被代理类的功能,Spring实现这一AOP功能的原理就使用代理模式对类进行方法级别的切面增强,即,生成被代理类的代理类,并在代理类的方法前设置拦截器,通过执行拦截器中的内容增强了到咯方法的功能,实现面向切面编程
- 包装器模式: Spring中用到的包装器模式在类名上有两种表现: 一种是雷鸣中含有Wrapper,另一种是类名中含有Decorator,基本上都是动态的给一个对象添加一些额外的职责
- 代理模式: 为其他对象提供一种代理难以控制对这个对象的访问,从结构上来看和Decorator模式类似,单Proxy是控制,更像是一种对功能的限制,而Decorator是增加职责
- 观察者模式: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自己更新
- 策略模式: 定义一系列的算法,把它们一个个封装起来,并且使他们可相互替换,本模式使得算法可独立于使用它的客户而变化
原理
它是一个全面的,企业应用开发一站式的解决方案,贯穿表现层,业务层,持久层但是Spring任然可以和其他的框架无缝整合
核心组件
1. Bean组件 2.Context组件 3.Core组件
Spring对象是什么时候创建的?
一般都是项目启动的时候创建的,以前用原生态的三大框架的时候是需要我们手动去指定他要去扫描哪些包的指定路径,这些包路径指定好了之后,将来在启动的同时,就回去扫描这些包下的注解作为一种标识向@Service ,@Controller ,@Component,等他识别这些注解的同时,就会生成对象交给spring容器来管理.
现在我们用的是SpringBoot,在@SpringBootApplication下面有个AutoPackage这个注解自动扫描包路径的,我们在使用SpringBoot的时候有个主启动包,在它的下面都是子包,它要去扫描的是所有子包里面是否有那些注解,如果有就会给它初始化好,放在容器里面进行管理
Spring IOC
Spring通过一种称作控制反转IOC技术促进了低耦合,IOC(控制反转)就是依赖导致原则的一种代码设计思路.就是把原先在代码里面需要实现的对象创建,对象之间的依赖,反转给容器来帮忙实现.
Spring IOC容器通过xml,注解等其他方式配置类及类之间的依赖关系,完成了对象的创建和依赖的管理注入. 实现IOC的主要设计模式是工厂模式
使用IOC的好处: 集中管理,实现类的可配置和易管理, 降低了类与类之间的耦合度
Spring AOP
AOP(面向切面)是一种编程范式,提供从另一个角度来考虑程序结构以完善面向对象编程(OOP).
AOP为开发者提供了一种描述横切关注点的机制,并能够自动将横切关注点织入到面向对象的软件系统中,从而实现了横切关注点的模块化.
AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理,日志管理,权限控制等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性型和可维护性.
使用AOP的好处:降低模块间的耦合度,使系统容易扩展,提高代码复用性
AOP的基本概念
- 连接点(JoinPoint): 需要在程序中插入横切关注点的点,连接点可能是在类初始化,方法调用,字段调用或处理异常等等, Spring中只支持方法执行连接点
- 切入点(Pointcut): 一组相关连接点的集合
- 通知(Advice): 在连接点上执行的行为,增强提供了在AOP中需要在切入点所选择的连接点进行扩展现有行为的手段,包括前置增强(before advice), 后置增强(after advice), 环绕增强(around advice).
- 切面(Aspect) : 通知和切入点的结合
- 织入(Weaving): 织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程
- 代理(Proxy) : 通过代理方式来对目标对象应用切面.AOP代理可以用JDK动态代理成CGLIB代理实现
- 目标对象(TArget) : 需要被织入关注点的对象,即被代理的对象
实现AOP的主要设计模式就是动态代理
Spring的动态代理有两种
1.JDK的动态代理: 两个核心接口(类)分别是InvocationHandler和Proxy 注意:只能代理接口
2.CGLIB动态代理: 两个核心接口(类)分别是MethodInterceptor和Enhancer 注意: 可以代理类和接口 ,但不能代理final类
Spring的特点
- 轻量级 : 从大小与开销方面而言spring都是轻量的,完整的Spring框架介意在一个大小只有1M多的jar文件里发布,并且Spring所需的处理开销也是微不足道的
- 控制反转: Spring通过一种称作控制反转IOC的技术促进了低耦合
- 面向切面: Spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开
- 容器: Spring包含并管理应用对象的配置和生命周期,从这个意义上它是一种容器,你可以配置你的每个bean如何被创建----基于一个可配置原型,你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例---以及它们是如何关联的
- 框架集合: Spring可以将简单的组件配置,组合成为复杂的应用,在Spring中,应用对象被声明式地组合,典型的是在一个XML文件里,Spring也提供了很多基础功能(事务管理,持久化框架集成等),将应用逻辑的开发留给开发者
SpringMVC原理
Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把这个请求分发给各个处理器,并支持可配置的处理器器映射,视图渲染,本地化,时区与主题渲染等,甚至还能支持文件上传
SpringBoot原理
springboot的开箱即用
通过启动类上@SpringBootApplication这个注解,这个注解下有几个原注解,其中有个注解叫@EnableAutoConfiguration注解,这个注解下又有子注解,分别是@AutoConfigurationPackage包扫描,就是启动后就会自动扫描启动类包中所有的子孙包,
@Import(AutoConfigurationImportSelector. class)该配置中内部集成了所有的SpringBoot中的选择器.这些选择器的主要的任务就是查看是否有自己选择器所管理的启动项的配置. 如果发现该启动项,那么选择器就会执行该启动项,从而实现了开箱即用的操作.
SpringBoot的特点
- 创建独立的Spring应用程序
- 嵌用的tomcat,无需部署WAR文件
- 简化Maven配置
- 自动配置Spring
- 提供生产就绪型功能,如指标,健康检查和外部配置
- 绝对没有代码生成和对XML没有要求配置
Mybatis
什么是mybatis?
MyBatis 是一个可以自定义SQL、存储过程和高级映射的持久层框架。MyBatis 摒除了大部分的JDBC代码、手工设置参数和结果集重获。MyBatis 只使用简单的XML 和注解来配置和映射基本数据类型、Map 接口和POJO 到数据库记录。相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,Mybatis 是一种“半自动化”的ORM实现。
Mybatis的优点:
- 简单易学,容易上手(相当于Hibermate)---基于SQL编辑
- JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接
- 很好的与各种数据库兼容(因为Mybatis使用JDBC来连接数据库,所以只要JDBC支持的数据库Mybatis都支持,而JDBC提供了可扩展性,所以只要这个数据库有针对Java包就可以与Mybatis兼容),开发人员不需要考虑数据库的差异性
- 提供了很多第三方插件(分页插件/逆向工程)
- Mybatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,解除sql与程序代码的耦合,便于统一管理和优化,并可重用
- 能够与spring很好的集成
- 提供XML标签,支持编写动态SQL语句
- 提供映射标签,支持对象与数据库的ORM字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
Mybatis框架使用场合
- MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案
- 对性能的要求很高或者要求变化较多的项目,如互联网项目,MyBatis将是不错的选择
Mybatis缓存
Mybatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的.一级缓存是指SqlSession级别的缓存,当在同一个SqlSession中进行相同的SQL语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,以及缓存最多缓存1024条SQL.二级缓存是指可以跨SqlSession的缓存.是mapper级别的缓存,对于mapper级别的缓存是不同的,SqlSession是可以共享的
Mybatis运行流程
1、获取sqlSessionFactory对象:
根据配置文件(全局,sql映射)初始化出Configuration对象
解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
注意:MappedStatement:代表一个增删改查的详细信息2、获取sqlSession对象
返回一个DefaultSQlSession对象,包含Executor和Configuration;
这一步会创建Executor对象;
Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)3、获取接口的代理对象(MapperProxy)
DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
使用MapperProxyFactory创建一个MapperProxy的代理对象
代理对象里面包含了,DefaultSqlSession(Executor)4、执行增删改查方法
1)调用DefaultSqlSession的增删改查(Executor);
2)会创建一个StatementHandler对象。
(同时也会创建出ParameterHandler和ResultSetHandler)
3)调用StatementHandler预编译参数以及设置参数值;
使用ParameterHandler来给sql设置参数
4)调用StatementHandler的增删改查方法;
5)ResultSetHandler封装结果
Redis
作用:redis缓存,减少与数据库的交互,节约性能,在每次执行查询操作的时候,先查缓存,缓存没有再查数据库
redis分片:分片是redis存储的一种方法,它是针对一台redis做了分区,将来它想要去存储数据,首先会拿到这个数据的key做一个Hash算法,算出来的值会按照顺时针的方逆向去寻找一个就近分区进行存储,如果将来某一分区宕机了,它的数据不会丢失,而是进行了合并,但是分片redis在里面并不是一个理性的策略,因为它不能实现高可用,如果它整个分片断了,就意味着整个数据彻底丢失,所以我们用得少
redis怎么整合到项目中去?
- 导jar包
- 在propoties文件中配置redis集群ip端口,存储的方式k-v结构把多台redis的ip地址和端口放进去
- 写一个配置类,用@Configuration注解进行描述,生成一个核心对象(配置获取ip端口对象),交给spring容器管理
- 使用@Autowared注解注入,调用jedis里面各种各样的方法
Redis集群
集群的三种模式:
- 主从模式 缺点:不具备高可用,master节点在主从模式中唯一,若master挂掉,则redis无法对外提供写服务
- Sentinel模式(哨兵) 工作机制:当使用哨兵模式的时候,客户端就不要直接连接redis,而是连接sentinel的ip和port,由sentinel来提供具体的可提供服务的Redis实现,这样当master节点挂掉以后,sentinel就会感知并将新的master节点提供给使用者
- Cluster模式 概念:是主从模式和哨兵模式的结合体,通过cluster可以实现主从和master重选功能,所以如果配置两个副本三个分片的话,就需要六个Redis实例,因为Redis的数据是根据一定规则分配到Cluster的不用机器的,当数据量过大时,可以新增机器进行扩容,使用集群,只需要将redis配置文件中的cluster-enable配置打开即可,每个集群中至少需要三个主数据库才能正常运行,新增节点非常方便 Cluster集群特点: 1.多个redis节点网络互联,数据共享 2.所有节点都是一主一从(也可以一主多从),其中从不提供服务,仅作为备用 3.不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为 4.支持在线增加,删除节点 5.客户端可以连接任何一个主节点进行读写
Dubbo
doubbo的作用
远程调用, 远程调用就是把单体项目做了一个垂直的拆分,把模块拆分出来部署到不同的服务器上,不同的服务器将来想要去调用数据,首先要有通信连接和通信协议,基于协议去做远程调用
怎么实现,怎么用远程调用?
Dubbo底层封装了一个RPC通信协议,RPC通信协议传输的是一个二进制文件,我们依照现有的开发方式来用控制层调用业务层,业务层调用dao层,到层是mybatis,查询出来的数据是一个对象,但是RPC传输的数据是一个二进制文件,我们需要把它转换成dubbo能够识别的数据,所以,需要进行序列化操作,然后在进行数据的回传,交给用户的同时dubbo会进行反序列化操作,到达前台控制层的同时,会把二进制再次转换成对象
Spring Cloud
什么是Spring Cloud?
Spring Cloud是一系列框架的集合,它利用Spring Boot的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务发现注册,配置中心,消息总线,负载均衡,断路器,数据监控,都可以用Spring Boot的开发风格做到一键启动部署.
Spring Cloud断路器的作用是什么?
当某个服务单元发生故障,通过断路器的故障监控,向调用方法返回一个错误响应,而不是长时间的等待,这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统中的蔓延
Spring Cloud的核心组件有哪些?
- Eureka: 服务注册于发现
- Feign: 基于动态代理机制,根据注解和选择的机器,拼接请求url地址,发起请求
- Ribbon: 实现负载均衡,从一个服务的多台服务器中选择一台
- Hystrix: 提供线程池,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免的服务的雪崩问题
- Zuul: 网关管理,由Zuul网关转发请求给对应的服务
什么是服务熔断?什么是服务降级?
服务熔断: 在复杂分布式系统中,微服务之间相互调用,可能出现各种原因导致服务器阻塞在高并发场景下,阻塞会导致线程不可用,服务器的线程全部阻塞会导致服务器崩溃,由于服务器之间的调用关系是同步的,会对整个微服务系统造成服务雪崩
服务降级: 一旦发生服务雪崩们就会熔断整个服务,通过维护自己的线程池,当线程达到阈值的时候就启动服务降级,如果其他请求继续访问就直接返回fallback的默认值
Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别??
- ZooKeeper保证的是CP,Eureka保证的是AP, ZooKeeper在选举期间服务不可用,Eureka各个节点是平等关系,只要有一台Eureka就可以保证服务可用,但是查询到的数据不是最新的,自我保护机制会导致Eureka不再从注册列表移除因长时间没收到心跳应该过期的服务,但是仍然可以接受新服务的注册和查询请求,但是不会被同步到其他节点(高可用), 当网络稳定时,当前实例新的注册信息会被同步到其他节点中(最终一致性)
- ZooKeeper有Leader和Follower角色,Eureka各个节点平等
- ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题
- Eureka本质上是一个工程,而ZooKeeper只是一个进程
什么是Ribbon?
Ribbon是一个负载均衡客户端,可以很好的控制http和tcp的一些行为. feign默认集成了Ribbon
SpringCloud和Dubbo的区别??
服务的调用方式: Dubbo使用的是RPC远程调用,Dubbo本身只是实现了服务治理 SpringCloud使用的是Rest API,其实更符合微服务官方的定义
服务的注册中心来看: Dubbo使用了第三方的ZooKeepe作为底层的注册中心,实现服务的注册和发现 SpringCloud使用Spring Cloud Netflix Eureka实现注册中心
服务网关: Dubbo并没有本身的实现,只能通过其他第三方技术的整合 SpringCloud有Zuul路由网关,作为路由服务器,进行消费者的请求分发,SpringCloud还支持断路器,与Git完美集成分布式配置文件支持版本控制,事务总线实现配置文件的更新与服务自动装配等等一些列的微服务架构要素
Rest和RPC对比
RPC最主要的缺陷就是服务提供方和调用方式之间依赖太强,我们需要为每一个微服务进行接口的定义,并通过持续继承发布,需要严格的版本控制才不会出现服务提供和调用指尖因为版本不同而产生的冲突
Rest是轻量级的接口,服务的提供和调用不存在代码之间的耦合,只是通过一个约定进行规范,但也有可能出现文档和接口不一致而导致的服务集成问题,但可以通过swagger工具整合,是代码和文档一体化解决,所有REST在分布式环境下比RPC更灵活
SpringBoot和SpringCloud有什么区别?
SpringBoot是Spring退出用于解决传统框架配置文件冗余,装配组件繁杂的基于Maven的解决方案,旨在快速搭建单个微服务
SpringCloud专注于解决各个微服务之间的写覅与配置,服务之间的通信,熔断,负载均衡等技术维度并相同,并且SpringCloud是依赖SpringBoot的,而SpringBoot并不依赖于SpringCloud,甚至还可以和Dubbo进行优秀的整合开发
总结
- SpringBoot专注于快速的开发单个个体的微服务
- SpringCloud是关注全局的微服务协调整理治理框架,整合并管理各个微服务,为各个服务之间提供配置管理,服务发现,断路器,路由,事件总线等集成服务
- SpringBoot不依赖SpringCloud,SpringCloud依赖于SpringBoot,属于依赖关系
- SpringBoot专注于快速,方便的开发单个的微服务个体,SpringCloud关注全局的服务治理框架
负载均衡的意义是什么?
负载均衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布
负载均衡旨在优化资源使用,最大吞吐量,最小响应时间并避免任何单一资源的过载,使用多个组件进行负载均衡而不是单个组件可能会通过冗余来提高可靠性和可用性
负载均衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务进程