银行国企补充
mybatis plus相对于直接使用mybatis有哪些优势
————————————————
版权声明:本文为CSDN博主「兮川」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zc_ad/article/details/83301911
1、SQL语句可以自由控制,更灵活、性能较高。
2、SQL与代码分离,易于阅读和维护。
3、提供XML标签,支持编写动态SQL语句。
JPA优势:
JPA移植性比较好(Hibernate方言)
提供了很多CRUD方法、开发效率高(不用编写sql语句)
对象化程度更高(面向对象开发思想)
Mybatis劣势:
简单CRUD操作需要编写SQL语句(单表仍需要编写Mapper接口方法和xml的sql)
XML中有大量sql需维护
mybatis自身功能有限
————————————————
版权声明:本文为CSDN博主「一个爱运动的程序员」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
2、依赖少:仅仅依赖 Mybatis 以及 Mybatis-Spring
3、损耗小:启动即会自动注入基本CRUD,性能基本无损耗,直接面向对象操作
4、通用CRUD操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
5、多种主键策略:支持多达4种主键策略(内含分布式唯一ID生成器),可自由配置,完美解决主键问题
6、支持ActiveRecord:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作
7、支持代码生成:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(P.S. 比 Mybatis 官方的 Generator 更加强大!)
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
8、内置分页插件:基于Mybatis物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于写基本List查询
9、内置性能分析插件:可输出Sql语句以及其执行时间,建议开发测试时启用该功能,能有效解决慢查询
10、内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,预防误操作
lombok作用:提高开发效率,通过注解形式使javabean生成get、set、有参数、无参数、toString等方法,无需手动实现。
UserMapper.java:
}
mybatis-plus:
主键采用雪花算法生成值的前提是实体类的主键属性名称必须为id。
mybatis-plus:
数据表字段带有_的可以自动映射到驼峰式命名的属性上(t_user——》tUser)。
注解:
1.数据库名不同,在类上增加@TableName(“mp_user”)
2.主键ID的驼峰一般无法识别,在主键属性上增加@TableId
3.属性与字段名不相同,在属性上增加@TableField(“name”)
@TableName(“数据库表名”):
使用场景实体类名称和数据表名不一致时,通过它指定表名,此时就可以使用mp的单表操作。
@TableId(“主键名”):
使用场景实体类属性名称和数据表主键不是id时,通过它声明该属性为主键,就可以采用雪花算法生成主键值操作。
@TableField(“字段名”):
使用场景实体类属性名称和数据表字段名不一致时,通过它指定数据表字段名称,就可以和实体类属性对应。
3、排除非表字段的三种方式
使用场景: 实体类中的某个属性不对应表中的任何字段,只是用于保存临时数据,或者临时组装的数据。
使用方式
1、 transient修饰实体类属性(修饰的属性不会被序列化)。
缺陷:有些需求需要序列化该字段。
2、 static修饰属性(前提手动实现get、set方法,Lombok对静态属性不会提供get、set方法)。
缺陷:每个对象的属性值一致。
3、 @TableField(exist=false),这个注解用来表示数据表中不存在该字段,默认是true。
————————————————
版权声明:本文为CSDN博主「一个爱运动的程序员」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
网关之降级、熔断、限流、隔离、幂等性验证的相关知识简单整理
制作网关项目的好处:
(1)网关层对外部和内部进行了隔离,保障了后台服务的安全性。 (2)对外访问控制由网络层面转换成了运维层面,减少变更的流程和错误成本 (3)减少客户端与服务的耦合,服务可以独立发展。通过网关层来做映射。 (4)通过网关层聚合,减少外部访问的频次,提升访问效率。 (5)节约后端服务开发成本,减少上线风险。 (6)为服务熔断,灰度发布,线上测试提供简单方案。 (7)便于扩展。
从接口安全方面说,它时属于微服务架构的基本功能。微服务架构的特点就是:“一解释就懂,一问就不知,一讨论就吵架”,对于我这个学艺不精的人来说,估计问什么都会吵架。
1. 应用场景
假设服务A依赖服务B和服务C,而B服务和C服务有可能继续依赖其他的服务,继续下去会使得调用链路过长,技术上称1->N扇出。
如果在A的链路上某个或几个被调用的子服务不可用或延迟较高,则会导致调用A服务的请求被堵住,堵住的请求会消耗占用掉系统的线程、io等资源,
当该类请求越来越多,占用的计算机资源越来越多的时候,会导致系统瓶颈出现,造成其他的请求同样不可用,最终导致业务系统崩溃,又称:雪崩效应。
2.处理方式
降级:在服务器压力剧增的情况下,根据实际业务情况和流量,对一些服务和页面不处理或简单处理,从而释放服务器资源保证核心交易正常运作。 熔断:熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。 限流:限制服务/接口访问的流量。可以从总量+速率进行处理 隔离:保证其中某个服务坏掉,不会影响到其他服务。线程池/信号量隔离模式 幂等性验证: 可能因为网络抖动或其他位置原因,服务端在短时间内可能会受到多笔相同的交易 超时机制:一种是请求的等待超时,一种是请求运行超时。 其中,降级、熔断、隔离属于出现问题后的处理机制。限流属于预防。
其中,降级、熔断、隔离属于出现问题后的处理机制。限流属于预防。
spring boot
SpringBoot是Spring社区发布的一个开源项目,在帮助开发者快速并且更简单的构建项目。它使用习惯优于配置的理念让你的项目快速运行起来,使用Spring Boot很容易创建一个独立运行(运行jar,内置Servlet容器,Tomcat、jetty)、准生产级别的基于Spring框架的项目,使用SpringBoot框架,你可以不用或者只需要很少的配置文件。
SpringBoot核心功能
独立运行的Spring项目:可以以jar包形式独立运行,通过java -jar xx.jar即可运行。
内嵌Servlet容器:可以选择内嵌Tomcat、Jetty等。
提供starter简化maven配置:一个maven项目,使用了spring-boot-starter-web时,会自动加载Spring Boot的依赖包。
自动配置Spring:Spring Boot会根据在类路径中的jar包、类,为jar包中的类自动配置Bean。
准生产的应用监控:提供基于http、ssh、telnet对运行时的项目进行监控。
————————————————
版权声明:本文为CSDN博主「lzcWHUT」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
Spring Cloud 是基于 Spring Boot 开发的一套微服务架构下的服务治理方案。
Spring Cloud 是一系列框架的有序集合。它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。
Spring Cloud 是为了解决微服务架构中服务治理而提供的一系列功能的开发框架,并且 Spring Cloud 是完全基于 Spring Boot 而开发。Spring Cloud 利用 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案。
- 用户认证和用户授权
单点登录的过程,单点登录
使用JWT实现单点登录
Spring 如何解决循环依赖的问题
1. 什么是循环依赖? what?
(1)循环依赖-->循环引用。--->即2个或以上bean 互相持有对方,最终形成闭环。
①:构造器的循环依赖。【这个Spring解决不了】
StudentA有参构造是StudentB。StudentB的有参构造是StudentC,StudentC的有参构造是StudentA ,这样就产生了一个循环依赖的情况,
②【setter循环依赖】field属性的循环依赖【setter方式 单例,默认方式-->通过递归方法找出当前Bean所依赖的Bean,然后提前缓存【会放入Cach中】起来。通过提前暴露 -->暴露一个exposedObject用于返回提前暴露的Bean。】如何检测是否有循环依赖?how to find?
可以 Bean在创建的时候给其打个标记,如果递归调用回来发现正在创建中的话--->即可说明循环依赖。
②:populateBean:填充属性,这一步主要是多bean的依赖属性进行填充
③:initializeBean:调用spring xml中的init() 方法。
从上面讲述的单例bean初始化步骤我们可以知道,循环依赖主要发生在第一、第二步。也就是构造器循环依赖和field循环依赖。
那么我们要解决循环引用也应该从初始化过程着手,对于单例来说,在Spring容器整个生命周期内,有且只有一个对象,所以很容易想到这个对象应该存在Cache中,
调整配置文件,将构造函数注入方式改为 属性注入方式 即可
————————————————
版权声明:本文为CSDN博主「Zeus_龙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
earlySingletonObjects :提前暴光的单例对象的Cache 。【用于检测循环引用,与singletonFactories互斥】
singletonObjects:单例对象的cache
Spring首先从一级缓存singletonObjects中获取。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取这里就是解决循环依赖的关键,这段代码发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。
知道了这个原理时候,肯定就知道为啥Spring不能解决“A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象”这类问题了!因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决
Spring五个事务隔离级别和七个事务传播行为
单例模式下synchronize加锁后为什么要用volatile
解决并发共享变量问题需要解决三个问题:原子性、可见性、有序性synchronize:保证原子性、可见性、有序性(多线程顺序执行)
volatile:保证可见性、有序性(禁止指令重排序)
public class Singleton {
private static volatile Singleton s;//1,volatile修饰的必要性
private Singleton(){};//必须是private
public static Singleton getInstance() {
if(s == null) {//2
synchronized (Singleton.class) {//3
if(s == null) {//4
s = new Singleton();//问题关键:步骤5分为三步,存在指令重排可能性
}
}
}
return s;//6
}
}
位置5可分为三个步骤:
1、memory=allocate();// 分配内存 相当于c的malloc
2、ctorInstanc(memory) //初始化对象
3、s=memory //设置s指向刚分配的地址
由于synchronize不保证单个线程内部指令的顺序,比如线程A在位置5的执行顺序有可能是1-2-3,也有可能是1-3-2,如果是1-3-2的情况,线程A执行完步骤3给s对象分配了地址;此时来个线程B,那么在位置2判断s就不为null,但是此时线程A还没有初始化对象,就会导致线程B拿到的s出错,线程A不会出错。
所以位置3加锁后,只能保证多线程串行执行加锁部分的代码块,不能保证位置5里面的指令执行顺序,所以对象s用volatile修饰 ,禁止指令重排序,从而保证了代码执行的正确性。
总结:步骤1用volatile修饰对象,就是为了步骤5禁止指令重排
————————————————
版权声明:本文为CSDN博主「章绍龙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/shaolong1013/article/details/94824574
微服务
此时的服务调用将分为两个过程:
- Server A 去服务注册中心拿到 Server B 的地址,如果 Server B 是单机部署,这个地址就只有一个,如果 Server B 是集群化部署,这个地址就有多个;
- 拿到 Server B 的地址之后,Server A 再去调用 Server B。
三行配置含义分别如下:
- spring.application.name 表示当前服务的名字,这个名字将作为服务的标记存储在Eureka上,当其他服务需要调用这个服务的时候,都是通过这个名字来查找服务。
- server.port 当前服务的端口。
- 最后一个地址表示当前服务需要注册到的服务注册中心地址,这里需要注意,如果服务注册中心是一个集群,这里也可以只写集群中的一个节点,Eureka 集群会自动进行服务同步。
在微服务中,只要当前项目的 classpath 下存在 spring-cloud-starter-netflix-eureka-client 依赖,并且提供了 eureka 注册中心的地址,该服务就会自动注册到 Eureka Server 上。
主要调用逻辑
步骤如下:
- 服务提供者启动hsf容器,上报服务信息到服务注册中心.
- 服务提供方上报元数据信息。
- 服务消费方启动hsf容器,拉取提供者信息.
- 拉取配置服务信息进行调用。
HTTP1.0、HTTP1.1 和 HTTP2.0 的区别
udp如何实现可靠性传输
TCP(TransmissionControl Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
UDP是User Datagram Protocol,一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。可靠性由上层应用实现,所以要实现udp可靠性传输,必须通过应用层来实现和控制。
传输层无法保证数据的可靠传输,只能通过应用层来实现了。实现的方式可以参照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。
实现确认机制、重传机制、窗口确认机制。
如果你不利用Linux协议栈以及上层socket机制,自己通过抓包和发包的方式去实现可靠性传输,那么必须实现如下功能:
发送:包的分片、包确认、包的重发
接收:包的调序、包的序号确认
目前有如下开源程序利用udp实现了可靠的数据传输。分别为RUDP、RTP、UDT。
TCP协议—如何提高数据发送
1.滑动窗口发送前四个段,不需要等待任何ACK,直接发送
收到第一个ACK,滑动窗口向后移动,继续发送第五个段的数据,依次类推
操作系统为了维护这个滑动窗口,需要开辟一个发送缓冲区来记录当前没有应答的数据,而确认应答过的数据,会从缓冲区删除
窗口越大,则网络的吞吐率越高
此时接收端收到了1001之后。再次返回的ACK就是7001了(因为2001——7000)接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中,这种机制被称为”高速重发机制“(快重传)。
————————————————
版权声明:本文为CSDN博主「浩然849」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_56763572/article/details/119659186
接收端将自己可以接受的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK段通知发送端窗口的字段越大,网络吞吐量越高。
接收端一旦发现自己快满了,就会将窗口大小设置成一个更小的值传给发送端,发送端接收到这个数据后就会减缓发送速度。
如果接收端缓冲区满了,此时窗口大小设置为0,发送端将不会在发送数据,而是定期发送一个窗口探测数据段,使接收端将窗口大小告诉发送端。
核心就是防止开始传输时由于传输数据过大,网络不好而引起的大量丢包问题,引入慢启动机制,开始先发送少量数据看网络是否堵塞,然后在决定以多大的速度传输数据。
引入一个概念称为拥塞窗口,发送开始的时候, 定义拥塞窗口大小为1,每次收到一个ACK应答, 拥塞窗口加1。
每次发送数据包的时候, 将拥塞窗口和流量控制的窗口大小做比较, 取较小的值作为实际发送的窗口。
拥塞窗口是按指数增加的,为了避免拥塞窗口增长的太快,引入一个慢启动阈值,当拥塞窗口超过这个阈值的时候,变为线性增长。
慢启动开始的时候,阈值等于窗口的最大值,每次超时重传时阈值变为原来的一半,拥塞窗口置回1。
当TCP开始通信的时候,网络吞吐量开始上升,随着网络拥堵,吞吐量立刻下降。
拥塞控制归根结底就是 TCP协议尽可能的将数据传输给对方,但又要避免给网络造成太大的压力的折中方案。
4.延迟应答
如果接收端接收到数据就返回一个ACK的话,此时返回的ACK就会很小,比如说:如果接收端缓冲区为800KB的话,发送一个400KB的数据,立即返回的话窗口大小只有400KB,但是延迟一会再发的话,缓冲区可能就会把这400KB的数据处理掉了,这时返回的窗口大小就为800KB,极大的提高传输效率。
但并不是所有的包都可以延迟应答,他会收到数量限制和时间限制,每隔一定数量的包就应答一次,超过最大延迟时间就应答一次。
5.捎带应答
在延迟应答基础上,客户端服务器在应用层上也是“一发一收的”,那么此时ACK就可以搭顺风车和服务器回应的数据一起回给客户端。
Linux删除指令
使用rm -rf 目录名字 命令即可
-r 就是向下递归,不管有多少级目录,一并删除
-f 就是直接强行删除,不作任何提示的意思
eg
删除文件夹实例:rm -rf /var/log/httpd/access
将会删除/var/log/httpd/access目录以及其下所有文件、文件夹
删除文件使用实例:rm -f /var/log/httpd/access.log
将会强制删除/var/log/httpd/access.log这个文件
深翻页
为了实现分页,每次收到分页请求时,数据库都需要进行低效的全表扫描。
“ 什么是全表扫描?全表扫描 (又称顺序扫描) 就是在数据库中进行逐行扫描,顺序读取表中的每一行记录,然后检查各个列是否符合查询条件。这种扫描是已知最慢的,因为需要进行大量的磁盘 I/O,而且从磁盘到内存的传输开销也很大。
你要在本地保存上一次接收到的主键 (通常是一个 ID) 和 LIMIT,而不是 OFFSET 和 LIMIT,那么每一次的查询可能都与此类似。
为什么?因为通过显式告知数据库最新行,数据库就确切地知道从哪里开始搜索(基于有效的索引),而不需要考虑目标范围之外的记录。
要使用这种基于游标的分页,需要有一个惟一的序列字段 (或多个),比如惟一的整数 ID 或时间戳,但在某些特定情况下可能无法满足这个条件。在查询页面每次记录下头尾的主键id,在查询条件中增加主键范围查找,避免深分页。
一般正常查看列表不会有去看最后一页的这种需求,像天猫,淘宝,京东,搜索商品也是只能点击下一页,也没有跨页去查找的这种功能。通常都会有指定的条件去筛选出需要的结果。如果LIMIT m,n不可避免的话,要优化效率,只有尽可能的让m小一下,我们扩展前面的clue做法,还是SELECT * FROM message ORDER BY id DESC,按id降序分页,每页20条,当前是第10页,记录当前页条目id最大的是2519,最小的是2500;【加粗字体是精髓!!!!】
原理还是一样,记录住当前页id的最大值和最小值,计算跳转页面和当前页相对偏移,由于页面相近,这个偏移量不会很大,这样的话m值相对较小,大大减少扫描的行数。
【其实传统的limit m,n,相对的偏移一直是第一页,这样的话越翻到后面,效率越差,而上面给出的方法就没有这样的问题。】
注意SQL语句里面的ASC和DESC,如果是ASC取出来的结果,显示的时候记得倒置一下。
Elasticsearch
1、Elasticsearch和MongoDB/Redis/Memcache一样,是非关系型数据库。
是一个接近实时的搜索平台,从索引这个文档到这个文档能够被搜索到只有一个轻微的延迟,企业应用定位:采用Restful API标准的可扩展和高可用的实时数据分析的全文搜索工具。
2、可拓展:支持一主多从且扩容简易,只要cluster.name一致且在同一个网络中就能自动加入当前集群;本身就是开源软件,也支持很多开源的第三方插件。
3、高可用:在一个集群的多个节点中进行分布式存储,索引支持shards和复制,即使部分节点down掉,也能自动进行数据恢复和主从切换。
4、采用RestfulAPI标准:通过http接口使用JSON格式进行操作数据。
5、数据存储的最小单位是文档,本质上是一个JSON 文本:实际项目开发中,几乎每个系统都会有一个搜索的功能,数据量少时可以直接从主数据库中比如Mysql搜索。
但当搜索做到一定程度时,比如系统数据量上了10亿、100亿条的时候,传统的关系型数据库的I/O性能和统计分析性能就难以满足用户需要了。
所以很多公司都会把搜索单独做成一个独立的模块,用ElasticSearch等来实现。
虽然内存缓存数据库的读写性能很高,但完全把数据放在内存中是不太现实的,比如到PB级别的数据,按照每个节点96G内存计算,
在内存完全装满的数据情况下,需要的机器是:1PB=1024T=1048576G ,节点数就是1048576/96=10922个 ,再考虑到数据备份,节点数还需要翻倍,成本巨大决定了其不现实!
mysql中怎么样可以实现:有一个数据存在的时候执行查找操作,该数据不存在的时候执行插入操作
-
MySQL插入一条数据,如果数据已存在就跳过,不存在就插入:使用insert ignore语句:(要求必须有唯一字段参与匹配,该唯一字段可以为主键)
insert ignore into dept(deptno) values(20); # 如果已存在deptno为20的行,则跳过不执行操作,否则执行插入(注意deptno必须唯一或为主键 -
插入一条数据,如果数据存在则更新,不存在则插入(必须要有唯一字段或主键),使用 insert...on duplicate key update语句,例如:
insert into dept(deptno,dname) values(30,'null') on duplicate key update dname='xiaoming';
该条语句,如果已经存在了对应的deptno(deptno为unique或者主键),那么就执行后面的update操作,即其就等价于:
update dept set dname='xiaoming' where deptno=30;
如果并不存在对应的deptno,则执行insert操作,即相当于只存在on 关键字前面半部分。
如果最终执行的是行插入操作,则该条语句执行结果中返回的受影响的行数为1;如果是原有的记录被更新,则返回的受影响的行的值为2; -
Replace关键字的使用:Replace关键字最主要的作用就是可以将delete和insert操作合二为一,实现一个原子操作。在使用Replace时,表中必须存在唯一索引,即存在unique字段,且该字段不允许为空值。
replace into dept(deptno,dname,loc) values(50,'xiaohong','BeiJing');
当deptno=50存在时,就会执行delete这条记录,并重新insert一个新的记录,新纪录dname和loc为当前设定的值;当deptno=50不存在时,则直接执行插入操作;
在执行REPLACE后,系统返回了所影响的行数,如果返回1,说明没有重复的记录,直接执行插入操作;如果返回2,说明有重复记录,系统先DELETE这条记录,然后再INSERT这条记录。
SET column1=value1,column2=value2,...
WHERE some_column=some_value;
WHERE some_column=some_value;
FROM table_name;
FROM table_name
ORDER BY column_name,column_name ASC|DESC;
CMS实现原理
该示例取自一篇牛逼的论文,解释我们的场景完全足够。整个堆内存有4页,包含了7个对象。在初始标记阶段,4页都标记为clean,对象a是从根直接可达的,所以将其标记为活对象。
1a处于并发标记的过程中,对象b,c,e都被标记为活对象。在这个时候,对象g应用d被删除了,对象b引用c修改为引用d.因为g和b发生了变更,所以第1页和第3页被标记为脏页。
1c表示在并发标记结束时的样子。很明显,标记还不完整,因为b的引用对象d还没有被标记。在重新标记阶段才会被标记:在这个阶段所有的脏页会重新扫描,d会被标记上。
1d表示就是重新标记后的状态,这时候标记就结束了。下一个阶段就是并发清除了,最终f会被回收。
在回收的时候,虽然c现在是不可达的对象,但它被标记了,所以不会被回收,它会在下一次垃圾回收的时候会被回收。
旧生代:Old Generation。用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象。旧生代占用大小为-Xmx值减去-Xmn对应的值。
————————————————
版权声明:本文为CSDN博主「Franco蜡笔小强」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/w372426096/article/details/81360083
Java基本类型+字节
粘包和拆包
假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况:
1.服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包
2.服务端一次接受到了两个数据包,D1和D2粘合在一起,称之为TCP粘包
3.服务端分两次读取到了数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这称之为TCP拆包
4.服务端分两次读取到了数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余部分内容D1_2和完整的D2包。
特别要注意的是,如果TCP的接受滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种情况,即服务端分多次才能将D1和D2包完全接受,期间发生多次拆包。
粘包、拆包问题的解决方案:定义通信协议
目前业界主流的协议(protocol)方案可以归纳如下:
1 定长协议:假设我们规定每3个字节,表示一个有效报文。
2.特殊字符分隔符协议:在包尾部增加回车或者空格符等特殊字符进行分割 。
3.长度编码:将消息分为消息头和消息体,消息头中用一个int型数据(4字节),表示消息体长度的字段。在解析时,先读取内容长度Length,其值为实际消息体内容(Content)占用的字节数,之后必须读取到这么多字节的内容,才认为是一个完整的数据报文。
CAS不断自旋
- 简单来说就是将一个值分散成多个值,在并发的时候就可以分散压力,性能有所提高。
-
作者:Java3y
链接:https://www.zhihu.com/question/39130725/answer/1006948362
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
MySQL 5.0 版本开始支持存储过程。
存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。
存储过程是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。
存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。
优点
- 存储过程可封装,并隐藏复杂的商业逻辑。
- 存储过程可以回传值,并可以接受参数。
- 存储过程无法使用 SELECT 指令来运行,因为它是子程序,与查看表,数据表或用户定义函数不同。
- 存储过程可以用在数据检验,强制实行商业逻辑等。
缺点
- 存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
- 存储过程的性能调校与撰写,受限于各种数据库系统。
数据库分区、分表、分库、分片
高并发编程-ExecutorCompletionService深入解析
假设现在有一大批需要进行计算的任务,为了提高整批任务的执行效率,你可能会使用线程池,向线程池中不断submit异步计算任务,同时你需要保留与每个任务关联的Future,最后遍历这些Future,通过调用Future接口实现类的get方法获取整批计算任务的各个结果。虽然使用了线程池提高了整体的执行效率,但遍历这些Future,调用Future接口实现类的get方法是阻塞的,也就是和当前这个Future关联的计算任务真正执行完成的时候,get方法才返回结果,如果当前计算任务没有执行完成,而有其它Future关联的计算任务已经执行完成了,就会白白浪费很多等待的时间,所以最好是遍历的时候谁先执行完成就先获取哪个结果,这样就节省了很多持续等待的时间。
而ExecutorCompletionService可以实现这样的效果,它的内部有一个先进先出的阻塞队列,用于保存已经执行完成的Future,通过调用它的take方法或poll方法可以获取到一个已经执行完成的Future,进而通过调用Future接口实现类的get方法获取最终的结果。
————————————————
版权声明:本文为CSDN博主「wind瑞」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/windrui/article/details/101366444
一些补充
1、RUNNABLE,线程处于执行中
2、BLOCKED,线程被阻塞
3、WAITING,线程正在等待
2、通过top -Hp 23344可以查看该进程下各个线程的cpu使用情况;
上图中可以看出pid为25077的线程占了较多的cpu资源,利用jstack命令可以继续查看该线程当前的堆栈状态。
jstack命令
通过top命令定位到cpu占用率较高的线程之后,继续使用jstack pid命令查看当前java进程的堆栈状态
jstack命令生成的thread dump信息包含了JVM中所有存活的线程,为了分析指定线程,必须找出对应线程的调用栈,应该如何找?
在top命令中,已经获取到了占用cpu资源较高的线程pid,将该pid转成16进制的值,在thread dump中每个线程都有一个nid,找到对应的nid即可;隔段时间再执行一次stack命令获取thread dump,区分两份dump是否有差别,在nid=0x246c的线程调用栈中,发现该线程一直在执行JstackCase类第33行的calculate方法,得到这个信息,就可以检查对应的代码是否有问题。
MySQL insert死锁
简单的insert会在insert的行对应的索引记录上加一个排它锁,这是一个record lock,并没有gap,所以并不会阻塞其他session在gap间隙里插入记录。
不过在insert操作之前,还会加一种锁,官方文档称它为insertion intention gap lock,也就是意向的gap锁。这个意向gap锁的作用就是预示着当多事务并发插入相同的gap空隙时,只要插入的记录不是gap间隙中的相同位置,则无需等待其他session就可完成,这样就使得insert操作无须加真正的gap lock。
假设有一个记录索引包含键值4和7,不同的事务分别插入5和6,每个事务都会产生一个加在4-7之间的插入意向锁,获取在插入行上的排它锁,但是不会被互相锁住,因为数据行并不冲突。
假设发生了一个唯一键冲突错误,那么将会在重复的索引记录上加读锁。当有多个session同时插入相同的行记录时,如果另外一个session已经获得该行的排它锁,那么将会导致死锁。
Java单元测试
JUnit是一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。
————————————————
版权声明:本文为CSDN博主「___cc木槿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36568192/article/details/79857185
②很多人对自己写的代码,测试时就简单写main,然后sysout输出控制台观察结果。这样非常枯燥繁琐,不规范。缺点:测试方法不能一起运行,测试结果要程序猿自己观察才可以判断程序逻辑是否正确。
③JUnit的断言机制,可以直接将我们的预期结果和程序运行的结果进行一个比对,确保对结果的可预知性。
assertSame()用来测试两个引用是否指向同一个对象
1、测试方法上面必须使用@Test注解进行修饰。
2、测试方法必须使用public void 进行修饰,不能带有任何参数。
3、新建一个源代码目录用来存放测试代码。
4、测试类的包应该与被测试类的包保持一致。
5、测试单元中的每一个方法必须独立测试,每个测试方法之间不能有依赖。
6、测试类使用Test做为类名的后缀(非必要)。
7、测试方法使用test作为方法名的前缀(非必要)。
1、@BeforeClass所修饰的方法在所有方法加载前执行,而且他是静态的在类加载后就会执行该方法,
在内存中只有一份实例,适合用来加载配置文件。
2、@AfterClass所修饰的方法在所有方法执行完毕之后执行,通常用来进行资源清理,例如关闭数据库连接。
3、@Before和@After在每个测试方法执行前都会执行一次。
4>常用注解
1、@Test(excepted=XX.class) 在运行时忽略某个异常。
2、@Test(timeout=毫秒) 允许程序运行的时间。
3、@Ignore 所修饰的方法被测试器忽略。
代码的覆盖程度:评测测试过程中已经执行的代码的多少。
代码的覆盖程度,一种度量方式。针对代码的测试覆盖率有许多种度量方式。
语句覆盖( StatementCoverage ):也称为行覆盖( lin EC overage ) , 段覆盖(segmentcoverage)和基本块覆盖(bASicblockcoverage)。它度量每一个可执行语句是否被执行到了。
判定覆盖(DecisionCoverage):也被称为分支覆盖(branchcoverage),所有边界覆盖(alledgescoverage), 基本路径覆盖( basispathcoverage ), 判定路径覆盖(decisiondecisionpath或DDPtesting)。它度量是否每个 BOOL 型的表达式取值true 和 false 在控制结构中都被测试到了。
条件覆盖(ConDItionCoverage): 它独立的度量每一个子表达式,报告每一个子表达式的结果的 true 或 false。这个度量和判定覆盖(decisioncoverage)相似,但是对控制流更敏感。不过,完全的条件覆盖并不能保证完全的判定覆盖。
路径覆盖(PathCoverage):也称为断言覆盖(prEDIcatecoverage),它度量了是否函数的每一个可能的分支都被执行了。路径覆盖的一个好处是:需要彻底的测试。但有两个缺点:一是,路径是以分支的指数级别增加的,例如:一个函数包含 10个 IF 语句,就有 1024 个路径要测试。如果加入一个 IF 语句,路径数就达到 2048;二是,许多路径不可能与执行的数据无关。
循环覆盖(LOOPCoverage):这个度量报告你是否执行了每个循环体零次、只有一次还是多余一次(连续地)。对于 dowhile循环,循环覆盖报告你是否执行了每个循环体只有一次还是多余一次(连续地)。这个度量的有价值的方面是确定是否对于 while 循环和 for 循环执行了多于一次,这个信息在其它的覆盖率报告中是没有的。
————————————————
版权声明:本文为CSDN博主「___cc木槿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36568192/article/details/79857185