https://www.yuque.com/qianmys/tbcnb5/sy2mwz7om0z8g9gd
频繁随机访问——ArrayList
频繁插入删除——LinkedList
ACID:原子性、一致性、隔离性、持久性
要么全部执行成功,要么全部执行失败
四大特性ACID:原子性、一致性、隔离性、持久性
事务并发问题:脏读、幻读、不可重复读
事务隔离级别:读未提交、读已提交、可重复读、串行序列化
(需要分别解释上述特点)
Redis事务:一个步骤中,执行一组命令
1、Redis事务不具有原子性:Redis 不能保证所有指令同时成功和失败,只能保证事务的指令一同执行,因为对Redis来说,事务回滚带来的代价太大,影响性能
2、Redis事务不具有隔离性:Redis 事务在提交之前任何指令都不会实际的被执行,所以不存在MySQL中脏写,脏读,不可重复读,幻读等问题
Redis事务常用命令:
1、MULTI:标记一个事务块的开始;
2、EXEC:执行事务块中的所有命令;
3、DISCARD:取消事务,放弃执行事务块中的所有命令;
4、UNWATCH:取消 WATCH 命令对所有 key 的监控;
5、WATCH key [key…]:监控一个或多个key,如果事务执行之前这些key被其他事务改动,事务就会被打断;
WATCH 底层采用的是CAS乐观锁,如果我们使用WATCH监控了一些 key,那么在事务中在执行修改这些被监控的 key 数据的时候,会判断当前 key 的值是否与期望值一样,如果一样就会做修改,如果不一样就会放弃修改,当前整个事务的操作都会放弃执行
分类:
1、编程式事务:TransactionTemplate/TransactionManager(×)
2、声明式事务:@Transactional(√)
事务传播行为:
1、TransactionDefinition.PROPAGATION_REQUIRED(propagation_required)
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
2、TransactionDefinition.PROPAGATION_REQUIRES_NEW(requires_new)
创建一个新的事务,如果当前存在事务,则把当前事务挂起
3、TransactionDefinition.PROPAGATION_NESTED(nested)
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行
如果当前没有事务,则该取值等价于1
4、TransactionDefinition.PROPAGATION_MANDATORY(mandatory)(×)
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
事务将不会发生回滚:
1、TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
2、TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起
3、TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常
注解:
@Transactional(rollbackFor = Exception.class)注解:事务在遇到非运行时异常时也回滚
如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚
事务管理相关三个接口:
1、PlatformTransactionManager:(平台)事务管理器,Spring 事务策略的核心
2、TransactionDefinition:事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)
3、TransactionStatus:事务运行状态
Spring 并不直接管理事务,而是提供了多种事务管理器 。Spring 事务管理器的接口是:PlatformTransactionManager
@Transactional
可用在方法(public)、类、接口(×)上
@Transactional 的工作机制是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用 JDK 的动态代理,如果目标对象没有实现了接口,会使用 CGLIB 动态代理
public类或方法上使用@Transactional注解:Spring容器在启动时为其创建一个代理对类,方法实际调用的是TransactionInterceptor 类中的 invoke()方法
事务失效:
1、@Transactional 注解只有作用到 public 方法上事务才生效,不推荐在接口上使用;
2、避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效;
3、被 @Transactional 注解的方法所在的类必须被 Spring 管理,否则不生效;
4、底层使用的数据库必须支持事务机制,否则不生效;
1、数据库不支持事务
2、事务方法未被spring管理
3、方法没有被public修饰
4、同一类中方法调用
5、未配置事务管理器
6、方法的事务传播类型不支持事务
7、不正确的捕获异常
8、错误的标注异常类型
// 同一类中方法调用
@Service
public class MyService {
private void method1() {
// 先获取该类的代理对象,然后通过代理对象调用method2
((MyService)AopContext.currentProxy()).method2();
}
@Transactional
public void method2() {
}
}
1、继承Thread类
2、实现Runnable方法
3、实现Callable方法
4、创建线程池
在锁对象的对象头里面有一个 threadid 字段
第一次访问的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id
再次进入的时候会先判断 threadid 是否与其线程 id 一致
通过自旋循环一定次数来获取锁,执行一定次数之后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁
1、同步锁只有一个线程访问——偏向锁(减少加锁解锁的CAS操作)
2、有其他线程抢占锁——轻量级锁
3、第二个线程加入锁争用——重量级锁
简化配置,方便集成其他主流框架,使开发更简单
自动去把第三方组件的Bean装载到IOC容器中,不需要开发人员再去写Bean相关的配置
在springboot应用里面只需要在启动类上去加上@SpringBootApplication注解,就可以去实现自动装配,它是一个复合注解,真正去实现自动装配的注解是 @EnableAutoConfiguration这样一个注解,自动装配的实现主要依靠三个核心的关键技术:
1、引入starter启动依赖组件的时候,这个组件里面必须包含有一个 @Configuration配置类,而在这个配置类里面,我们需要通过@Bean这个注解去声明需要装配到IOC容器里面的Bean对象。
2、第三方jar包里面的配置类全路径都将放在classpath:/META-INF/spring.factories文件里面,这样的话springboot就可以知道第三方jar包里面这个配置类的位置。这个步骤主要是用到了spring里面的SpringFactoriesLoader来完成的。
3、springboot拿到所有第三方jar包里面声明的配置类以后,再通过Spring提供的ImportSelector这样一个接口(@Import注解功能),来实现对这些配置类的动态加载,从而去完成自动装配的动作
1、Cookie 一般用来保存用户信息 ,登录一次网站后访问网站其他页面不需要重新登录
Session 主要作用就是通过服务端记录用户的状态。
典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的,服务端给特定的用户创建特定的 Session 后就可以标识这个用户并且跟踪这个用户
2、Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端
3、 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密
1、固定窗口计数器算法
使用一个counter计数,每处理一个请求counter+1,达到设定值之后,后续请求就会被拒绝
问题:无法保证突然激增的流量
2、滑动窗口计数器算法
可以把时间以一定比例分片
如接口限流每分钟处理 60 个请求,我们可以把 1 分钟分为 60 个窗口。每隔 1 秒移动一次,每个窗口一秒只能处理 不大于 60(请求数)/60(窗口数) 的请求。如果当前窗口的请求计数总和超过了限制的数量的话就不再处理其他请求
特点:当滑动窗口的格子划分的越多,滑动窗口的滚动就越平滑,限流的统计就会越精确
3、漏桶算法
把发请求的动作比作成注水到桶中,处理请求的过程可以比作漏桶漏水。我们往桶中以任意速率流入水,以一定速率流出水。当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率
实现:队列
与消息队列削峰/限流的思想是一样
4、令牌桶算法
现在桶里装的是令牌,请求在被处理之前需要拿到一个令牌,请求处理完毕之后将这个令牌丢弃(删除)。我们根据限流大小,按照一定的速率往桶里添加令牌。如果桶装满了,就不能继续往里面继续添加令牌了
1、RateLimiter
2、Bucket4j
1、借助中间件架限流:可以借助 Sentinel 或者使用 Redis 来自己实现对应的限流逻辑
2、网关层限流:比较常用的一种方案,直接在网关层把限流给安排上了。不过,通常网关层限流通常也需要借助到中间件/框架。就比如 Spring Cloud Gateway 的分布式限流实现RedisRateLimiter就是基于 Redis+Lua 来实现的,再比如 Spring Cloud Gateway 还可以整合 Sentinel 来做限流
为什么建议 Redis+Lua 的方式?
1、减少了网络开销:我们可以利用 Lua 脚本来批量执行多条 Redis 命令,这些 Redis 命令会被提交到 Redis 服务器一次性执行完成,大幅减小了网络开销。
2、原子性:一段 Lua 脚本可以视作一条命令执行,一段 Lua 脚本执行过程中不会有其他脚本或 Redis 命令同时执行,保证了操作不会被其他指令插入或打扰
1、${}
是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc. Driver。
2、#{}
是 sql 的参数占位符,MyBatis 会将 sql 中的#{}替换为? 号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的? 号占位符设置参数值,比如 ps.setInt(0, parameterValue),#{item.name} 的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 param.getItem().getName()
1、一级缓存是mybatis中默认开启的缓存机制,它是基于线程的本地缓存,适用于单线程、读多写少的场景
2、二级缓存是基于namespace级别的缓存,可以被多个SqlSession对象共享,被多个SqlSession对象共享,适用于多线程、读写频繁的场景
RDB、AOF:
适合
不适合
主管面听说会看项目源码进行解释
@SpringBootConfiguration 创建 SpringBoot 项目之后会默认在主类加上
1、使用构造函数 new ThreadPoolExecutor
2、使用工具类Executors
1、缓存模式
常用:使用过期时间兜底,先更新DB,后删除缓存,提升数据一致性——适合读多写少
2、缓存异常
双写?
3、缓存一致性
1、更新MySQL即可,不管Redis,以过期时间兜底
2、更新MySQL之后,操作Redis
更新MySQL,删除Redis
3、异步将MySQL同步更新到Redis
4、为什么需要缓存?
根据局部性原理,80%的请求会落在20%的热点数据上,对于读多写少的场景,增加缓存有利于提高吞吐量和健壮性
特性:对称性、安全性、互斥性
set key value nx ex secondsnx
setnx命令,key是锁名字,value是持有者id,在设置一个过期时间兜底
value必须是谁申请、谁释放,在解锁时需要先进行检查
1、加上owner——谁申请、谁释放
2、lua脚本——保证原子操作
Redission:
1、如果该客户端面对的是一个redis cluster集群,首先会根据hash节点选择一台机器
发送一段lua脚本到redis上(lua脚本里面是要执行的业务逻辑)
2、第二个客户端加锁 https://www.cnblogs.com/AnXinliang/p/10019389.html
3、watch dog自动延期机制:只要客户端1一旦加锁成功,就会启动一个watch dog看门狗,是一个后台线程,会每隔10秒检查一下,如果客户端1还持有锁key,那么就会不断的延长锁key的生存时间
4、可重入加锁机制:incrby myLock 对客户端1的加锁次数,累加1
5、释放锁机制:发现加锁次数是0了,说明这个客户端已经不再持有锁了,此时就会用del myLock命令删除
1、容易与 Spring 生态系统集成,如 Spring JDBC、Spring ORM、Spring Data、Spring Security
2、提供嵌入式 HTTP 服务器,如 Tomcat 和 Jetty,可以轻松地开发和测试 web 应用程序
3、提供了多种插件 Maven方便开发
四种Web容器,分别为Tomcat,Jetty,Undertow,Netty
容器负责管理应用程序的生命周期、处理请求和响应、管理对象的生命周期
容器的主要组件:
1、SpringApplication
SpringBoot 应用程序的核心类,负责启动 SpringBoot 应用程序,并负责初始化和配置ApplicationContext 容器
步骤:
2、ApplicationContext
Spring Framework 的核心容器,负责管理和组织应用程序中的各个 Bean 对象,提供了依赖注入、AOP、事件机制等功能
3、DispatcherServlet
Web MVC 框架的核心组件,负责处理 HTTP 请求和响应,将请求分发给对应的 Controller,并将 Controller 的响应返回给客户端
4、WebMvcConfigurer
Spring MVC 的配置接口,提供了多个方法,可以用于配置 Spring MVC 框架的各种选项
由Spring MVC自动配置创建和初始化,可以通过实现该接口来扩展和定制Spring MVC框架的功能,如配置跨域资源共享 (CORS)
5、Filter
Java Servlet API 的核心组件之一,负责处理 HTTP 请求和响应,并可以在请求和响应之间添加各种逻辑处理
可以通过实现 Filter 接口或继承 OncePerRequestFilter 类来实现
6、Servlet
Java Servlet API 的核心组件之一,负责处理 HTTP 请求和响应
可以通过实现 Servlet 接口或继承 HttpServlet 类来实现
7、EmbeddedServletContainer
SpringBoot 内嵌的 Web 容器,负责处理 HTTP 请求和响应,并管理应用程序的生命周期
SpringBoot 支持多种内嵌的 Web 容器,例如 Tomcat、Jetty、Undertow
https://javaguide.cn/system-design/framework/spring/spring-common-annotations.html
内连接
外连接(左外、右外)
执行流程:
1、@EnableWebMvc:在配置类中开启Web MVC的配置支持
2、@Controller:@Component注解的一种具体形式,还有@Service、@Repository
3、@RequestMapping:处理请求地址映射,映射web请求到某一个handler
@GetMapping、@PostMapping、@PutMapping、@PatchMapping、@DeleteMapping
4、@ResponseBody:响应请求的返回Body
5、@RequestBody:绑定HTTP请求的Body
6、@PathVariable:使用在请求handler方法的参数
7、@RestController:同时引入了@Controller和@ResponseBody两个注解
8、@ControllerAdvice:与@ExceptionHandler一起使用,可以统一处理业务异常
9、@ExceptionHandler
10、@InitBinder:日期格式的统一处理
11、@ModelAttribute:提前绑定全局user对象
12、@Transactional:使用事务
13、@CrossOrigin:支持跨域注解
14、@ExceptionHandler:异常处理
15、@Required:用于bean的setter方法上,必须在配置阶段注入
16、@Autowired:用于bean的field、setter方法以及构造方法上,显式地声明依赖,根据type来注入
17、@Qualifier:和@Autowired一起使用,指定要绑定的bean名称
18、@Configuration:Spring配置
19、@ComponentScan:指定Spring扫描注解的package
20、@Value:指定属性取值的表达式