自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(146)
  • 问答 (2)
  • 收藏
  • 关注

原创 文章目录

spring源码-bean加载整体流程spring源码-循环依赖spring源码:九大后置处理器方法spring源码:实例化bean的准备工作spring源码:扫描bean的原理

2021-03-06 18:50:29 171 2

原创 ConcurrentHashMap原理

所以,总结来看,concurrentHashMap线程安全的原因有以下几点会通过cas,对tab[i]位置进行赋值在插入元素的时候,会通过synchronized来加锁在统计hashmap中元素个数的时候,通过volatile修饰的变量,以及cas操作来完成+1。

2023-03-16 09:28:09 369 1

原创 nacos源码入门

这个bean是监听了WebServerInitializedEvent事件,在监听到这个事件之后,会进行一些列的逻辑,我们来看下主要关注这里的register()方法对于nacos注册中心,业务应用是如何注册的,再总结下在应用启动之前,我们需要引入springcloud-nacos相关的jar包。

2023-03-07 18:42:52 603

原创 sentinel源码入门

总结来看,sentinel的源码逻辑是比较清晰的通过springboot的自动注入,注入了一个切面在切面中,通过环绕通知,分别执行slot的entry()和exit()方法在调用entry()方法之前,会通过spi机制,获取到所有的slot,并构建成一个执行链在所有的slot被调用完毕之后,会开始调用业务的方法在最后的finally方法中,会调用exit(),执行各个slot的exit()方法。

2023-03-07 08:20:58 517

原创 seata源码-全局事务提交 服务端源码

以上,就是全局事务提交的逻辑,整体看下来,我们可以发现,对于全局事务提交的时候,分支事务在处理的时候,是异步来处理的,这是和回滚逻辑有很大的区别,因为上篇博客中,我们有看到,全局事务回滚时,分支事务在第二阶段,是同步处理的,在接收到请求之后,会根据undoLog生成回滚sql,并执行,然后删除undoLog数据,但是对于全局事务提交的第二阶段,会发现,接收到请求之后,直接塞到了队列中,通过异步的请求,没1000ms执行一次提交的逻辑。

2023-02-19 10:23:10 586

原创 seata源码-全局事务回滚服务端源码

对于分布式事务,进行全局回滚的逻辑,还是比较简单的在事务管理者这边发起全局事务回滚的请求seata服务端,也就是事务协调者接收到请求之后,会向所有的rm,发起netty请求,进行分支事务的处理各个分支事务,会根据undoLog日志,生成回滚的sql,然后执行seata服务端在等分支事务返回状态之后,会先删除分支事务,在删除分支事务之前,会将分支事务加的锁给删除(这里的锁,如果是mysql的话,其实就是写入到mysql中的一条记录)

2023-02-12 10:13:41 1159

原创 openFeign源码学习

所以,openFeign其实底层,就是通过代理对象的方式,帮我们去发起远程调用,在代理对象中,会分别区分使用微服务名进行负载均衡的逻辑和程序员直接指定ip、端口的方式,本质上没太大的区别,只是一个集成了ribbon,一个直接发起调用。

2023-02-11 10:37:04 532

原创 seata源码-开启全局事务服务端源码

通过上面服务端的代码来看,其实在开启全局事务的时候,服务端的逻辑是比较简单明了的根据事务id + ip + port生成全局事务id根据全局事务id,写入到globalTable表中一条记录这里写到数据库中的记录,就是全局事务的信息,在后面分支事务提交和回滚的时候,都会相应的操作这条记录。

2023-02-07 08:32:48 466

原创 seata源码-入门

这篇博客,主要是站在client端的角度,去看了一些源码,大致的逻辑,再总结下当业务应用启动的时候,会通过seata的bean对象,给需要处理全局事务的service,生成代理对象在service的方法被执行的时候,会被interceptor拦截到在被拦截之后,会先开启全局事务,接着执行目标方法,如果没有异常,就进行全局事务提交,如果有异常,就进行全局事务回滚。

2023-02-05 13:52:26 514

原创 rocketmq源码-consumer负载均衡逻辑

这篇笔记主要记录consumer在启动过程中,负载均衡的逻辑,多个消费者组成一个消费者组,对于集群模式,同一个消费者组中的多个消费者共同消费一个topic下的所有消息,所以每个consumer可能会处理N个messageQueue,至于哪个consumer消费哪个messageQueue,是由负载均衡策略决定的。

2023-02-04 12:59:04 348

原创 rocketmq源码-consumerQueue和indexFile文件写入

在rocketmq的文件中,除了commitLog文件,还有两个重要的文件,分别是indexFile文件和consumerQueue文件,这篇笔记主要记录这两个文件的数据是怎么写进去的consumeQueue文件中对应topic下的一个queue,在consumeQueue文件中,存放了三部分数据:分别是当前消息在commitLog中的offset、以及消息的大小、tagCode信息。

2023-02-04 12:58:01 549

原创 rocketmq源码-consumer已消费offset更新逻辑

这篇博客,主要记录consumer已经消费的offset是如何更新的对于集群模式,offset是维护在broker中的;而广播模式,offset是存储在本地文件中(暂时没有验证具体存储的位置,是根据源码推测的)不管是pull模式,还是push模式,都需要维护consumer当前已经消费的offset更新offset的逻辑,大致是这样的:1.client从broker拉取消息2.然后client回调业务系统的消费者所注册的messageListener,对消息进行处理。

2022-12-20 13:48:45 819

原创 rocketmq源码-关于消费者push模式和pull模式的对比

按照网上大部分的说法,对于push模式是broker自己推送消息给consumer,如果这个推断成立,那broker设计我认为是有问题的,因为对于broker而言,我只是去存储消息的,我不关心你是push还是pull,我只需要提供接口,让client来查询消息就可以了,如果broker还需要关心consumer的模式,那系统就太耦合了;对于pull模式,是通过netty请求去broker拉取消息,拉取到消息之后,将消息存入到了内存中的一个队列中,存入到队里中之后,立即发起下次请求;

2022-12-16 08:34:36 1232 2

原创 rocketmq源码-broker处理consumer拉取消息请求

在前面consumer拉取消息的博客中,有说过,对于consumer,在拉取消息的时候,是需要指定code码的,在consumer去broker拉取消息的时候,指定的code码是:PULL_MESSAGE,所以这篇博客,我们简单看下broker在接收到netty请求之后,是如何处理的这里看起来,是比较简单明了的,就是根据当前请求中的offset和size,从commitLog中拉取消息数据,然后返回就可以了;

2022-12-15 18:49:59 570

原创 rocketmq源码-pull模式拉取消息、同步拉取消息

上一篇博客,记录的是push模式,异步发送netty请求拉取消息的代码,这篇博客主要记录consumer发送同步netty请求,去拉取消息的逻辑,但是对于同步发送请求,需要结合LitePullConsumer来看在Lite PullConsumer中有两种方式,分别是:subscribe和assign模式,这两种模式的区别,我的理解是:前者是mq帮我们进行负载均衡,后者我们可以按照自己的需求去进行负载均衡,给当前消费者分配messageQueue。

2022-12-15 18:47:07 1194

原创 rocketmq源码-consumer拉取消息(push模式)

在前面consumer启动的博客中,有说过,在启动过程中,有两个比较重要的逻辑,分别是负载均衡和拉取消息的service,这篇博客,主要记录拉取消息的service,因为前面的demo和这篇笔记中的demo,都是基于push模式来学习的,所以前面的笔记都是基于push模式的,但是最近看了下pull模式,和push模式的代码还是有点区别的,所以后面单独起一篇博客,记录pull模式的逻辑对于消费者有两种模式:pull和push但是在push模式中,又分为了顺序消费和并行消费。

2022-12-15 09:10:13 1055 1

原创 rocketmq源码-consumer启动

这篇笔记记录consumer启动的逻辑consumer主要是负责去broker中拉取消息,然后将拉取到的消息,交给消费者去处理consumer本质上也是一个netty客户端,所以,在启动的时候,和producer有很多相似的点,但是有1个区别点:1、producer的负载均衡是在真正去发送消息的时候,通过轮询的方式,选择其中的一个messageQueue;

2022-12-15 08:50:53 313

原创 rocketmq源码-broker接收消息

这篇笔记,主要记录producer在通过netty发送了请求之后,在broker这边是如何处理的消息的这里是broker的nettyServer端接收客户端发送消息的入口,不解释为什么会是这个类了。

2022-12-15 08:46:29 329

原创 rocketmq源码-producer发送消息

这篇笔记,记录producer发送消息的相关源码我们以最简单的demo为例i < 3;i ++) {try {}我们要看的是:producer.send()这个方法校验消息的合法性根据消息中的topic,找到对应的路由信息根据路由信息 以及轮询策略,找到要发送的messageQueue构建netty请求,发送到broker。

2022-12-14 08:47:07 206

原创 rocketmq源码-producer启动流程

创建、启动producer的逻辑,是写在业务系统中的,根据rocketmq源码中的demo,只需要这几行代码,就可以启动producer这几行代码的逻辑,也比较简单,就是创建一个producer对象,创建对象时,需要指定producerGroup’然后设置nameSrv地址;最后调用其start()方法即可所以,启动producer最为核心的代码,是在start()方法中在start()方法中,最重要的是mqClientFactory.start()方法。

2022-12-13 19:05:23 340

原创 rocketmq源码学习-broker启动

这篇笔记记录broker启动的源码学习broker主要完成一下几件事情:1.接收producer的发送请求,并对消息进行持久化、同步其他节点2.接收consumer读取消息星球3.定时向nameSrv注册心跳信息,保持连接在启动的时候,也是分了两个方法1、创建brokerController2、启动brokerController总结来看,broker在启动的时候启动nettyServer和nettyClient。

2022-12-13 09:49:13 997

原创 rocketmq源码学习-nameServer

最近看了下rocketmq的源码,计划针对最近的学习,做一个笔记,先从nameServer启动的逻辑开始记录吧在rocketmq中,有四个关键的组件nameServerbrokerproducerconsumer这四个组件之间的关系是这样的nameSrv启动的源码比较简单,其实就干了两件事情1、初始化nettyServer服务端,用来接收客户端请求,这里的客户端,包括:producer、consumer、broker2、启动了一个定时任务,定时去扫描内存中不活跃的broker信息。

2022-12-13 09:44:54 442

原创 mybatis一级缓存和二级缓存区别点

我们通常说mybatis中一级缓存是sqlSession级别的,二级缓存是namespace级别的,这篇笔记主要来记录下这么说的原理。

2022-08-28 15:58:29 1018 1

原创 mybatis二级缓存默认未开启源码解读

上面有说过,默认的CacheEnable属性默认是true,所以在初始化executor对象的时候,默认会初始化CachingExecutor对象,所以,无论是否使用了二级缓存,都会先调用到cachingExecutor对象中。我们接着来看赋值的逻辑这里,如果props为空(就是在全局配置文件中没有配置settings节点),此时在给各个属性赋值的时候,分别指定了默认值,可以看到,cacheEnable属性值默认是true;可以看到,在真正调用二级缓存前,会有两层判断,分别是cache和useCache;.

2022-08-28 11:55:52 1033

原创 mybatis二级缓存原理

在mybatis中,一级缓存是默认开启的,无法关闭;二级缓存可以选择开启或者关闭,这篇博客主要介绍二级缓存的原理,具体的使用,不再介绍了。

2022-08-28 09:27:00 309

原创 @MapperScan注解原理解析 --> 1.3版本和2.0版本的区别

在1.3版本中,MapperScannerRegistrar的registerBeanDefinitions方法中,会自己初始化一个扫描器,然后去扫描mapper接口,将扫描到的接口,初始化为beanDefinition对象,将beanDefinition对象的beanClass设置为mapperFactoryBean。.........

2022-08-28 07:53:13 317

原创 适配器策略模式

适配器策略模式的使用使用在框架源码中的应用

2022-08-27 20:05:53 233

原创 mybatis源码-plugin源码

在使用mybatis的时候,我们可以自己指定plugin,在sql执行过程中,增加一些额外的逻辑处理,这篇笔记主要记录plugin的原理。

2022-08-27 20:05:28 248

原创 mysql联合索引的使用

这篇笔记主要记录联合索引的使用设置了shopId、userId、relationId三个字段,作为联合索引,这三个字段,都是long类型的,也就是bigint分别验证以下几个场景:场景一:explain select * from testIndex where shopId = 1 and user_id = 1001 and relationId = 1;...

2022-08-18 08:17:00 1034

原创 @Extension、@SPI注解原理

在dubbo源码中,涉及到一些dubbo自定义的注解,这篇笔记主要记录这些注解的原理和使用方式,了解了这些之后,便于我们对dubbo进行二次扩展dubbo的SPI机制,和Java原生的SPI机制相比,新增了name,可以指定某一个实现类对应的name,我们在使用的时候,可以根据name,获取自己想要使用的扩展类,如果在获取实现类时,指定name为true,默认返回的是@spi注解中指定的name对应的实现类简单来说:@SPI注解中指定的value值,是当前接口默认的实现类,比如,下面的这个截图,就表示Pr

2022-07-03 14:02:40 1915

原创 AopContext对象原理

AopContext的是使用和原理

2022-06-26 17:20:52 670

原创 rocketmq延迟消息实现原理

这篇笔记主要记录延迟队列的实现原理

2022-05-27 08:50:50 2371 1

原创 慢sql优化

慢sql优化大表深分页问题解决:问题描述A表中,数据量大约在150W左右,并且还在持续增长表中的核心字段:id:店铺id:用户id:模板id:我现在的场景是,在A店铺闭店的时候,需要把这个表中A店铺下所有的用户数据都删除,因为考虑到数据量较大,所以采用异步方式来处理异步线程在处理的时候,也是分批处理的,不可能一次全部删除完毕,所以,提供了两个接口:1.切割接口:一次切割1000条数据,然后返回2.执行接口:根据切割接口返回的数据,执行删除操作这两个接口有可能是并行执行的,所以需要考

2022-05-24 20:04:57 304

原创 spring注入list集合

spring可以帮助我们自动的完成bean属性的注入,其中有一个比较特殊的,就是list集合spring中,在使用@Autowired注解注入list集合的时候,并不会根据注入属性值的类型去容器中查找,而是根据list集合的元素类型,从spring容器中找到所有的实现类,放在list集合中,然后注入到bean中...

2022-05-15 09:01:56 9230

原创 git开发分支合并master,revert之后,再次merge,不生效问题

遇到一个问题:开发分支是:feature/test在把开发分支合并到master分支之后,如果因为某些原因,直接revert了代码然后会发现,再次把feature/test分支合并到master的时候,并不会把开发分支的代码合到master中处理办法:1.基于master分支,拉一个新的分支出来:feature/test_new2.找到revert的版本号,需要注意的是:一次revert之后,会有两条revert相关的记录,分别是revert 和revert之后的merge记录,此时需要用的是第

2022-05-10 18:43:34 4857

原创 jdk1.8-hashmap 树化过程

在jdk8中的hashmap,引入了红黑树的概念,那自然就会涉及到树化的过程,这篇笔记单独记录下树化的一些细节

2022-04-20 08:18:36 1300 2

原创 Redis分布式锁加锁失败,休眠机制

redissonLock分布式锁在加锁的时候,如果已经有线程加锁成功,此时的线程会进入等待,比如:当前key还有2S过期,那就休眠2S,这里休眠怎么实现的呢?通过Semaphore来实现?如何实现?初始化Semaphore的permits为0,Semaphore是用来进行资源竞争的一个工具类,初始化时,指定的permits表示同时允许有几个线程持有资源,这里为0,就表示永远不允许有线程持有资源,那这样的话,在tryAcquire()时,只需要指定超时时间为key的过期时间即可,这样的话,就会在过期时间到

2022-04-16 14:31:22 4125

原创 springmvchandlerAdapter和handlerMapping类在什么时候被初始化

springmvc

2022-04-15 08:39:12 322

原创 ThreadPoolExecutor源码笔记

线程池源码

2022-04-13 20:08:12 309

原创 sentinel滑动时间窗口算法统计通过请求数量细节

问题描述昨天写的笔记中,最后我留了一个疑问,疑问是这样的:假如:在0-500ms之间有4次请求,500-1000ms之间有4个请求;在1000ms - 1500ms之间请求次数为0,1600ms的时候,有三个请求进来,此时在进行判断的时候,会把第二个窗口进行reset:也就变成了这样:我的疑问是:此时在统计qps的时候,如果还是直接把两个窗口的请求次数累加到一起,那就统计的不是前1S之内的请求数了;、今天翻了下源码,发现针对这个场景的源码了:源码com.alibaba.csp.sentin

2022-04-02 12:35:51 522 1

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除