随便学学3.0
Spring Boot、Spring MVC和Spring有什么区别
Spring是一个IO容器,用来管理Bean,使用依赖注入实现控制反转,可以很方便的整合各种框架,提供AOP机制弥补OOP的代码服用问题,更方便将不同类不同方法中的共同处理抽取成切面,自动注入给方法执行,比如日志、异常等
Springmvc是spring对web框架的一个解决方案,提供了一个总的前端控制器Servlet,用来接收请求
Springboot是spring提供的一个快速开发工具包,让程序员能更方便、更快速的开发spring+springmvc应用,简化了配置(约定了默认配置)约定大于配置
SpringMVC工作流程:
- 用户发送请求到前端控制器DispatcherServlet
- DispatcherServlet收到请求调用HandlerMapping处理器映射器
- 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器及处理器拦截器(有过有则生成)一并返回给DispatcherServlet
- DispatcherServlet调用HandlerAdapter处理器适配器
- HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)
- Controller执行完成返回ModelAndView
- HandlerAdapter将controller执行结果返回给DispatcherServlet
- DispatcherServlet将ModelAndView传给ViewReslover视图解析器
- ViewResolver解析后返回具体View
- Dispatcher根据View进行渲染视图
- DispatcherServlet响应用户
Spring MVC的主要组件
- HandlerMappring处理器映射器,根据用户请求的资源url来查找Handler。
- HandlerAdapter处理器适配器。
- HandlerExceptionResolver专门用来处理异常
- ViewResolver视图解析器
- RequestToViewNameTranslator从request获取viewname
- LocaleResolver国际化的时候用到了
- ThemeResolverr用于解析主题,找到资源的名称
- MultipartResolver用于处理上传请求
- FlashMapManager主要用在redirect中传递参数
Spring Boot自动装配的原理
@Import+@Configuration+@Bean+Spring spi机制
自动配置类有各个starter提供,使用@Configuration+@Bean定义配置类,放到META-INF/spring.factories下
使用Spring spi扫描META-INF/spring.factories下的配置类
使用@Import导入自动配置类
如何理解Spring Boot中的Starter
使用spring+springmvc的时候,如果需要引入mybatis等框架,需要到xml中定义mybatis需要的bean
starter就是定义一个starter的jar包,写一个@Configuration配置类、将这些bean定义在里面,然后在starter包的META-INF/spring.fatories中写入该配置类,springboot会按照约定来加载该配置类
开发人员只需要将相应的starter包依赖进应用,进行相应的属性配置(使用默认配置时,不需要手动配置),就可以直接使用相应的功能
Mybatis的优缺点
优点:
- 基于SQL语句编写,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL卸载XML里,解除sql与程序代码的耦合,便于做统一管理;提供xml标签,支持编写动态SQL语句
- 与JDBC相比,大大减少了代码量,消除了JDBC大量冗余的代码,不需要手动开关连接
- 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)
- 能够与Spring很好的集成
- 提供映射标签,支持对象与数据库ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
缺点:
- SQL语句的编写工作量大,尤其当字段多,关联表多的时候
- SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库
索引的基本原理
索引的原理:就是把无序的数据变成有序的查询
- 把创建了索引的列的内容进行排序
- 对排序结果生成倒排表
- 在倒排表内容上拼上数据地址链
- 在查询的时候,先拿到倒排表内容,再取出数据地址链,从而拿到具体数据
Mysql聚簇索引和非聚簇索引的区别
都是B+树的数据结构
- 聚簇索引:将数据存储与索引放到了一块,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的
- 非聚簇索引:叶子节点不存储数据,存储的是数据行地址,也就是说根据索引查到找数据行的位置再取磁盘查找数据
聚簇索引的优势:
- 查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询效率高
- 聚簇索引对于范围查询的效率很高
- 聚簇索引适合用在排序的场合
劣势:
- 维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(page split)的时候。
- 表因为使用UUId(随机ID)作为主键,使数据存储稀疏
- 如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值;过长的主键值,会导致非叶子节点占用占用更多的物理空间
索引的原则
查询更快、占空间更小
- 索引不是越多越好
- 不要对经常变动的数据加索引
- 小数据量的表不需要加索引
- 索引一般加在常用来查询的字段上
Mysql事务的基本特性和隔离级别
事务基本特性ACID分别是:
原子性指的是一个事务中的操作要么全部成功,要么全部失败。
一致性指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。
隔离性指的是一个事务的修改在最终提交前,对其他事务是不可见的。
持久性指的是一旦事务提交,所做的修改就会永久保存到数据库中。
隔离性有4个隔离级别,分别是:
- read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫做脏读。
- read commit 读已提交,两次读取结果不一致,叫做不可重复读。
- repeatable read 可重复读,这是mysql的默认级别,就是每次读取结果都一样,但是有可能产生幻读。
- serializable 串行,一般不使用,他会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题。
脏读:某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个回滚了操作,则后一个事务所读取的数据就会是不正确的。
不可重复读:当前事务先进行了一次数据读取,然后再次读取到的数据是别的事务修改成功的数据,导致两次读取到的数据不匹配
幻读:当前事务读第一次取到的数据比后来读取到数据条目少,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
ACID靠什么保证的
A原子性由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql
C一致性由其他三大特性保证、程序代码要保证业务上的一致性
I隔离性由MVCC来保证
D持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,宕机的时候可以从redo log恢复
对慢查询的优化
- 首先分析语句,看是否加载了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。
- 分析语句的执行计划,然后获得其索引使用情况,之后修改语句或修改索引,使得语句可以尽可能地命中索引。
- 如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。
Cookies和Session的区别
- cookie数据存放在客户端,session数据存放在服务器端
- cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗
- session会在一定时间内保存在服务器上,当访问增多,会比较占用服务器的性能
- 单个cookie在客户端的限制是3k
mysql主从同步原理
mysql主从同步的过程:
mysql的主从复制中主要有三个线程:master(binlog dump thread)、slave(I/O thread、SQL thread)
- 主节点binlog,主从复制的基础是主库记录数据库的所有变更到binlog。binlog是数据库服务器启动的那一刻起,保存所有修改数据库结构或内容的一个文件。
- 主节点log dump线程,当binlog有变动时,log dump线程读取其内容并发送给从节点
- 从节点I/O线程接收binlog内容,并将其写入到relay log文件中。
- 从节点的SQL线程读取relay log文件内容对数据进行更新,最终保证主从数据库的一致性。
由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。
全同步复制
主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是性能会受到严重影响
半同步复制
从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
MyISAM和InnoDB的区别
MyISAM:
不支持事务,但是每次查询都是原子的
支持表级锁,每次操作是对整个表加锁
存储表的总行数
一个MyISAM表有三个文件:索引文件、表结构文件、数据文件
采用非聚簇索引,索引文件的数据域存储只想数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。
InnoDb:
支持ACID的事务,支持事务的四种隔离级别
支持行级锁及外键约束,因此可以支持写并发
不存储总行数
主键索引采用聚簇索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整
索引的类型及对数据库的性能影响
- 主键索引(PRIMARY KEY)
- 唯一的标识,主键不可重复,只能有一个列作为主键
- 唯一索引(UNIQUE KEY)
- 不允许具有索引值相同的行,多个列都可以标识为唯一索引
- 常规索引(KEY/INDEX)
- 默认的,index,key关键字来设置
- 全文索引(FullText)
- 在特定的数据库引擎下才有,MyISAM MongoDB
- 快速定位数据
索引可以极大的提高数据的擦汗寻速度
通过使用索引,可以在查询的过程中,提高系统的性能,但是会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件,索引需要占用物理空间
Redis中RDB和AOF机制
RDB:
在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
优点:
- 整个Redis数据库将只包含一个文件dump.rdb,方便持久化。
- 容灾性好,方便备份。
- 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能。
- 相对于数据量大的时候,比AOF的启动效率更高。
缺点:
- 数据安全性低。RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候
- 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
AOF:
以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录
- 优点:
- 数据安全,Redis中提供了3钟同步策略,即每秒同步、每修改同步和不同步。每秒同步也是异步完成的,其效率也是非常高的,不过一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。
- 通过append模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过reids-check-aof工具解决一致性问题。
- AOF机制的rewrite模式,定期对AOF文件进行重写,可以达到压缩的效果
- 缺点:
- AOF文件比RDB文件大,且恢复速度慢
- 数据量大的时候,比rdb启动效率低
- 运行效率没有RDB高
AOF文件比RDB更新频率高,优先使用AOF还原数据
AOF比RDB更安全也更大
RDB性能比AOF好
如果都配了优先加载AOF
Redis的过期键的删除策略
- 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清楚。该策略可以最大化的节省CPU资源,却对内存非常不友好,极端情况可能出现大量的过期key没有再次被访问,从而不会被清楚,占用大量内存。
- 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires自带你钟一定数量的key,并清除其中已过期的key。
Redis钟同时使用了惰性过期和定期过期两种策略。
Redis线程模型、单线程快的原因
Redis基于Reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器 file event handler。这个文件事件处理器,是单线程的,所以 Redis 被叫做单线程的模型,
单线程快的原因:
- 纯内存操作
- 核心是基于非阻塞的IO多路复用机制
- 单线程反而避免了多线程频繁上下文切换带来的性能问题
redis哨兵模式
sentinel,哨兵是 redis 集群中非常重要的一个组件,主要有以下功能:
- 集群监控:负责监控redis master和slave进程是否正常工作。
- 消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
- 故障转移:如果master挂掉了,会自动转移到slave上
- 配置中心:如果故障转移发生了,通知客户端新的master地址
哨兵用于实现 redis 集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。
- 故障转移时,判断一个master node是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举
- 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的
- 哨兵通常需要3个实例,来保证自己的健壮性。
- 哨兵+redis主从的部署架构,是不保证数据零丢失的,只能保证redis集群的高可用性。
- 对于哨兵+redis主从这种复杂的部署架构,尽量在测试环境和生产环境都进行充足的测试和演练。
缓存雪崩、缓存穿透、缓存击穿
缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉
解决方案:
- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
- 给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失败,则更新数据缓存。
- 缓存预热
- 互斥锁
缓存穿透是指缓存和数据库钟都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:
- 接口层增加校验,如用户及鉴权校验,id做基础校验,id<=0的直接拦截
- 从缓存取不到的数据,在数据库中也没有渠道,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
- 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案
- 设置热点数据永不过期
- 加互斥锁
原文地址:https://www.cnblogs.com/gc5132/p/15168250.html
- map
- hdu----(3068)最长回文(manacher)
- hdu---(1280)前m大的数(计数排序)
- 程序员你为什么这么累【续】:编码习惯之Controller规范
- go-nsq使用简述
- hdu---(4515)小Q系列故事——世界上最遥远的距离(模拟题)
- 利用sys schema解决一次诡异的语句hang问题
- hdu----(4513)吉哥系列故事——完美队形II(manacher(最长回文串算法))
- 学习manacher(最长公共回文串算法)
- Apache Spark 2.3 加入支持Native Kubernetes及新特性文档下载
- Oracle 12c 多租户专题|隔离PDB的磁盘IO
- golang 裸写一个pool池控制协程的大小
- 2014---多校训练2(ZCC Loves Codefires)
- 完整的golang 多协程+信道 任务处理示例
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- TypeScript里一些特殊的类型
- TypeScript的类型断言,有点像ABAP的强制类型转换
- 什么是TypeScript的字符串索引签名
- [初探] proxy 的优势与使用场景
- TypeScript里的interface和class以及对应的JavaScript代码
- TypeScript里的interface扩展,多继承以及对应的JavaScript代码
- TypeScript里的混合类型
- 完全图解 HTTPS
- TypeScript里的完整函数定义语法
- TypeScript里的类型为any和泛型的区别
- 乐观锁、悲观锁,这一篇就够了!
- 面向切片编程(AOP)应用的一些实际例子
- 计数计量单位KMGTPEZY【计算机】【天文】
- 不用临时的变量 优雅、高效的交换两个数方法
- SAP offline OData插件的JavaScript代码是如何调用到Android平台的Java代码的