技术标签: java mybatis mysql redis springmvc
MyBatis提供了一级缓存和二级缓存
IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,IOC(控制反转),将创建对象的控制权由自己把控转移到spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系;
DI(依赖注入),将对象之间的依赖关系交由框架处理,减低组件之间的耦合性,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
AOP(面向切面编程)可以说是OOP的补充和完善.AOP将相同的业务逻辑按照横向切割的方式抽取到一个独立的模块中形成切面,将通知织入到方法连接点前后,底层使用的是动态代理
① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
1.原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用
2.一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的。
3.隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的
4.持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响
脏读一个事务读到另一个事务未提交的更新数据
幻读是一个事务在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行。
不可重复读是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据
就是一个事务读到另一个事务修改后并提交的数据。在同一个事务中,对于同一组数据读取到的结果不一致。
脏读:------修改时加排他锁 读取时加共享锁
不可重复度:------读取时加共享锁 写数据时加排他锁
幻读:------范围锁------锁定检索范围为只读 间隙锁。
01、用户发送出请求到DispatcherServlet(前端控制器)。
02、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
03、HandlerMapping找到具体的控制器(可查找xml配置或注解配置),生成处理器对象的执行链(如果有),再一起返回给DispatcherServlet。
04、DispatcherServlet调用HandlerAdapter(处理器适配器)。
05、HandlerAdapter经过适配调用具体的处理器(controller)。
06、Controller执行完成返回ModelAndView对象。
07、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
08、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
09、ViewReslover解析后返回具体View(视图)。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
内存优化
linux修改TOMCAT_HOME/bin/catalina.sh
windows修改TOMCAT_HOME/bin/catalina.bat
线程优化
参数 | 解释 |
---|---|
maxConnections | 服务器所能接受最大的请求和处理的连接数,NIO和NIO2默认为10000,APR默认是8192. |
maxThreads | 同一时间点上处理线程的最大数量。 |
acceptCount | 当所有可能的请求处理线程都在使用时,传入连接请求的最大队列长度。 队列已满时收到的任何请求都将被拒绝。 默认值为100 |
minSpareThreads | 最小空闲线程数,默认为10,不易过小。 |
配置优化
\conf\server.xml
autoDeploy默认为true。因此我们需要将这个参数设置为false。
禁用DNS查询
APR插件提高Tomcat性能
① SQL语句及索引的优化
SQL语句的优化:
1、尽量避免使用子查询
2、避免函数索引
3、用IN来替换OR
4、LIKE前缀%号、双百分号、_下划线查询非索引列或*无法使用到索引,如果查询的是索引列则可以
5、读取适当的记录LIMIT M,N,而不要读多余的记录
6、避免数据类型不一致
7、分组统计可以禁止排序sort,总和查询可以禁止排重用union all
8、避免随机取记录
9、禁止不必要的ORDER BY排序
10、批量INSERT插入
11、不要使用NOT等负向查询条件
12、区分in和exists
索引的优化:
搜索的索引列,不一定是所要选择的列。换句话说,最适合索引的列是出现在 WHERE 子
句中的列,或连接子句中指定的列,而不是出现在 SELECT 关键字后的选择列表中的 列 。
使用惟一索引。考虑某列中值的分布。对于惟一值的列,索引的效果最好,而具有多个
重复值的列,其索引效果最差。
使用短索引。如果对串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做 。
利 用最左前缀。在创建 一个 n 列的索引时,实际是创建了 MySQL 可利用的 n 个索引。多列索引可起几个索引的作用,因为可利用索引中最左边的列集来匹配行。这样的列 集
称为最左前缀。
不要过度索引。不要以为 索引 “ 越多越好 ” ,什么东西都用索引是错的。每个额外的 索引都要占用额外的磁盘空间,并降低写操作的性能,这一点我们前面已经介绍 过。
考虑在列上进行 的比较类型。索引可用于 “ < ” 、 “ < = ” 、 “ = ” 、 “ > = ” 、 “ >” 和 BETWEEN 运算
7.如果对字符串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做。
8.对于 InnoDB 存储引擎的表,记录默认会按照一定的顺序保存,
(1)对于经常查询的字段,建议创建索引。
(2)索引不是越多越好,一个表如果有大量索引,不仅占用磁盘空间,而且会影响INSERT,DELETE,UPDATE等语句的性能。
(3)避免对经常更新的表进行过多的索引,因为当表中数据更改的同时,索引也会进行调整和更新,十分消耗系统资源。
(4)数据量小的表建议不要创建索引,数据量小时索引不仅起不到明显的优化效果,对于索引结构的维护反而消耗系统资源。
(5)不要在区分度低的字段建立索引。比如性别字段,只有 “男” 和 “女” ,建索引完全起不到优化效果。
(6)当唯一性是某字段本身的特征时,指定唯一索引能提高查询速度。
(7)在频繁进行跑排列分组(即进行 group by 或 order by操作)的列上建立索引,如果待排序有多个,可以在这些列上建立组合索引。
1、Join语句的优化:
2、避免索引失效
② 数据库表结构的优化:使得数据库结构符合三大范式与BCNF
③ 系统配置的优化
④ 硬件的优化
JMM:Java Memory Model(Java内存模型),围绕着在并发过程中如何处理可见性、原子性、有序性这三个特性而建立的模型。
描述了程序中各个变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节
作用
JMM 规定所有变量都存储在主内存,每条线程有自己的工作内存,工作内存中保存被该线程使用的变量的主内存副本,线程对变量的所有操作都必须在工作空间进行,不能直接读写主内存数据。不同线程间无法直接访问对方工作内存中的变量,线程通信必须经过主内存。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VgtAdAWA-1621395013244)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210511082342917.png)]
jvm结构分三部分:类装载器子系统,运行时数据区,执行引擎
然后运行时数据区下有分为5个模块:方法区、堆、Java栈、PC寄存器、本地方法栈
后先介绍下JVM垃圾回收结构,因为它与上一步有关联,这里分成三个区域:年青代、年老代、持久代,
持久代则是之前说到的运行时数据区下的方法区
而年青代、年老代则是属于运行时数据区下的堆,
然后年轻代下还分三个区分别是一个Eden区,两个Survivor区,
堆是Java虚拟机所管理的内存中最大的一块存储区域。堆内存被所有线程共享。主要存放使用new关键字创建的对象。所有对象实例以及数组都要在堆上分配。垃圾收集器就是根据GC算法,收集堆上对象所占用的内存空间(收集的是对象占用的空间而不是对象本身)。
Java堆分为年轻代(Young Generation)和老年代(Old Generation);年轻代又分为伊甸园(Eden)和幸存区(Survivor区);幸存区又分为From Survivor空间和 To Survivor空间。
年轻代存储“新生对象”,我们新创建的对象存储在年轻代中。当年轻内存占满后,会触发Minor GC,清理年轻代内存空间。
老年代存储长期存活的对象和大对象。年轻代中存储的对象,经过多次GC后仍然存活的对象会移动到老年代中进行存储。老年代空间占满后,会触发Full GC。
注:Full GC是清理整个堆空间,包括年轻代和老年代。如果Full GC之后,堆中仍然无法存储对象,就会抛出OutOfMemoryError异常。
常见的三种Garbage Collection
1,标记-清除法
将不用的对象实例标记,然后清除 。 缺点 会产生大量内存碎片。
2 ,复制 算法
把内存分成AB 2块,每次只是用其中的一块。当A块用完后,把A中还存活的对象复制到B中,然后将A块内存清空。不会产生内存碎片。缺点 内存使用率不高。
3,标记-整理法
当存活的实例过多时,如果复制的话,效率不高,不合适老生代。 这时,把存活的对象标记出来,全部移动到一端,然后对另外一部分进行清除。
1.1 Minor GC
从年轻代空间(包括Eden和Survivor区域)回收内存被称为Minor GC :
当Eden区域满了,jvm无法为新对象分配内存,会触发Minor GC;
新生代好进行标记和复制操作,就不会存在内存碎片。
年轻代中指向永久代中的引用,在标记阶段就会忽略。
stop-the-world。原因是Eden区中对象认为是垃圾,不会复制到Survivor区或者老年代。如果相反,Eden区
大部分对象不符合GC 条件,那么 Minor GC指定的时间就比较长。每次Minor GC会清理年轻代的内存。
1.2 Major GC 和Full GC
Major GC: 清理老年代
Full GC: 清理整个堆内存,包括年轻代和老年代
但是更多情况下,许多Minor GC 会 触发Major GC ,所以实际情况两者分离是不可能的。这就使得我们关注重点变成,GC是否能并发处理这些GC.
可以减轻数据库压力,查询内存比查询数据库效率高。
缓存 消息队列 时间轴 循环链表 排行榜 计数器 好友关系 分布式锁 倒排索引
会话缓存 全页缓存 队列 排行榜/计数器 发布/订阅
1.String(字符串)类型
字符串类型是 Redis 中最为基础的数据存储类型,它在 Redis 中以二进制保存,没有编码和解码的过程。无论存入的是字符串、整数、浮点类型都会以字符串写入redis中所有的key都是字符串类型,其它几种数据类型构成的元素也是字符串。注意字符串的长度不能超过512M。
2.Hash (表类型)
Hash对象的键是一个字符串类型,值是一个键值对集合,每一个 Hash 可以存储 40 亿个键值对。
常用命令: hget,hset,hgetall 等。
3.List (列表类型)
Redis列表只是字符串列表,按插入顺序排序。您可以向Redis列表的头部或尾部添加元素。和数据结构中的普通链表一样,我们可以在其左 部(left)和右部(right)添加新的元素。在插入时,如果该键并不存在,Redis 将为该键创建一个新的链表,如果这个键已经存在,则是向 list 添加元素。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List 中可以包含的最大元素数量是 40 亿个。
常用命令:lpush,rpush,lpop,rpop,lrange,BLPOP(阻塞版)等。
4.set(集合类型)
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
常用操作:sadd,spop,smembers,sunion 等。
5.zset (有序集合类型)
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
常用命令:zadd,zrange,zrem,zcard等
rdb:快照形式是直接把内存中的数据保存到一个dump文件中,定时保存,保存策略
优点
存储的文件是紧凑的
适合用于备份,方便恢复不同版本的数据
适合于容灾恢复,备份文件可以在其他服务器恢复
最大化了Redis的性能,备份的时候启动的是子线程,父进程不需要执行IO操作
数据保存比AOF要快
缺点
如果Redis因为没有正确关闭而停止工作是,到上个保存点之间的数据将会丢失
由于需要经常fork子线程来进行备份操作,如果数据量很大的话,fork比较耗时,如果cpu性能不够,服务器可能是卡顿。属于数据量大的时候,一个服务器不要部署多个Redis服务。
aof:把所有的对redis的服务器进行修改的命令都存到一个文件里,命令的集合
优点
缺点
对于同样的数据集,AOF文件通常要大于RDB文件
AOF可能比RDB要慢,这取决于fsync策略。通常fsync设置为每秒一次的话性能仍然很高,如果关闭sfync,即使在很高的负载下也和RDB一样快。不过,即使在很大的写负载情况下,RDB还是能提供很好的最大延迟保证
AOF1通过递增的方式更新数据,而RDB快照是从头开始创建,RDB会更健壮和稳定(所以适用于备份)
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
1.不管数据实际上存不存在,我们都把这个键存到缓存中,然后值设置为一个特定值,业务中如果获取到的结果是这个特定值,则报错返回。
2.使用 redis 的布隆过滤器(Bloom Filter),将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
解决方案:
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
LRU是redis唯一支持的回收算法
当数据到达最大内存限制时(maxmemory),redis根据maxmemory-policy配置策略,来决定具体行为
noeviction:不删除策略,达到最大内存限制时刻,如果需要更多内存,直接返回错误信息
allkey-lru:所有key通用,优先删除最近最少使用的key(LRU)
volatile-lru:只限于设置了expire的部分,优先删除最近最少使用的key
allkey-random:所有key通用,随机删除一部分key
volatile-random:只限于设置了expire部分,随即删除一部分key
volatile-ttl:只设置了expire的部分;优先删除剩余时间短的key
要想并发程序正确地执行,必须要保证原子性、可见性以及有序性。只要有一个没有被保证,就有可能会导致程序运行不正确。
原子性
定义:即一个或者多个操作作为一个整体,要么全部执行,要么都不执行,并且操作在执行过程中不会被线程调度机制打断;而且这种操作一旦开始,就一直运行到结束,中间不会有任何上下文切换。要想在多线程环境下保证原子性,则可以通过锁、synchronized来确保。volatile是无法保证复合操作的原子性。
可见性
定义:可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
有序性
定义:即程序执行的顺序按照代码的先后顺序执行。
构造子的作用就是初始化一个对象时 初始化状态的 每次new一个对象就必须把对象确定一个标准的状态 1、如果这个类只是一个简单的类(只身一个人,没有什么家庭背景,一人吃饱一家不饿的那种) new 一个对象就调用自己就搞定了(娶媳妇,生儿子就自己搞定了) 2、如果这个类(小刘)是一个大家族,他爹(老刘就在身边),他爷爷(老老刘也在了),小刘如果想搞个媳妇 生个儿子 不给老刘说一声怎么行
CMU-15213(计算机操作系统总结) - 数据类型杂谈 in Cint类型和unsigned int(也可以简写为unsigned)(int) -2147483647> (int) -2147483648会返回什么?#include <stdio.h>int main(){ int x = 2147483647; int y = -2147483648; printf("x > y -> %u\n", x > y);.
Unity 打开CS文件显示杂项文件前提在Editor-Preferences-Externaltools已经添加VS,但是依然是杂项文件,MonoBehaviour不变色,一些提示也不显示,我搜了很多博客都不行,里边也有一个写的很全,网址是https://www.codenong.com/42597501/我按照上述方式一一执行,但是依然不行我的问题我在打开Unity的时候报了一个警告,我才知道是我的Unity项目下的Packages里边的内容出问题了,这个文件下只有两个文件:manif
test_boost.cpp//// Created by tqc on 2020/1/9.//#include <boost/python.hpp>char const* greet(){ return "hello, world";}BOOST_PYTHON_MODULE(test_boost){ using namespace boos...
1.没有对应环境变量vim /etc/profile增加所需环境变量source /etc/profile(这个可以加到脚本里)2。脚本可以运行,cront不能运行大多数是因为路径找不到,crontab和脚本里无论是命令还是文件路径都用绝对路径3.按日期输出日志10 10 * * * /usr/bin/python /opt/cronfile/
MySQL:MySQL日期数据类型、MySQL时间类型使用总结 MySQL 日期类型:日期格式、所占存储空间、日期范围 比较。日期类型 存储空间 日期格式 日期范围------------ --------- --------------------- -----------------------------------------dat...
#include #include #include using namespace std;int is_prefix(char *a,char *b){ int m,n,i; m=strlen(a),n=strlen(b); char *longer=m>=n?a:b; char *shorter=m<n?a:b; m=strlen(longe
在扩增序列X的过程中,在序列延伸阶段,只产生了部分X序列延伸阶段就结束了,在下一轮的PCR反应中,这部分序列作为序列Y的引物接着延伸,扩增就会形成X和Y的嵌合体序列。### 参考数据库RDPwget http://drive5.com/uchime/gold.fausearch10 -uchime2_ref (除嵌合体)## 基于RDP数据库 去嵌合usearch10 -uch...
Charels: 抓包工具一:点击里面的 SSL Proxying Settings二: 三:安装后的样式:四:在浏览器的证书选项中, 导入该证书注: 不同浏览器的证书导入位置不一样例如: 火狐五:安装流程结束后可以看到:能对https抓包了....
为什么80%的码农都做不了架构师?>>> ...
二叉树的链式存储结构就是用链表来表示一棵二叉树,即用链表来指示元素之间的逻辑关系。通常有两种存储形式:链表中每个结点由三个域组成,除了数据域之外,还有两个指针域,分别用来给出该结点的左孩子和右孩子所在的存储地址。链表中每个结点由四个域组成,除了数据域之外,还有三个指针域,分别用来给出该结点的左孩子、右孩子和双亲结点所在的存储地址。class NodeL{Node root;public...
jQuery基本使用