待补充
先来简单的面试八股文
1、方法重载 和 重写 的区别
重载: 指的是一个类下方法不满足当前使用, 同一个方法名
但是 传递的参数或者返回的参数结果不同
的方法
public void t1(){}
public String t1(){}
public void t1(String name){}
重写: 特指 子类继承父类,父类方法不满足子类使用,需要对其重新实现
结合模板设计模式理解
2、Java面向对象的三大特性
封装:简单理解就是对 属性进行权限控制,不允许外部直接使用
- private : 私有,仅仅当前类可使用
- protected : 当前类、同包、子类可使用
- public : 公共的、无限制
继承:指的是 子类继承父类、类是单继承、接口是多继承
多态:指的是 Map map = new HashMap(); 编译类型是Map对象,但是实际运行对象是HashMap。多态的实现方式体现在重写、接口、抽象类和抽象方法。
3、String 为什么是不可变的?
首先 String 字符串 意思就是 字符拼接起来的 一个对象,其底层还是一个个char数组,并且是使用了 private 和 final 修饰 :private保证了其对象的内容不会被修改,而final保证了其本身的vale
引用地址不会被修改,从而保证了String不会被修改,并且在String中没有set方法保证不会被修改。
String name1 = "小明"; String name2 = "小明"; name1 = "小红";
分析: 其实是在常量池创建了 "小明" 这个变量,而 name1 只是将地址指向了 “小明” ,假设将字符可变,
那引用到他的 name2 的对象也会受到影响。 name1 = “小红”; 只是将 对象 name1 的引用地址变成了 “小红”不是说Striing可变
看了很多解释,唯独这个视频讲解的很透( •̀ ω •́ )✧ --> String不可变视频讲解
4、String、StringBuffer 和 StringBuilder 的区别是什么?
String: 是一个不可变的字符串,底层是由char[]实现,字符串存放在常量池当中,直到对象被销毁。因为String有不可变性,所以引申出了StringBuffer和StringBuilder。
StringBuffer:线程安全的可变字符串对象,性能相对会高,常用的方法有append(),
5、自动装箱与拆箱?
6、接口和抽象类的区别是什么?
7、== 与 equals区别?
8、你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?
9、线程有哪些基本状态,并描述每种状态?
10、final 关键字修饰这三个地方:变量、方法、类,会有什么作用?
11、说说 &和&&的区别、| 和 | | 区别?
12、ArrayList的拓容机制 、ArrayList和Vector、LinkedList的区别
ArrayList 的扩容机制: 位运算左移一位 、 乘2 ,变成原来的两倍
add方法 首先会先判断是否需要扩容 : ensureCapacityInternal(集合大小)
先看calculateCapacity()
方法
个人理解就是先判断元素集合是否为空,为空的话返回默认容量10,反之直接返回当前容量。当容量为12 添加到 第13个元素的时候开始扩容
再来看 ensureExplicitCapacity()
方法
定义容量为 12 的数组,当添加到第13个元素的时候开始扩容
ArrayList和Vector、LinkedList区别:
ArrayList 和 Vector 本质上就是数组:
数组有序号,且可以通过序号查询到对应的元素,对应查询效率大大增加,但是对应指定位置的增删慢,因为每一次的增删会导致元素的位置发生变化,每次的增删都需要维护一次数据。扩容慢。
LikedList是链表:
链表主要是由node节点组成,每一个node的指针指向下一元素的内容地址,通过头指针元素一个个查询到对应的元素,无序号,查找效率底,每次都只能从开头开始找,但是随机增删对的效率高,因为不需要维护对应的关系,只需要改变指针指向的元素地址即可删除对应元素,而弃之的node节点将由垃圾回收机制回收
13、描述深拷贝和浅拷贝?
14、HashMap和Hashtable的区别?
15、说说List,Set,Map三者的区别?
16、什么是线程死锁?线程的状态有哪些?
17、Object常用的方法?
18、谈一下HashMap的底层原理是什么?
19、谈一下hashMap中什么时候需要进行扩容,扩容resize()又是如何实现的?
20、浅谈volatile关键字的作用?
21、什么是API?
API 就是提供对外的一种调用方法
比如:
我们想调用alibaba的durid数据库连接池,就可以导入它的jar包从而使用他的API SDK
另一种则是作为功能服务暴露公共的API接口给外部使用 WEB 请求路径
22、平时在使用HashMap时一般使用什么类型的元素作为Key?
23、什么是Git?
版本控制工具,代码的团队开发、帮助我们备份、代码还原、追溯代码和权限控制
24、Git常见的命令?
git add(提交到暂存区)
git commit(提交到版本库)
git push(提交到远程仓库)
git clone(第一次将整个项目克隆)
git pull(之后得拉取项目)
git status(查看文件状态)
git diff(查看文件的修改)
git reset --hard HEAD^(回到上一个版本)
git reset --hard < commit id > (回到指定版本)
git log (查看日志)
命令 git checkout -- readme.txt
意思就是,把 readme.txt
文件在工作区的修改全部撤销,这里有两种情况:
一:readme.txt
自修改后还没有被放到暂存区(git add
),现在,撤销修改就回到和版本库一模一样的状态;
二:readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
注意区分:git checkout filename (切换分支) 和 git checkout – filename (撤销)
删除 : git rm test.txt
查看分支:git branch
创建分支:git branch < name >
切换分支:git checkout < name >
创建 + 切换分支:git checkout -b < name >
将某分支合并到当前分支:git merge < name >
25、什么是RestFul风格
Restful 的 四要素: 请求方式、请求方法、请求参数、方法返回值
Restful 是 一种API 的设计规范,按照它的设计规范去编写API 会使我们的代码变得统一,如查询统一使用GET方式、新增统一使用POST、修改统一使用PUT、删除统一使用DELETE,简洁可读性强
@PathVariable 实现路径传参
网页请求路径默认是GET
26、浅谈前后端分离技术
前后端分离就是 前端干前端的事情,后端干后端的事情 达到责任分离的目的,前后只需要专注于前端代码 不需要注重后端业务实现,后端只需要专注于后端代码 不需要注重前端的代码。
优点:责任分离,降低前后端严重耦合
缺点:跨域问题
27、列举常见的HTTP的状态码
200 / 201: 响应成功
400: 参数接收有问题
403: 权限不够访问该页面
404: 找不到访问路径
500: 后端代码有问题
502/503 / 504:网关或者路由有些问题
28、JDK1.8新特性 (待补充)
29、了解哪些设计模式?用到了哪些?手写一个单例模式
单例模式:
– 懒汉式
– 饿汉式
– 双重锁检测机制
工厂模式:
– 简单工厂模式
– 抽象工厂模式
设计模式
30、get和post请求的区别?
GET 请求只能 URL 编码,而 POST 支持多种编码方式
GET 请求只接受 ASCII 字符的参数,而 POST 则没有限制
GET 请求的参数通过 URL 传送,而 POST 放在 Request Body 中
GET 相对于 POST 更不安全,因为参数直接暴露在 URL 中
GET 请求会被浏览器主动缓存,而 POST 不会(除非自己手动设置)
GET 请求在 URL 传参有长度限制,而 POST 则没有限制
GET 产生的 URL 地址可以被收藏,而 POST 不可以
GET 请求的参数会被完整的保留在浏览器的历史记录里,而 POST 的参数则不会
GET 在浏览器回退时是无害的,而 POST 会再次提交请求
31、转发(Forward)和重定向(Redirect)的区别?
转发是服务器行为,重定向是客户端行为。
32、Cookie和Session的的区别?
33、 说说preparedStatement和Statement的区别?
34、数据库连接池的原理?为什么要使用连接池?
简单理解: 提前创建好指定数量的连接、需要就去“池”中获取,用完再放回去,减少了每次需要都取创建删除的繁琐流程。(提高效率)
多说一句: 线程的连接池也是如此
35、 什么是事务?MySQL的隔离界别有哪些?Spring的事务有哪些?
简单理解: 要么都成功要么都失败,分为 BEGIN(开启事务)、SAVEPOINT (保留点)、COMMIT (提交执行)、ROLLBACK (回滚事务/回到上一个保存点),开启事务之后是一种预处理的状态,修改的数据并没有真正的生效,需要提交后才会成功,这里又引申出了一个问题,那就是开启多个事务都同时修改一条数据需要怎么处理,引申出MySQL的隔离界别。
事务
:就是被绑定在一起作为一个逻辑工作单元的 SQL 语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务,准寻ACID原则。
MySQL的隔离界别
:
Spring的事务
:
required (默认事务): 如果当前存在了事务,那就融入这个事务中,没有则重新创建
假设出现异常那么update() 和 delete() 方法都会执行失败,因为在同一个事务中。
requires_new : 需要一个新事物,不管外部有没有,如果原来有,就挂起原事务
可以用在记录日志, 银行取钱,中间调用一个 log(); 记录日志方法,
不管取钱是失败还是成功都记录一次
nested : 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务
(嵌套事务,子事务回滚不影响外层事务,但是外层事务回滚子事务会一起回滚)
PROPAGATION_REQUEIRES_NEW:肯定会创建子事务,父子互不影响;
PROPAGATION_NESTED:肯定会创建子事务,父影响子,子不影响父;
PROPAGATION_REQUEIRED:子事务和父事务合并成一个事务,父子互相影响;
supports : 如果没有就以非事务的方式执行,如果有则融入该事务
never : 只要有事务我就报错
not_supported : 没有就非事务执行,有就直接挂起,然后非事务执行
mandatory : 如果没有,就抛出异常,如果有,就是用当前的
35、导致 spring 事务失效 原因?
@Transactional
只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ
代理模式。36、在MyBatis中, #{} 和 ${} 的区别是什么?
#{}
是预编译处理,${}
是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
Mybatis在处理${}
时,就是把${}
替换成变量的值。
使用#{}
可以有效的防止SQL注入,提高系统安全性
37、 查询语句不同元素(where、jion、limit、group by、having等等)执行先后顺序?
查询中用到的关键词主要包含六个,并且他们的顺序依次为 select–from–where–group by–having–order by
38、什么是Springle?Spring的核心? (待补充)
IOC
:
AOP
:
DI
:
39、Spring 的 AOP中有哪些不同的通知类型? 是怎么是实现的?
通知(advice)是你在你的程序中想要应用在其他模块中的横切关注点的实现。Advice主要有以下5种类型:
@Before
注解使用这个Advice。@AfterReturning
关注使用它。@AfterThrowing
注解来使用。@After
注解使用。@Around
注解使用。40、Spring AOP 默认使用jdk动态代理还是cglib?
要看条件,如果实现了接口的类,是使用jdk。如果没实现接口,就使用cglib
41、SpringAOP的应用场景 ?
场景一: 记录日志
场景二: 监控方法运行时间 (监控性能)
场景三: 权限控制
场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )
场景五: 事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )
42、Spring 的 bean 的作用域?
singleton
:在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。
prototype
:每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。
request
:每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。
session
:同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。
application
:限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。
bean的作用域
43、SpringMVC常用注解?
@EnableWebMvc 在配置类中开启Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,若无此句,重写WebMvcConfigurerAdapter方法(用于对SpringMVC的配置)。
@Controller 声明该类为SpringMVC中的Controller
@RequestMapping 用于映射Web请求,包括访问路径和参数(类或方法上)
@ResponseBody 支持将返回值放在response内,而不是一个页面,通常用户返回json数据(返回值旁或方法上)
@RequestBody 允许request的参数在request体中,而不是在直接连接在地址后面。(放在参数前)
@PathVariable 用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。
@RestController 该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。
@ControllerAdvice 通过该注解,我们可以将对于控制器的全局配置放置在同一个位置,注解了@Controller的类的方法可使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上,
这对所有注解了 @RequestMapping的控制器内的方法有效。
@ExceptionHandler 用于全局处理控制器里的异常
@InitBinder 用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中。
@ModelAttribute 本来的作用是绑定键值对到Model里,在@ControllerAdvice中是让全局的@RequestMapping都能获得在此处设置的键值对。
44、 SpringMVC的流程?
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器;
(5)HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
45、如何解决POST请求中文乱码问题,GET的又如何处理呢?
(1)解决post请求乱码问题:
在web.xml中配置一个CharacterEncodingFilter过滤器,设置成utf-8;
(2)get请求中文参数出现乱码解决方法有两个:
①修改tomcat配置文件添加编码与工程编码一致
②另外一种方法对参数进行重新编码:
String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),“utf-8”)
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。
46、Spring框架中用到了哪些设计模式?
1.工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。
2.代理设计模式:Spring AOP功能的实现。
3.单例设计模式:Spring中的bean默认都是单例的。
4.模板方法模式:Spring中的jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,它们就使用到了模板模式。
5.包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
6.观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。
7.适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、Spring MVC中也是用到了适配器模式适配Controller。
47、
30、手写冒泡排序、选择排序、插入排序,说什么是希尔排序、归并排序?哪些排序是稳定的?
31、什么是时间复杂度?
32、Mybatis 和 Mybatis-Plus 区别?
1、现在有线程 T1、T2 和 T3。你如何确保 T2 线程在 T1 之后执行,并且 T3 线程在 T2 之后执行?
t1.start();
t1.join(); // 等到 t1执行完后才会调用t2.start()
t2.start();
t2.join(); // 等到 t2执行完后才会调用t3.start()
t3.start();
t3.join();
// join(10)表示main线程会等待t1线程10毫秒,10毫秒过去后
2、HashMap初始容量为什么是16?为什么必须是2的幂?如果输入值不是2的幂比如10会怎么样?为什么不直接将key作为哈希值而是与高16位做异或运算?
HashMap 默认容量是右位运算4位为16,必须是2的幂次是因为在计算 hash 值的时候能够均匀的分布到数组上,防止hash冲突
不直接将key直接作为hash值是防止防止hash冲突激烈,对运算的key在做一次运算
3、 什么是JUC?
JUC指的是在 java.util.concurrent 包(JUC)中,有各式各样的并发控制工具,这里我们简单介绍几个常用的工具及其使用方式。
4、第一点什么是线程?什么是进程?
一个进程可以有多个线程,每个线程之间可以共享资源,线程是CUP最小的调度单位。
5、并发、并行?
并发:多线程操作同一个资源、本质:充分利用CUP的资源
- CUP 一核,模拟出多个线程,天下武功唯快不破,快速交替
并行:多个人一起行走、
- CUP 多核,多个线程同时执行,线程池
6、wait/sleep区别?
7、线程的创建方式有哪几种?
8、ReadWriteLock 了解吗?
读的时候可以有多个线程去读,写的时候只能有一个线程去写
在了解什么是读写锁先了解
乐观锁:锁版本
悲观锁:锁对象
表锁:锁整个表,不会出现死锁
行锁:只锁一行,会出现死锁现象
读锁:共享锁,多人可以读,会发生死锁
写锁:独占锁,只能一个人写,会发生死锁
读写锁是一个更加细粒度的锁
9、谈谈线程池?线程池有哪些参数?有哪些拒绝策略?线程池的execute和submit区别?
本质就是优化系统的使用、不用频繁的创建的销毁,线程的复用
优势:降低资源的消耗、提高效率,方便管理,控制最大并发数
已存在的线程池:
自定义线程 :
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor();
7大参数
核心线程(正在使用中的),
最大可以支持(最大线程数),
设置时长(60),
设置时长单位(是秒、分、毫秒),//到这里如果超过了时间,发现你并没有没使用,会把核心以外的线程删除
阻塞队列(用来存放多余的不能执行的队列,很多队列是Integer.MAX,无界队列),
线程工厂(用什么样的工厂去产生,产生一个什么样的一个线程)
拒绝测略(如果,核心线程,非核心线程以及队列都满了,那么就会拒绝,需要自己定义)
线程池的拒绝策略:
线程池的execute和submit区别:(待补充)
10、CAS: 是什么 ?AQS:是什么?
CAS:
指的是 Compare and Swap , 它体现的是一种乐观锁的思想,无锁高并发的实现, 比如多个线程要对一个共享的整型变量执行 + 1 操作:
// 需要 不断的尝试获取
while(true){
int 旧值 = 共享变量 ; // 比如拿到了当前值 0
int 结果 = 旧值 + 1 ; // 在旧值 0 的基础上增加 1 ,正确结果是 1
/*
在这时候如果 别的线程把共享变量改成了 5 ,本线程的正确结果 1 就作废了,这时候
compareAndSwap 返回false,重试 直到 返回 true 表示我本线程 做修改 的同时,别的
线程没有干扰
*/
if( compareAndSwap(旧值,结果) ){
//成功, 退出循环
}
}
获取共享变量时,为了保证改变了的可见性,需要使用 volatile 修饰。结合 CAS 和 volatile 可以实现无锁并发,适用于竞争不激烈、多核 CPU 的场景下
CAS 底层依赖于一个 Unsafe 类来直接调用操作系统底层的 CAS 指令。
AQS:(待补充)
AQS指的是AbstractQuenedSynchronizer抽象的队列式同步器。是除了java自带的synchronized关键字之外的锁机制。
AQS采用的优先队列来解决并发问题,FIFO(First In First Out)先入先出思想。
10、mysql 的 性能优化问题 ?
硬盘和操作系统的层面优化、 也就是 硬件设施上的提高
影响mysql的性能因素主要是 cpu、 磁盘的读取速度、可用内存大小 、网络的带框,这一般都会交给我们的 DBA(数据库管理员) 或者 运维管理人员完成,重点关注服务本身所承载的体量,然后再提出合理的指标要求,避免出现资源浪费的情况
架构设计层面的优化
mysql 是一个 磁盘访问非常频繁 的关系型数据库 ,在高并发 和 高性能的场景中 ,mysql数据库必然会承受巨大的并发压力,此时优化的方式 可以分为一下几个部分
(1)搭建mysql的主从集群:单个mysql容易发生单点故障,一旦服务宕机将会导致依赖mysql数据库的服务全部无法响应,主从集群 或者 主主集群 都可以保存服务的高可用
(2)读写分离设计,在读多 写少的情况下,通过读写分离的方案可以避免读写的冲突,去避免读写冲突
(3)引入分库分表的机制通过分库可以降低单个服务节省的一个IO压力。通过分表的方式可以降低单表数据量从而去提升sql的查询效率
(4)针对热点数据可以引入更为高校的分布数据库比如redis,mongoDB等等,可以很好的缓解MySQL的访问压力,还能替身数据的检索性能
mysql程序配置的优化
一般可以通过my.cnf来完成
sql语句执行的优化:
sql 的查询一定要基于索引来进行数据扫描
避免索引失效的问题
使用索引扫描,联合索引中的列 ,从左往右,命中越多越好
尽可能使用sql语句用到的索引完成排序
查询语句使用 列信息 代替 * 查询
永远用小结果集驱动大的结果集
11、MySQL的索引?索引失效问题?使用索引的原因?索引的底层原理?SQL优化?
MySQL的索引:
普通索引(INDEX)、唯一索引(UNION)、主键索引(ID)、组合索引、全局索引(MyISAM 里)
索引失效问题:
索引失效的7种情况 - liehen2046 - 博客园 (cnblogs.com
使用索引的原因:
索引的底层原理: (待补充)
B+Tree
SQL优化:
sql优化主要是通过对慢sql进行 EXPLAIN 分析,对其可能用到的索引和实际走上的索引进行分析、对扫描行数进行分析
对于工作中有可能是再后续功能迭代的时候对sql进行了修改导致没有走上最优的索引,又或者是sql再添加条件时候组合索引没有覆盖到条件
又或者随着数据量的增加,已经修改sql无法提高查询的效率,只能采用相关的mysql优化问题
12、MySQL的存储引擎?存储原理?
MySQL存储引擎精讲
13、什么是聚簇索引和非聚簇索引?(待补充)
主键索引就是聚簇索引、只需要一次回表查询
14、什么是行锁?表锁?间隙锁?什么情况下行锁会升级为表锁?
行锁:
行锁是innodb存储引擎特有的细粒度锁,能够减少锁冲突问题
表锁:
表锁指的是对整张表锁住了
间隙锁:
间隙锁指的是对 区间行 锁住了,导致无法对这区间内的数据进行操作
什么情况下行锁会升级为表锁:(待补充)
15、高并发?
高并发
首先 什么是高并发?
高并发意味着大流量,需要运用技术手段来抵抗流量的冲击,这些手段就好比操纵流量,让流量能更平稳地被系统所处理,带给用户更好的体验。
常见的高并发有,双11、春运抢票、微博热点数据等等,除了这些典型的事情,每秒几十万的秒杀系统,每天千万级的定单系统等等也可以归并为高并发。不能只是但从数字上看,要更具实际的业务场景,就像不能说10w QPS的秒杀是高并发,而1w的信息流就不是高并发,信息流的处理的逻辑可能比秒杀系统的逻辑还要难上数倍。
业务都是从 0 做起来的,最重要的是在业务量逐渐变成原来的 10倍、100倍的过程中,是否用到了高并发的处理方法去演进你的系统,从架构设计、编码实现、甚至产品方案等维度去预防和解决高并发引起的问题?而不是一味的升级硬件、加机器做水平扩展。
16、高并发系统设计的目标是什么?(待补充)
先搞清楚高并发系统设计的目标,在此基础上再讨论设计方案和实践经验才有意义和针对性。
宏观目标
高并发绝不意味着只追求高性能,这是很多人片面的理解。从宏观角度看,高并发系统设计的目标有三个:高性能、高可用,以及高可扩展。
1、高性能:性能体现了系统的并行处理能力,在有限的硬件投入下,提高性能意味着节省成本。同时,性能也反映了用户体验,响应时间分别是100毫秒和1秒,给用户的感受是完全不同的。
2、高可用:表示系统可以正常服务的时间。一个全年不停机、无故障;另一个隔三差五出线上事故、宕机,用户肯定选择前者。另外,如果系统只能做到90%可用,也会大大拖累业务。
3、高扩展:表示系统的扩展能力,流量高峰时能否在短时间内完成扩容,更平稳地承接峰值流量,比如双11活动、明星离婚等热点事件。
17、高可用?(待补充)
高可用就是对原来的单体项目的缺陷进行迭代升级、原先的单体服务只要一个功能模块出了问题那么整个服务都变得不可用、为了解决问题将功能模块进行服务的划分单独部署。
集群搭建,是主要的解决思路
什么是redis
NoSQL( Not Only SQL
),意即不仅仅是SQL, 泛指非关系型的数据库。Nosql这个技术门类,早期就有人提出,发展至2009年趋势越发高涨。
redis 的热 key 问题
找出 热key , 通过 MQ 的 广播方式 , 去通知 全部的服务 在自己的模块中创建一个 二级缓存去存储这个 热key 和 value 值, 之后查询的时候走自己的缓存即可。
针对与 集群部署的 redis 就需要设计 随机分配 热key + ( 0~2 的随机数 ) , 通过 hash 槽 来分配是哪一个 redis 中写
什么是 docker ?
我认为docker就是一种轻量级的虚拟机是实现容器化技术的一个应用工具,从操作系统的层面对进程进行封装和隔离,由于独立于宿主和其他的隔离进程 所以也被称为容器
为什么要使用docker,优势有哪些?
占用资源小,它不需要进行硬件虚拟也不需要运行完整操作系统所带来的额外资源开销,使得docker对资源的利用率更高
启动快,docker容器应用由于直接运行在宿主的内核上不需要启动完整的操作系统,因此可以做到秒级别的启动
解决了环境不一致的问题,在别人的电脑上可以运行,但是下拉到我们的电脑上就不可以,而我们的docker是将我们应用和环境一起打包成一个镜像,可以实现我们的环境一致的问题
高效的迁移和部署,由于docker的特性,我们在部署docker应用项目的时候可以将我们的应用和环境打包成镜像push到仓库中,别的电脑想要使用就直接pull下来,大大减少了我们运维人员部署的成本
隔离级别的安全,原始的一台服务器中会存在多个应用,会出现环境版本不一致而导致应用之间崩溃问题,比如我一个应用A要用到mysql5.7,应用B要用到mysql8会导致操作起来很麻烦,而且如果mysql8启动需要暂用大量的资源,可能会将其他正常运行的环境杀死以确保它的正常运行,而docker是基于操作系统进程级别的隔离,对进程进行封装和隔离 资源的分配也是交给docker去操作,所以解决了这一问题
说说docker 中三个核心组件 image (镜像) 、 contaier (容器) 、Hub (仓库)
思考docker 怎么开启一个服务?通过开启一个镜像(image )去开启一个服务,而一个服务就是一个容器(contaier ),一个镜像可以开启多个服务,那么镜像从哪里来呢?就从 远程仓库(Hub )里获取 下载到我们的 本地仓库
镜像的操作命令:
容器的操作命令:
传统虚拟机和docker对比
传统:为了模拟线上环境,还得在安装一个vm虚拟机,然后再部署多个linux的操作系统,再在这些操作系统上运行我们的应用,
mysql -> 来宾虚操作系统要资源 -> vm虚拟机 -> 操作系统OS(宿主机) -> 硬件
应用 -> 虚拟操作系统 -> 虚拟机 -> 真正的物理内存
docker:
mysql -> docker引擎 -> 操作系统OS(宿主机) -> 硬件
省略了来宾操作系统 和 虚拟层