Spring源码分析-1
Spring源码环境搭建下载gradleSpring版本用的Gradle(类似于maven但是比maven强大)进行执行和编译,所以需要下载gradle环境
https://gradle.org/releases/
本篇文章使用的6.82版本
https://downloads.gradle-dn.com/distributions/gradle-6.8.2-all.zip
配置环境变量下载完成后解压,就和配置java环境变量一样,配置系统环境变量
需要配置:GRADLE_HOME、PATH、GRADLE_USER_HOME
系统变量(s)中添加:
1GRADLE_HOME D:\Program Files (x86)\gradle-6.8.2
系统变量(s)中添加:
这里面的变量内容执行你想要存放gradle包的路径,我的是放到了d盘的一个文件夹下
1GRADLE_USER_HOME
系统变量(s)的path中添加:
1%GRADLE_HOME%/bin
配置下载加速
在gradle文件的init.d文件夹下添加init.gradle文件
内容为:
1234 ...
Spring源码分析-2
参考文章:https://blog.csdn.net/weixin_48033662/article/details/120000961
核心注解
注解
功能
@Bean
容器中注册组件
@Primary
同类组件如果有多个,标注主组件
@DependsOn
组件之间声明依赖关系
@Lazy
组件懒加载(最后使用的时候才创建)
@Scope
声明组件的作用范围(SCOPE_PROTOTYPE,SCOPE_SINGLETON)
@Configuration
声明这是一个配置类,替换以前配置文件
@Component
@Controller、@Service、@Repository
@Indexed
加速注解,所有标注了 @Indexed 的组件,直接会启动快速加载
@Order
数字越小优先级越高,越先工作
@ComponentScan
包扫描
@Conditional
条件注入
@Import
导入第三方jar包中的组件,或定制批量导入组件逻辑
@ImportResource
导入以前的xml配置文件,让其生效
@Profi ...
Spring源码分析-3
spring整体架构
基础接口Resource+ResourceLoader
Resource代表spring中的资源的高度抽象,spring中所有的加载最终都是由Resource来实现的,具体根据不同的需要实现不同的接口,可以来自于二进制文件,可以来自于网络、磁盘等等情况
通过Resource接口获取资源Resource接口的实现类有:
Resource接口继承了InputStreamSource 接口,InputStreamSource 接口中有一个方法:getInputStream(),所以汇总起来,Resource接口中共有以下方法:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475public class ResourceTest { /**使用ClassPathResource获取资源**/ @Test p ...
Spring注解驱动开发
Spring注解驱动开发转载博客:https://blog.csdn.net/weixin_48033662/article/details/120000961
分布式核心
微服务中核心问题解决方案分布式id,分布式锁,鉴权,事务等等
分布式id生成方案有哪些?UUID,数据库主键自增,Redis自增ID,雪花算法。
描述
优点
缺点
数据库主键自增
MySQL数据库设置主键且主键自动增长
1. INT和BIGINT类型占用空间较小;2. 主键自动增长,IO写入连续性好;3. 数字类型查询速度优于字符串
1. 并发性能不高,受限于数据库性能;2. 分库分表,需要改造,复杂;3. 自增:数据和数据量泄露
UUID
UUID是通用唯一标识码的缩写,其目的是让分布式系统中的所有元素都有唯一的辨识信息,而不需要通过中央控制器来指定唯一标识。
1. 降低全局节点的压力,使得主键生成速度更快;2. 生成的主键全局唯一;3. 跨服务器合并数据方便。
1. UUID占用16个字符,空间占用较多;2. 不是递增有序的数字,数据写入IO随机性很大,且索引效率下降(mysql的B+树索引机制)
号段模式
量获取多个ID并缓存在本地,集群中每个mysql使用不同的自增步长
1. 不依赖数据库,即使数据库挂了,还能坚持一段时间2.
1. 重启后,会 ...
分布式id的生成方案
分布式id的生成方案ID是数据的唯一标识,传统的做法是利用UUID和数据库的自增ID,在互联网企业中,大部分公司使用的都是Mysql,并且因为需要事务支持,所以通常会使用Innodb存储引擎,UUID太长以及无序,所以并不适合在Innodb中来作为主键,自增ID比较合适,但是随着公司的业务发展,数据量将越来越大,需要对数据进行分表,而分表后,每个表中的数据都会按自己的节奏进行自增,很有可能出现ID冲突。这时就需要一个单独的机制来负责生成唯一ID,生成出来的ID也可以叫做分布式ID,或全局ID。下面来分析各个生成分布式ID的机制。
这篇文章并不会分析的特别详细,主要是做一些总结,以后再出一些详细某个方案的文章。
数据库自增ID第一种方案仍然还是基于数据库的自增ID,需要单独使用一个数据库实例,在这个实例中新建一个单独的表:
表结构如下:
12345678CREATE DATABASE `SEQID`;CREATE TABLE SEQID.SEQUENCE_ID ( id bigint(20) unsigned NOT NULL auto_increment, stub char( ...
无题
两军问题拜占庭将军问题
深究Spring中Bean的生命周期
深究Spring中Bean的生命周期前言这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,直到看到了《Spring in action》这本书,书上有对Bean声明周期的大致解释,但是没有代码分析,所以就自己上网寻找资料,一定要把这个Bean生命周期弄明白!
网上大部分都是验证的Bean 在面试问的生命周期,其实查阅JDK还有一个完整的Bean生命周期,这同时也验证了书是具有片面性的,最fresh 的资料还是查阅原始JDK!!!
一、Bean 的完整生命周期在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。
相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程
Bean 的生命周期
如上图所示,Bean 的生命周期还是比较复杂的,下面来对上图每一个步骤做文 ...
zookeeper分布式锁
背景为了保证数据的一致性,在一些业务处理中都会选择加锁来保证数据的一致性。在单机模式下我们通常选择使用synchronized等这种JAVA提供好的jvm锁来实现,但是在集群和分布式情况下,这种jvm级别的锁式无法满足我们的需求,因为一个服务部署在多台服务器上,这些服务器上的jvm是无法通讯的,所以我们需要一种方案来解决分布式情况下数据一致性。
在互联网公司,基本上企业内部都会有自己的一套分布式锁开发框架
前言分布式锁一般有三种实现方式:
数据库乐观锁
基于redis实现分布式锁
基于zooKeeper实习哪分布式锁
本次讲着重介绍zooKeeper实现分布式锁,和与数据库和redis实习分布式锁的对比。
核心zookeeper的分布式锁主要是依据临时节点和事件监听机制来完成的
curator框架实现zookeeper分布式锁前提:需要搭建起zookeeper基础架构,并且使用gateway网关做负载均衡
12345<dependency> <groupId>org.apache.curator</groupId> <artif ...
分布式事务之seata
分布式事务之seata分布式事务基础事务概念事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都被撤销。
事务可以看做是一次大的操作,它由不同的小操作组成,这些操作要么全部成功,要么全部失败。
例如
转账:包含转出和转入操作
网购:包含下单、扣减库存、支付操作
四个特性
原子性(Atomicity):操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态。要么全部执行,要么全部不执行
一致性(Consistency):事务的执行使数据从一个状态转换为另一个状态,数据库的完整性约束没有被破坏。能量守恒,总量不变
eg: 拿转账来说,假设用户A和用户B两者的钱加起来一共是2000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是2000,这就是事务的一致性。
隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。信 ...
MySQL面试题
列式数据库的使用场景mysql为什么用b+树而不用跳表mysql走索引时范围查询和等值查询的io次数
Redis缓存和数据库一致性问题
Redis缓存和数据库一致性问题缓存应用和数据库在更新时经常会出现不一致的问题,采用哪种策略,值得去思考。从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案。
先删除缓存,再更新数据库
该方案会导致不一致的原因是。同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:(1)请求A进行写操作,删除缓存(2)请求B查询发现缓存不存在(3)请求B去数据库查询得到旧值(4)请求B将旧值写入缓存(5)请求A将新值写入数据库上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。那么,如何解决呢?采用延时双删策略
123456public void write(String key,Object data){ redisUtils. ...
redis分布式锁
背景为了保证数据的一致性,在一些业务处理中都会选择加锁来保证数据的一致性。在单机模式下我们通常选择使用synchronized等这种JAVA提供好的jvm锁来实现,但是在集群和分布式情况下,这种jvm级别的锁式无法满足我们的需求,因为一个服务部署在多台服务器上,这些服务器上的jvm是无法通讯的,所以我们需要一种方案来解决分布式情况下数据一致性。
在互联网公司,基本上企业内部都会有自己的一套分布式锁开发框架
前言分布式锁一般有三种实现方式:
数据库乐观锁
基于redis实现分布式锁
基于zooKeeper实习哪分布式锁
本次讲着重介绍redis实现分布式锁,和与数据库和zooKeeper实习分布式锁的对比。
可靠性为了保证分布式锁的可用,我们至少要保证锁的实现同时满足以下四个条件:
互斥性。在任意时刻,只能有一个客户端持有锁
不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁
具有容错性。只要大部分的redis节点正常运行,客户端就可以加锁和解锁
解铃还须系铃人。加锁和解锁的对象必须是同一个客户端,客户端不能把别人加的锁给解了。
redi ...
redis面试题
在分布式数据库中CAP原理CAP+BASECAP123456789C:Consistency(强一致性)A:Availability(可用性)P:Partition tolerance(分区容错性)注意:分布式架构的时候必须做出取舍。一致性和可用性之间取一个平衡。多余大多数web应用,其实并不需要强一致性。因此牺牲C换取P,这是目前分布式数据库产品的方向
经典CAP图123456CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三大类:CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
BaseBASE就是为了解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案。
BASE其实是下面三个术语的缩写: 基本可用(Basically Ava ...