索引是数据库中提高查询效率的技术,类似于字典的目录
主要作用为了增加数据的查询速度,它的执行也是有一定条件的,不是加了索引就能够加快查询的效率,由于索引的创建实会占据内存空间的,mysql中通过Explain Select来查看索引的扫描次数。情况如下:
以下不适合加索引:
1:如果每次都需要取到所有表记录,无论如何都必须进行全表扫描了,那么是否加索引也没有意义了。
2、对非唯一的字段,例如“性别”这种大量重复值的字段,增加索引也没有什么意义。
3、对于记录比较少的表,增加索引不会带来速度的优化反而浪费了存储空间,因为索引是需要存储空间的,而且有个致命缺点是对于update/insert/delete的每次执行,字段的索引都必须重新计算更新
数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。
简单的说:事务就是将一堆的SQL语句(通常是增删改操作)绑定在一起执行,要么都执行成功,要么都执行失败,即都执行成功才算成功(事务的作用),否则就会恢复到这堆SQL执行之前的状态。
A:原子性:一个事物是不可再分的工作单位,该事物要么成功要么失败。
B:一致性:事物必须是使数据库从另外一个一致性状态到另一个一致性状态,与原子性密切相关。
C:持久性:指一个事物一旦提交后对数据库中数据的改变应该是永久不变的。
D:隔离性:一个事物的执行不能够被其他事物所干扰。
1.主键约束:实现实体的完整性(PK:主键),值唯一,不能为空,且可以自动递增
2.外键约束:用于多表之间的查询该表组建作为另外张表的外键建立标语标志就的关系(FK)
3.非空约束:(NOT NULL)保证该字段的内容不能为空null
4.唯一约束:列表的唯一性约束(UNIQUE)
5.检查约束:检查列的值是否满足一个boolean表达式(CHECK)
6.默认约束:给指定的字段可以设置默认值,不设置值时使用默认值而不是null
查询SQL尽量不要使用select *,而是具体字段(节约资源,减少网络开销)
尽量把过滤条件精细,能用and不用or(使用or可能会使索引失效,从而全表扫描)
使用varchar代替char(char按照声明大小存储,varchar按照数据实际长度储存,储存空间 小,节省空间)
尽量使用数值替代字符串类型
查询尽量避免返回大量数据
使用explain分析你SQL执行计划
索引设计最多5个,不能太多
(1)查询时,能不用* 就不用,尽量写全字段名。
(2)索引不是越多越好,每个表控制在6个索引以内。范围where条件的情况下,索引不起作用,比如where value<100
(3)大部分情况连接效率远大于子查询,但是有例外。当你对连接查询的效率都感到不能接受的时候可以试试用子查询,虽然大部分情况下你会更失望,但总有碰到惊喜的时候不是么…
(4)多用explain 和 profile分析查询语句
(5)有时候可以1条大的SQL可以分成几个小SQL顺序执行,分了速度会快很多。
(6)每隔一段时间用alter table table_name engine=innodb;优化表
(7)连接时注意:小表 jion 大表的原则
(8)学会用explain 和 profile判断是什么原因使你的SQL慢
(9)查看慢查询日志,找出执行时间长的SQL进行优化
(10)尽量避免使用order by
(11)因为where子句后面的条件是执行顺序是从右到左,所以尽量把能过滤掉大部分数据的条件放在最后
Spring的控制反转:把一个类放入到spring容器中,对象的创建、初始化、销毁等工作交给spring容器来做。由spring容器控制对象的生命周期。
AOP把系统分为两部分,核心关注点和横切关注点。核心主要处理业务逻辑,横切主要是权限验证,日志,事物处理等。
AOP主要由:方面(Aspect)一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现
连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
通知(Advice):
1.前置通知before 方法执行前要执行的功能 2.后置通知after 方法执行后要执行的功能
3.返回后通知afterReturning 方法执行返回结果 4.异常通知afterThrowing。5.环绕通知around 方法执行前和后都要执行的功能
切入点(Pointcut): Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
引入(Introduction)Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。
AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。
SpringMVC严格上来说是一种设计思想而不是设计模式,其底层采用反射的机制构建工程,适配器,代理模式构建。
#能够有效防止SQL的注入攻击,并且是预编译的SQL
#还能够对传入的数值当成一个字符串,会对自动传入的数据加上一个双引号。
如:where name=#{name} 如果传入的值是jack,那么解析成的SQL是:where name=“jack”
$会将传入的值直接显示在sql中,会导致异常 并且不能防止sql的攻击,且相对低效
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)中构建出SqlSessionFactory(SqlSessionFactory是线程安全的);
然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。
说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的(对应着我们的model对象中的实体),而resultMap则是对外部ResultMap的引用(提前定义了db和model之间的隐射key–>value关系),但是resultType跟resultMap不能同时存在。
在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。
(1)当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实 MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。
(2)当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。
(1) FROM [left_table] 选择表
(2) ON
(3)
(4) WHERE
(5) GROUP BY
(6) AGG_FUNC(column or expression),… 聚合
(7) HAVING
(8) SELECT (9) DISTINCT column,… 选择字段、去重
(9) ORDER BY
(10) LIMIT count OFFSET count; 分页
LRU也就是“最近最少使用”,LRU缓存就是使用这种原理实现的,就是缓存一定数量的数据,当超过该数据的阈值时就把相关的数据删除掉,例如我们缓存10000条数据,当小于该数据时可以随意的增加,超过时就将过期的数据删除掉。
好比java中实现LRU就有两种方式:一是LinkedHashMap,一种是自己设计的数据结构,使用链表+HashMap。
1.get请求用来从服务器上获得资源,而post是用来向服务器提交数据;
2.get将表单中数据按照name=value的形式,添加到action 所指向的URL 后面,并且两者使用"?“连接,而各个变量之间使用”&“连接;post是将表单中的数据放在HTTP协议的请求头或消息体中,传递到action所指向URL;
3.get传输的数据要受到URL长度限制(1024字节);而post可以传输大量的数据, POST数据是没有限制的,上传文件通常要使用post方式;
4.使用get时参数会显示在地址栏上,如果这些数据不是敏感数据,那么可以使用get;对于敏感数据还是应用使用post;
5.get使用MIME类型application/x-www-form-urlencoded的URL编码(也叫百分号编码)文本的格式传递参数,保证被传送的参数由遵循规范的文本组成,例如一个空格的编码是”%20"。
6.Jsp页面中的FORM标签里的method属性为get时调用doGet(),为post时调用doPost()。
SQL注入:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。
防止的方法:
1.永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等。
2.永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
4.不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。
在网页中,一个元素占有空间的大小由几个部分构成,其中包括元素的内容(content),元素的内边距(padding),元素的边框(border),元素的外边距(margin)四个部分。这四个部分占有的空间中,有的部分可以显示相应的内容,而有的部分只用来分隔相邻的区域。4个部分一起构成了css中元素的盒模型。
1.href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。
2.src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a:hover, li:nth-child)
M: Model 模型层
V: View视图层
VM: ViewModel 视图模型控制
vue是实现了双向数据绑定的mvvm框架,当视图改变更新模型层,当模型层改变更新视图层。
在vue中,使用了双向绑定技术,就是View的变化能实时让Model发生变化,而Model的变化也能实时更新到View。
vue-router是用来定义路由规则的
组件: 1.router-link 2.router-view
答:
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些
答:总共分为8个阶段 1.创建前/后,2.载入前/后,3.更新前/后,4.销毁前/后。
1.创建前/后: 在beforeCreated阶段,vue实例的挂载元素 e l 和 ∗ ∗ 数 据 对 象 ∗ ∗ d a t a 都 为 u n d e f i n e d , 还 未 初 始 化 。 2. 在 c r e a t e d 阶 段 , v u e 实 例 的 数 据 对 象 d a t a 有 了 , el和**数据对象**data都为undefined,还未初始化。 2.在created阶段,vue实例的数据对象data有了, el和∗∗数据对象∗∗data都为undefined,还未初始化。2.在created阶段,vue实例的数据对象data有了,el还没有。
载入前/后:
3.在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。
4.在mounted阶段,vue实例挂载完成,data.message成功渲染。
5.更新前/后:当data变化时,会触发beforeUpdate和updated方法。
6.销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。
启动器是一套方便的依赖没描述符,它可以放在自己的程序中。你可以一站式的获取你所需要的 Spring 和相关技术,而不需要依赖描述符的通过示例代码搜索和复制黏贴的负载。
真正做到开箱即用
Spring Boot 也提供了其它的启动器项目包括,包括用于开发特定类型应用程序的典型依赖项。
spring-boot-starter-web-services - SOAP Web Services
spring-boot-starter-web - Web 和 RESTful 应用程序
spring-boot-starter-test - 单元测试和集成测试
spring-boot-starter-jdbc - 传统的 JDBC
spring-boot-starter-hateoas - 为服务添加 HATEOAS 功能
spring-boot-starter-security - 使用 SpringSecurity 进行身份验证和授权
spring-boot-starter-data-jpa - 带有 Hibeernate 的 Spring Data JPA
spring-boot-starter-data-rest - 使用 Spring Data REST 公布简单的 REST 服务
主要回答: spring-boot-maven-plugin 提供了一些像 jar 一样打包或者运行应用程序的命令。
扩展:
spring-boot:run 运行你的 SpringBooty 应用程序。
spring-boot:repackage 重新打包你的 jar 包或者是 war 包使其可执行
spring-boot:start 和 spring-boot:stop 管理 Spring Boot 应用程序的生命周期(也可以说是为了集成测试)。
spring-boot:build-info 生成执行器可以使用的构造信息。
ps -aux 或者ps -elf
路径: 使用vi或者vim编辑器编辑网卡配置文件/etc/sysconfig/network-scripts/ifcft-eth0(网卡文件名称可变)
重启服务: service network restart
1.启动 ./nginx
2.停止 nginx -s stop 或 nginx -s quit
3.重启 ./nginx -s reload(平滑重启) 或 service nginx reload 。
4.查看nginx版本 nginx -v 。
5.检查配置文件是否正确 nginx -t 。
正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标原始
服务 器,然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。
特点:
1.客户端可以使用正向代理(正向代理是客户端代理)
2.正向代理 用户非常清楚自己访问服务器的地址, 服务器不知道真实的请求者是谁
3.应用场景: 美团外卖,滴滴打车,路由器机制
反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,
即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,
无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机
来降低网络和服务器的负载,提高访问效率。
特点:
1. 服务器端使用反向代理( 服务器端代理)
2. 反向代理 用户访问服务器时,用户不清楚真实的服务器到底是谁, 服务器清楚是谁访问的.
3. 使用场景: 一般服务器端都是反向代理
1.轮询机制 根据配置文件的顺序,依次访问服务器. 默认的负载均衡策略
2.权重策略 如果需要设定访问服务器的频次(某个访问的多,某个访问的少),可以通过权重的策略实现.
例如: server localhost:8091 weight=9;
3.IPHASH 如果需要用户与服务器进行绑定时,则设定IPHash
1.跨平台、配置简单。
2.非阻塞、高并发连接 2-3 万并发连接数,官方监测能支持 5 万并发。
3.内存消耗小 1个服务不超过2M
4.成本低廉,且开源。
5.稳定性高,宕机的概率非常小。
1. 如果浏览器的网址与Ajax请求网址必须满足同源策略.则浏览器才能解析Ajax,执行正确的请求.
2. 同源策略规定
规定要求:请求协议://域名:端口号
。1.如果3者都满足,则符合同源策略.浏览器可以正确解析.
。2.反之(有一个不满足)不满足同源策略.称之为跨域请求 则浏览器不能正常解析Ajax请求.
3.跨域解决方案:
。1.JSONP(以前使用)
。2.CORS(跨域资源共享)
CORS是一个W3C标准,全称跨域资源共享(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
如果实现跨域资源共享,则需要单独配置服务端即可. 只需要将允许访问的页面的网址,通过响应头的形式进行设定.则可以实现跨域请求
为什么需要分布式架构?
1)增大系统容量。当业务量越来越大时,一台机器容量已经无法满足了,我们就需要多台机器。所以,我们需要垂直或是水平拆分业务系统,让其变成一个分布式的架构。
2)加强系统可用。当所有业务都部署在一台机器上的时候,一旦机器出故障就会导致整体不可用。所以,需要通过分布式架构来冗余系统以消除单点故障,从而提高系统的可用性。
分布式架构有什么优势?
1)实现更大数据量的存储。
2)可以提高系统的高可用性。
3)提高系统的可重用性。
4)可更好提高系统的性能。
分布式架构有什么劣势?
采用任何技术方案都是“按下葫芦浮起瓢”,都是有得有失,分布式架构也有劣势,具体如下:
1)会增加架构设计的难度。
2)部署和维护的成本也会加大。
分布式系统架构的难点在于系统设计,以及管理和运维。所以,分布式架构解决了“单
点”和“性能容量”的问题,但却新增了一堆问题。
分布式架构设计有什么难点?
1)异构系统的不标准问题?(软件、协议、格式、运维的不标准)
2)系统架构中的服务依赖问题?(多米诺骨牌效性,一个服务宕机)
3)故障发生的概率更大?(故障恢复时间、影响面)
4)多层架构的运维复杂度更大?(基础层-硬件、平台层-中间件、应用层-业务、接入层-网关)
分布式架构设计的目的?
1)提高整体架构的吞吐量,服务更多的并发和流量。
2)提高系统的稳定性,让系统的可用性更高。
如何基于架构设计提高其性能?
1)缓存系统。加入缓存系统,可以有效地提高系统的访问能力。从前端的浏览器,到网络,再到后端的服务,底层的数据库、文件系统、硬盘和CPU,全都有缓存,这是提高快速访问能力最有效的手段。
2)负载均衡系统。负载均衡是做水平扩展的关键技术。其可以用多台机器来共同分担一部分流量请求。
3)异步调用。异步系统主要通过消息队列来对请求做排队处理,这样可以把前端的请求的峰值给“削平”了,而后端通过自己能够处理的速度来处理请求。
4)数据分区和数据镜像。数据分区是把数据按一定的方式分成多个区(比如通过地理位置),不同的数据区来分担不同区的流量。
如何基于架构提高系统的稳定性?
1)服务拆分,主要有两个目的:一是为了隔离故障,二是为了重用服务模块。
2)服务冗余,可以去除单点故障,并可以支持服务的弹性伸缩,以及故障迁移。
3)限流降级,当系统实在扛不住压力时,只能通过限流或者功能降级的方式来停掉一部分服务,或是拒绝一部分用户,以确保整个架构不会挂掉。
4)高可用架构,从冗余架构的角度来保障可用性。比如,灾备多活,或是数据可以在其中复制保持一致性的集群。
5)高可用运维,指的是DevOps中的CI(持续集成)/CD(持续部署)。一个良好的运维应做了足够的自动化测试,做了相应的灰度发布,以及对线上系统的自动化控制。这样,可以做到“计划内”或是“非计划内”的宕机事件的时长最短。
分布式架构有哪些关键技术?
1)服务治理。服务治理的最大意义是需要把服务间的依赖关系、服务调用链,以及关键的服务给梳理出来,并对这些服务进行性能和可用性方面的管理。
2)架构管理。基于服务所形成的架构需要有架构版本管理、整体架构的生命周期管理,以及对服务的编排、聚合、事务处理等服务调度功能。
3)DevOps。分布式系统可以更为快速地更新服务,但是对于服务的测试和部署都会是挑战。所以,还需要DevOps的全流程,其中包括环境构建、持续集成、持续部署等。 自动化运维。有了DevOps后,我们就可以对服务进行自动伸缩、故障迁移、配置管理、状态管理等 一系列的自动化运维技术了。
4)资源调度管理。应用层的自动化运维需要基础层的调度支持,也就是云计算IaaS层的计算、存储、 网络等资源调度、隔离和管理。
5)整体架构监控。如果没有一个好的监控系统,那么自动化运维和资源调度管理只可能成为一个泡影, 因为监控系统是你的眼睛。没有眼睛,没有数据,就无法进行高效的运维。所以说,监控是非常重要 的部分。这里的监控需要对三层系统(应用层、中间件层、基础层)进行监控。
6)流量控制。最后是我们的流量控制,负载均衡、服务路由、熔断、降级、限流等和流量相关的调度都 会在这里,包括灰度发布之类的功能也在这里。
能说说你对CAP的理解吗?
1)分布式系统设计中的CAP指的是什么:
C:一致性(Consistency),每次访问都能获得最新数据但可能会出现错误的响应。
A:可用性(Availability),每次访问都能收到非错响应,但不能保证获取最新数据。
P:分区容错性(Partition Tolerance),在任意分区网络故障的情况下系统仍能继续运行。
2)分布式系统中的CAP设计不可能三者都满足。
在一个分布式系统中,首先网络是不可靠的,我们的系统就需要支持分区容错,然后需要在软件可用性和一致性之间做出取舍,也就是鱼和熊掌不能兼得。
CP:一致性和分区容错性,等待分区节点的响应可能会导致延时错误。如果你的业务需求需要原子读写,CP 是一个不错的选择。
AP:可用性与分区容错性,响应节点上可用数据的最近版本可能并不是最新的。当分区解析完后,写入(操作)可能需要一些时间来传播。如果业务需求允许最终一致性,或当有外部故障时要求系统继续运行,AP 是一个不错的选择。
说说你对Linux系统的认识?
Linux系统启动,重启、退出的常用指令?
说几个Linux系统下常用的文件操作?
Linux系统中的防火墙操作有哪些?
Linux 系统的中的进程操作指令你了解哪些?
Linux 系统中的你是如何查找文件的?
Linux 系统中的浏览文件的内容的指令有哪些?
Linux 系统中文件的打包和压缩、解压缩是如何实现的?
你是如何理解vi和vim的?
vim下有几种工作模式?
Linux平台下的网络配置指令常用的有哪些?
Linux平台下的用户和用户组操作?
你了解linux平台下的shell编程吗?
Linux平台下你自己安装过哪些软件?
Docker是什么?
为什么要选择Docker?
如何理解Docker中的镜像和容器?
Docker的安装方式是怎样的?
Docker在线安装的基本步骤是怎样的?
Docker支持的常用基本操作有哪些?
Docker进行数据管理的方式有哪些?
Docker的数据卷你是如何理解的?
Docker镜像如何制作?
Docker下如何实现容器互联?
Redis 是什么?(key/value数据库)
Redis 现在最新版本是什么?(6.22)
Redis 的版本如何进行查看?(redis-server -v,redis-cli -v)
Redis 默认有多少个数据库?(16个)
Redis 的核心配置文件是哪个?(redis.conf)
Redis 的常用配置参数有哪些?(适当说几个)
Redis 支持的数据类型有哪些?(String,Hash,List,Set,Stream等)
Redis 支持的数据基本操作有哪些?(Set,Get,Del等)
Redis 支持的字符串操作有哪些?
incr/incrby,decr/decrby,append,strlen,mset/mget
Redis 中的key的有效时长如何设置(expire,pexpire)
Redis 支持的hash操作有哪些?
hset/hget,hincrby,hmset/hmget,hexists,hdel,hlen,hkeys/hvals
Redis 持久化数据的方式有哪些?(AOF和RDB)
Redis 是如何解决哈希冲突的?(同一个哈希桶中的多个元素用同一个链表来保存)
Redis 中的refresh操作用于解决什么问题?(哈希桶中的链表长度越大性能越低)
Redis 中的单线程模型如何理解?(Redis网络 IO 和键值对读写由一个线程完成)
Redis 在你项目中是通过什么API访问的?
Redis为什么要设计单线程模型?
1)单线程减少了cpu资源的争用,避免了上下文的切换。
2)基于内存读写,单线程读写耗时更少。
Redis在单线程模式下为什么还那么快?
1)纯内存操作
2)核心是基于非阻塞的IO多路复用机制
3)单线程反而避免了多线程的频繁上下文切换问题
Reids 持久化的意义?
redis持久化的意义,在于故障恢复,数据恢复,也可以归类到高可用的一个环节里面去。比如你redis整个挂了,然后redis就不可用了,你要做的事情是让redis变得可用,尽快变得可用。如果redis重启了,没有持久化的话,redis就会丢失所有的数据,如果通过持久化将数据搞一份儿在磁盘上去,然后定期比如说同步和备份到一些云存储服务上去,那么就可以保证数据不丢失全部,还是可以恢复一部分数据回来的。
如何理解redis中RDB方式的持久化?
RDB 记录的是某一时刻的数据,而且是全量快照。RDB方式会对redis中的数据执行周期性的持久化或手动save操作实现持久化。
Redis中的RDB方式持久化中的save和bgsave有什么不同?
Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave。其中,SAVE保存是阻塞主线程,客户端无法连接redis,等SAVE完成后,主线程才开始工作,客户端可以连接。bgsave会由主线程fork一个save操作的子进程,bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。在执行save过程中,不影响主进程,客户端可以正常链接redis,等子进程fork执行save完成后,通知主进程,子进程关闭。
Redis中RDB方式持久化的优点?
第一:RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说Amazon的S3云服务上去,在国内可以是阿里云的ODPS分布式存储上,以预定好的备份策略来定期备份redis中的数据
第二:RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可。
第三:相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速
Redis中RDB方式持久化的缺点?
第一:如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好。一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据
第二:RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,甚至是数秒。
如何理解Redis中的“写后”日志?
AOF 日志正好相反,是写后日志:“写后”的意思是 Redis 是先执行命令,把数据写入内存,然后才记录日志。传统数据库的日志,例如 redo log(重做日志),记录的是修改后的数据,而 AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。
Redis中AOF方式的写后日志有什么优点?
为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。而写后日志这种方式,就是先让系统执行命令,只有命令能执行成功,才会被记录到日志中,否则,系统就会直接向客户端报错。同时也不会阻塞当前的写操作。
Redis中AOF方式的写后日志有什么风险?
如果刚执行完一个命令,还没有来得及记日志就宕机了,那么这个命令和相应的数据就有丢失的风险。如果此时 Redis 是用作缓存,还可以从后端数据库重新读入数据进行恢复,但是,如果 Redis 是直接用作数据库的话,此时,因为命令没有记入日志,所以就无法用日志进行恢复了。
AOF 虽然避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。这是因为,AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。
Redis中AOF方式的写后日志有什么策略?
1)Always:同步写,可靠性高数据基本不丢,但每个写命令都要落盘,性能较差
2)Everysec:每秒写,性能适中,宕机时可能回丢失1秒的数据
3)No: 操作系统控制的的写,性能好,当即时丢失数据较多。
Redis中AOF方式持久化的优点?
第一:AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据
第二:AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复
第三:AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在rewrite log的时候,会对其中的指导进行压缩,创建出一份需要恢复数据的最小日志出来。再创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件ready的时候,再交换新老日志文件即可。
第四:AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据
Redis中AOF方式持久化的缺点?
第一:对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
第二:AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的
第三:以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。
Redis 中的持久化机制该如何选择?
1)数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择;
2)如果允许分钟级别的数据丢失,可以只使用 RDB;
3)如果只用 AOF,优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个平衡。
Redis 底层设计上都支持哪些数据结构?
Redis 为了平衡空间和时间效率,针对 value 的具体类型在底层会采用不同的数据结构来实现,有简单动态数组SDS、链表、字典、跳跃链表、整数集合、压缩列表、对象等,其中哈希表和压缩列表是复用比较多的数据结构,如图所示:
Redis中分片的应用场景和原理?
Redis中的分片思想就是把鸡蛋放到不同的篮子中进行存储。因为一个redis服务的存储能力是有限。分片就是实现redis扩容的一种有效方案。
Redis中的多路复用机制是如何实现的?
Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制
Redis中的哨兵机制你是如何理解的?
哨兵其实就是一个运行在特殊模式下的 Redis 进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。
Redis的高性能如何保证?
线程模型,数据结构,持久化,网络模型
Redis的高可靠性如何保证?(持久化,主从复制,哨兵机制)
Redis 的高可靠性有两层含义:第一,数据尽量少丢失,通过 AOF 和 RDB 进行保证。第二,服务尽量少中断,通过增加副本冗余量保证,将一份数据同时保存在多个实例上。即使有一个实例出现了故障,需要过一段时间才能恢复,其他实例也可以对外提供服务,不会影响业务使用。
Redis的高可扩展性如何保证?
数据分片+负载均衡
Redis 要支持10万的QPS该如何玩?
单机的redis几乎不太可能说QPS超过10万+,除非一些特殊情况,比如你的机器性能特别好,配置特别高,物理机,维护做的特别好,而且你的整体的操作不是太复杂,一般的单机也就在几万。
真正实现redis的高并发,需要读写分离,对缓存,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就一秒钟几千,一两千。大量的请求都是读,一秒钟二十万次读。所以redis的高并发可以这样玩:主从架构 -> 读写分离 -> 支撑10万+读QPS的架构
如何理解正向和反向代理?
正向代理服务器一般都是客户端代理,代理客户端执行业务,反向代理服务器一般都是服务器端代理.用户无需关心真实的服务器是谁.
Nginx是什么?
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强。
Nginx主要用于解决什么问题?
反向代理、请求的转发、负载均衡等。
你现在用的Nginx是什么版本?
Nginx 的基础架构是怎样的?
nginx 是由一个 master 管理进程,多个 worker 进程(处理工作)。基础架构设计如图所示:
其中,master 负责管理 worker 进程,worker 进程负责处理网络事件。整个框架被设计为一种依赖事件驱动、异步、非阻塞的模式。
Nginx 的进程管理模型有什么优点?
1)可以充分利用多核机器,增强并发处理能力。
2)多 worker 间可以实现负载均衡。
3)Master 监控并统一管理 worker 行为。在 worker 异常后,可以主动拉起 worker 进程,从而提升了系统的可靠性。并且由 Master 进程控制服务运行中的程序升级、配置项修改等操作,从而增强了整体的动态可扩展与热更的能力。
Nginx的核心配置文件是哪个文件?
Nginx.conf
Docker平台下Nginx配置的结构是怎样的?
嵌套结构,在nginx.conf文件内部嵌套了default.conf文件,我们所需要做的大部分修改,直接在default.conf文件中进行即可。
说几个Nginx配置文件中关键元素?
server、upstream、。。。
1)采用独立的进程,可以让互相之间不会影响。一个进程异常崩溃,其他进程的服务不会中断,提升了架构的可靠性。
2)进程之间不共享资源,不需要加锁,所以省掉了锁带来的开销。
1)进程数已经等于核心数,再新建线程处理任务,只会抢占现有进程,增加切换代价。
2)作为接入层,基本上都是数据转发业务,网络 IO 任务的等待耗时部分,已经被处理为非阻塞/全异步/事件驱动模式,在没有更多 CPU 的情况下,再利用多线程处理,意义不大。并且如果进程中有阻塞的处理逻辑,应该由各个业务进行解决,比如 openResty 中利用了 Lua 协程,对阻塞业务进行了优化。
6总结(Summary)
6.1重难点分析
…
6.2FAQ分析
……
6.3Bug分析