JVM内存结构
类加载子系统
类加载器子系统负责从文件系统或网络中加载class文件,class文件有特定的文件头标识
ClassLoader 只负责class文件的加载,至于是否可以运行是由Execution Engine(执行引擎)决定
加载的类信息存放在方法区中,除了类信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是class文件中常量池部分的内存映射)
类的加载过程
加载(Loading)Java虚拟机对class文件的加载采用的是按需加载的模式,也就是说当需要用到该类时才会把class文件加载到内存中生成Class对象;而且加载某个class文件时,Java虚拟机采用的是双亲委派的模式(既把请求交由父类加载,是一种任务委派的模式。)
通过类的权限定名获取定义此类的二进制字节流
将这个字节流存储所代表的静态结构转化为方法区的运行时数据结构
在内存中生成一个java.lang.Class对象,作为方法区这个类各种数据的访问入口
如果一个类使用同一个ClassLoader并且类的完整路径一样,那么JVM判定为是同一个Class对象
严格上 ...
MySQL的锁
锁分类
当多个事务或进程访问同一个资源时,为了保证数据的一致性就会用到锁机制,在MySQL中锁有多种不同的分类。
以操作粒度区分
行级锁、表级锁和页级锁
表级锁:每次操作锁住整张表。锁定的粒度大、开销小、加锁快;不会发生死锁,但发生锁冲突的概率极高,并发度最低,应用在InnoDB、MyISAM、BDB中;
行级锁:每次操作锁住一行数据。锁定的粒度小、开销大、加锁慢;会出现死锁,发生锁冲突的概率极低,并发度最高,应用在InnoDB中;
页级锁:每次锁定相邻的一组记录。锁定粒度、开销、加锁时间介于行级锁和表级锁之间;会出现死锁,并发度一般,应用在BDB中;
行锁
表锁
页锁
MyISAM
√
BDB
√
√
MyISAM
√
√
以操作类型区分
读锁、写锁
读锁(S):共享锁,针对同一份数据,多个读操作可以同时进行不会互相影响;
写锁(X):排它锁,当前写操作没有完成时,会阻塞其他读和写操作;
为了允许行锁和表锁的共存,实现多粒度的锁机制,InnoDB还有两种内部使用的意向锁,这两种意向锁都是表锁:
意向读锁(IS)、意向写锁(IX): ...
MySQL架构原理
MySQL体系架构
MySQL Server的架构可以分为以下四层:网络连接层、服务层、存储引擎层和系统文件层。
网络连接层客户端连接器提供与MySQL服务器连接的支持,支持市面上的主流语言。例如:Java、Python等,它们通过各自的API与MySQL建立连接。
服务层服务层是MySQL Server的核心,主要包含系统管理和控制工具、连接池、SQL接口、解析器、查询优化器、缓存六个部分。
连接池负责管理与客户端与服务端的连接,一个线程负责管理一个连接。
系统管理和控制工具备份恢复、安全管理、集群管理等。
SQL接口用于接收客户端的SQL指令(DDL、DML、存储过程、视图等),返回用户需要的结果信息。
解析器负责将客户端的SQL指令解析生成一个解析树。然后根据一些SQL规则检查解析树是否合法。
查询优化器解析树通过解析器的检查后,交由查询优化器来生成执行计划,与存储引擎层进行交互。
缓存缓存机制是由一系列小缓存组成的:表缓存、记录缓存、权限缓存、引擎缓存等。如果查询命中缓存则可以直接从缓存中获取结果直接返回。
存储引擎层存储引擎负责MySQL中数据的存储与提取,与系统文件进行交互 ...
Zookeeper源码环境搭建
下载源码本文以 Zookeeper 3.5.4 为例,源码下载地址:https://github.com/apache/zookeeper/tree/release-3.5.4
源码编译在命令行使用 ant 编译的时候出现了一些问题,在网上没有找到解决方案,所以使用 idea 进行编译,希望有知道原因的大佬指点迷津,下图为执行 ant eclipse 后的报错信息
下边是具体操作步骤
首先使用 idea 打开项目
右击 build.xml ,选择 Add as Ant Build File
展开右侧 Ant 侧边栏,双击 eclipse
等待 build 完成,时间根据自身网络环境而定
编译完成后会产生eclipse 的配置文件
源码导入这时关掉项目窗口,选择 File --> New --> Project from Existing Sources...
选择项目目录,选择导入Eclipse项目,然后一路 Next
这时候源码就导入成功了~
启动Zookeeper服务端针对单机版本和集群版本,分别对应两个启动类:
单机:ZooKeeperSe ...
Zookeeper一致性协议——ZAB
ZAB协议简介Zookeeper通过ZAB保证分布式事务的最终一致性。
ZAB全称Zookeeper Atomic Broadcast(ZAB,Zookeeper原子消息广播协议)
ZAB是一种专门为Zookeeper设计的一种支持 崩溃恢复 的 原子广播协议 ,是Zookeeper保证数据一致性的核心算法。ZAB借鉴了Paxos算法,但它不是通用的一致性算法,是特别为Zookeeper设计的。
基于ZAB协议,Zookeeper实现了⼀种主备模式的系统架构来保持集群中各副本之间的数据的⼀致性,表现形式就是使⽤⼀个单⼀的主进程(Leader服务器)来接收并处理客户端的所有事务请求(写请求),并采⽤ZAB的原⼦⼴播协议,将服务器数据的状态变更为事务 Proposal的形式⼴播到所有的Follower进程中。
问题提出
主从架构下,leader 崩溃,数据一致性怎么保证?
选举 leader 的时候,整个集群无法处理写请求的,如何快速进行 leader 选举?
ZAB过程ZAB协议的核⼼是 定义了对于那些会改变Zookeeper服务器数据状态的事务请求的处理⽅式
所有事务必须由 ...
Zookeeper简介
Zookeeper是⼀个开源的分布式协调服务,其设计⽬标是将那些复杂的且容易出错的分布式⼀致性服务封装起来,构成⼀个⾼效可靠的原语集,并以⼀些简单的接⼝提供给⽤户使⽤。
zookeeper是⼀个典型的分布式数据⼀致性的解决⽅案,分布式应⽤程序可以基于它实现诸如数据订阅/发布、负载均衡、命名服务、集群管理、分布式锁和分布式队列等功能。
zookeeper基本概念集群角色 Zookeeper 中引入了了 Leader 、 Follower 、 Observer 三种⻆⾊。 Leader 服务器为客户端提供读和写服务,除 Leader 外,其他机器包括 Follower 和 Observer 都能提供读服务。唯⼀的区别在于 Observer 不参与 Leader 选举过程, 不参与写操作的过半写成功策略,因此 Observer 可以在不影响写性能的情况下提升集群的性能。
会话(session)指客户端会话, ⼀个客户端连接是指客户端和服务端之间的⼀个TCP⻓连接
数据节点(Znode)ZooKeeper将所有数据存储在内存中,数据模型是⼀棵树 ( ZNode Tree ),由斜杠( ...
一文详解Spring循环依赖
什么是循环依赖?大家都知道spring的核心是一个实现了AOP的IOC容器,那么IOC容器对于bean的初始化,会遇到以下情况:当BeanA初始化时,它依赖的对象BeanB也需要执行初始化,如果BeanB里也依赖了BeanA,则又会开始执行BeanA的初始化,那么这样会无限循环,导致初始化异常如下所示。
Spring已经很好的解决了这个问题,这个解决方法就是三级缓存。
什么是三级缓存?我们以上图中A、B互相依赖为例,spring为了解决循环依赖问题,做了以下步骤:
A通过反射创建的“初级bean”a放入到三级缓存中,再执行a的属性填充,这时发现依赖B,开启B的初始化。
B通过反射生成的“初级bean”b放入到三级缓存中,再执行b的属性填充,这时发现依赖A,开启A的初始化。
从三级缓存中找到a,A不再创建新对象,把它移动到二级缓存中,返回a。
b拿到a的引用,设置到b对应的字段上,属性填充完成,将b从三级缓存暴露到一级缓存中,返回b。
a拿到b的引用,设置到a对应的字段上,属性填充完成,将a从二级缓存暴露到一级缓存中,返回a,A对应的实例Bean初始化完成。
其简易时序图 ...
IOC容器加载流程
Spring容器的AbstractApplicationContext#refresh()【容器刷新】源码解析;本文只记录大体步骤, 细节部分自行阅读源码;
AbstractApplicationContext#refresh()是IOC容器加载的主要流程,源代码如下
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110@Override public void refresh() throws BeansException, IllegalStateException { // 对象锁加锁 synchronized (this.startupShutdownMonitor ...
Spring Bean 生命周期
实例化Bean
设置Bean属性值
判断是否实现BeanNameAware,如果实现调用其setBeanName方法
判断是否实现BeanFactoryAware,如果实现调用其setBeanFactory方法
判断是否实现ApplicationContextAware,如果实现调用其setApplicationContext方法
调用BeanPostProcessor的预初始化方法
判断是否标注@PostConstruct注解,如果有则执行
判断是否实现InitializingBean,如果实现调用其afterPropertiesSet方法
判断是否配置初始化方法(init-method)
调用BeanPostProcessor的后初始化方法
是否为singleton
singleton: 将Bean放入SpringIOC的缓存池中
prototype: 将Bean交给调用者,后续不进行管理(不参与后续步骤)
执行@PreDestory标注的方法
调⽤DisposableBean的destory⽅法
调⽤属性配置的销毁⽅法(destory-method)
Spring Framework 5.0.x 模块组成、体系结构、整体架构
核心容器(Core Containe)核心容器提供了Spring框架的基本功能,是其它模块建立的基础,有 spring-core、spring-beans、spring-context、spring-context-support和spring-expression(Expression Language、SpEL)组成。spring-beans和spring-core是spring框架的核心模块。
spring-core提供了框架的基本组成部分,包括控制翻转(Inversion of Control, IOC)和依赖注入(Dependency Injection, DI)功能。
spring-beans提供了BeanFactory,BeanFactory接口是spring框架中的核心接口,它是工厂模式的经典实现。BeanFactory使用控制翻转对应用程序的配置和依赖性规范与实际的应用程序代码进行了分离。但BeanFactory容器实例化后并不会自动创建实例化Bean,只有当Bean被使用的时候BeanFactory容器才会对该Bean进行实例化与依赖关系的装配。
spring ...