自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

JellyfishMIX 的博客

Talk is cheap. Show me the code. --Linus Torvalds

  • 博客(95)
  • 收藏
  • 关注

原创 ReentrantLock 源码分析

tryAcquire 方法由子类实现 if(!}AbstractQueuedSynchronizer 的 acquire 方法是一个模板方法。模板方法的定义:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。

2022-09-23 12:59:11 431 1

原创 AQS(AbstractQueuedSynchronizer) 源码分析

AQS 全称 AbstractQueuedSynchronizer,是 juc 包(java.util.concurrent)中一个同步器开发框架,用于支持上层的锁。本文逐行分析核心逻辑。

2022-09-23 12:56:28 298

原创 kafka 高吞吐设计分析

非零拷贝发送数据过程: 用户执行系统调用读磁盘,用户态切换成内核态。硬盘上的数据通过 DMA 读入内核空间后,cpu 拷贝至用户空间,切换回用户态。执行网络 IO 系统调用,用户态切换成内核态,cpu 拷贝数据至内核空间(socket 缓存),通过 DMA 写入网卡。存在两次 cpu 拷贝和两次内核态用户态切换浪费。

2024-04-05 00:30:35 599

原创 kafka 消息防丢失/消息防重复设计分析

消息语义(诉求)有三种。分别是: 消息最多传递一次(消息不重复), 消息最少传递一次(消息不丢失), 消息有且仅有一次传递(消息不重复且不丢失)。

2024-04-05 00:25:04 1354

原创 操作系统硬中断/软中断介绍

参考 linux 硬中断软中断的思路,为了避免中断丢失和中断可能占用 cpu 时间过长且未经操作系统调度的问题,把一次完整的中断拆为(硬中断 + 软中断)两部分执行。

2023-12-27 11:06:27 429

原创 设计模式 -- 观察者模式

观察者模式也被称为发布订阅模式。在 GoF 的《设计模式》一书中,它的定义是这样的:中文翻译: 在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。从模型来讲,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。

2023-11-10 02:47:05 660

原创 Failed to get field handle to set library path 问题解决(jdk17 升级)--附 xgboost4j 源码分析

ClassLoader 的 usr_paths 字段在高版本 jdk(例如 jdk17) 中没了,因此 ClassLoader.class.getDeclaredField("usr_paths") 会抛异常 NoSuchFieldException, try catch 把 NoSuchFieldException 的异常栈吞掉了,换成了 IOException 继续网上抛,因此 catalina.out 中异常栈最后在 IOException 处就断掉了。

2023-10-19 10:42:42 263

原创 kafka 对 java NIO 的封装

NetworkReceive: 对 NIO 中读 Buffer 的封装,用来缓存接收的数据。NetworkSend: 对 NIO 中写 Buffer 的封装,用来缓存发送的数据。KafkaChannel: 把 TransportLayer, NetworkReceive 和 NetworkSend 又做了一次封装,隐藏了底层组件的细节。

2023-06-09 14:35:22 1181

原创 javaNIO -- ByteBuffer 原理机制

ByteBuffer 可以理解为是一个 byte 数组,用于读取与写入。ByteBuffer 通过一些精巧的属性和方法, 更高效地使用内存空间。

2023-06-04 02:11:28 428

原创 kafka-Producer Sender 源码分析

发送请求分为两步。1. 第一步是消息预发送,Sender 从 RecordAccumulator 拉取要发送的消息集合,封装成 ClientRequest,传递给 NetworkClient。NetworkClient 首先根据 ClientRequest 构造 InFlightRequest,InFlightRequest 表示已发送但还未收到响应的请求。然后根据收到的 ClientRequest 构造 NetworkSend 类对象,放入到 KafkaChannel 的缓存里,消息预发送结束。

2023-05-16 15:15:59 505

原创 spring-web HandlerAdapter 源码分析

HandlerAdapter 存在的原因是, 处理器(handler)的实现有多种,例如实现 Controller 接口,实现 HttpRequestHandler 接口,或者使用 @RequestMapping 注解将方法作为一个处理器等。导致 springMVC 无法直接执行这个处理器,所以这里需要一个适配器(adapter),由它去执行处理器(handler)。

2023-05-09 17:30:41 661

原创 synchronized 的 monitor 机制

monitor 是 synchronized 中用以实现线程之间的互斥与协作的主要手段。每个 monitor 在每个时刻,只能被一个线程持有,该线程就是 activeThread,其它线程都是 waitingThread,分别在两个队列 entrySet 和 waitSet 里等候。在 entrySet 中等待的线程状态是 waiting for monitor entry,而在 wait set 中等待的线程状态是 in Object.wait()。

2023-04-11 16:57:04 933

原创 spring-web HandlerMethodArgumentResolver 源码分析

HandlerMethodArgumentResolver 在解析参数时使用,使用了组合模式 + 策略模式。AbstractNamedValueMethodArgumentResolver 是基于名称获取值的 HandlerMethodArgumentResolver 抽象基类,提供根据参数名称解析的能力。NamedValueInfo 是静态内部类,对应注解的属性。

2023-02-17 21:00:08 963

原创 spring-web InvocableHandlerMethod 源码分析

HandlerMethod,处理器的方法的封装对象。HandlerMethod 只提供了处理器的方法的基本信息,不提供调用逻辑。InvocableHandlerMethod,继承 HandlerMethod 类,可调用的 HandlerMethod 实现类。

2023-02-17 20:56:47 823

原创 spring-web DispatcherServlet 源码分析

Servlet 接口提供处理请求的能力。请求来自于 web 容器,例如 tomcat, JBoss, Jetty 等。spring-web 应用和 web 容器共同遵守 Servlet 规范。Servlet 接口有一个非常重要的实现类 HttpServlet,实现了 service 方法,SpringMVC 框架中的 DispatcherServlet 就是继承自 HttpServlet。

2023-02-17 20:53:00 705

原创 tomcat-container 源码分析

1. tomcat 由 connector 和 container 两部分组成,connector 接收到请求后,先将请求包装为 request,然后传递给 container 进行处理,最终返回给请求方。2. tomcat-container 按照包含关系一共有 4 个容器: StandardEngine, StandardHost, StandardContext, StandardWrapper。

2023-02-17 20:49:35 543

原创 BeanPostProcessor 源码分析

BeanPostProcessor 的调用时机,在初始化 bean 的 initializeBean 方法中,执行 invokeInitMethods 方法,调用 bean 的 init 方法及此阶段相关生命周期函数来初始化 bean。

2023-01-31 22:50:18 185

原创 @PostConstruct 注解源码分析

@PostConstruct 注解加在一个 bean 的方法上,当此 bean 被 spring-ioc 初始化时,自动调用此方法。注意,此类的实例需要作为 bean 交由 spring-ioc 管理时,注解才能生效。实现原理是借助了 BeanPostProcessor 的机制,具体地说,是 InitDestroyAnnotationBeanPostProcessor。

2023-01-31 22:39:29 718

原创 tomcat-connector 源码分析

NioEndpoint 组件是 IO 多路复用模型的一种实现,包含 Acceptor, Poller, LimitLatch, SocketProcessorBase, Executor 共 5 个组件。主体结构 Acceptor + Poller + Executor 线程池是典型的主从 reactor 模式。

2023-01-06 11:29:36 685

原创 设计模式--reactor 模式

reactor 模式通常应用于网络 IO 场景,高性能的中间件 redis, netty 都在使用。

2022-12-26 16:24:24 676 2

原创 tomcat 如何启动的 spring-ioc 容器

本文中我们不关注 tomcat 的机制,只需要知道在这个 xml 中,给 tomcat 指定了上下文加载路径: WEB-INF/web.xml。一个比较常见的 web.xml 配置,可以看到配置了一个 listener 实现 ContextLoaderListener。ServletContextListener 来自于 javax.servlet 包,是 tomcat 与 spring 的衔接接口,可以监听 tomcat servletContext 相关事件,拥有操作 servlet 上下文的能力。

2022-12-02 16:26:22 587

原创 xml schema 详解

1. xml schema 是定义 xml 文件的合法构建模块,可以理解为是一种编写 xsd 或 xml 文件的语法。使用 schema 语法编写的文件后缀名可以是 .xsd 或 .xml。2. xsd(xml schema definition) 文件,后缀名 .xsd,定义 xml 文件中可以出现哪些元素, 属性, 元素之间的关系, 顺序, 元素的数量, 元素或属性的类型和值的范围等,是对 xml 文件的一种约束方式。xsd 文件也使用 schema 语法编写。

2022-11-18 00:45:34 1124

原创 mysql foreach 写法,多条 sql 与一条 sql 的性能消耗分析

比如有 100 条 sql,如果不手动开启事务把这 100 条 sql 放在同一个事务中执行,那么这 100 条 sql 会分别在 100 个隐式事务中。每个事务占用一个连接,这样就占用了 100 个连接。

2022-11-09 02:20:35 897

原创 传统关系型数据库(mysql),缓存(redis),elasticsearch

toC 或高 QPS 的应用,通常会在 mysql 前面加缓存(例如 redis)。查询的数据如果缓存中有,则直接从缓存中返回(称为命中缓存),不再查询 mysql,减少了对 mysql 的 IO 压力。

2022-11-04 16:19:03 1646 1

原创 由 mysql 中的一次慢查询,来看 order by 的文件排序和索引排序

在 mysql 中 filesort 的实现算法有两种:双路排序:根据查询条件取出排序字段,和可以直接定位行数据的行指针信息,这也是第一次 IO。然后在 sort buffer 中进行排序。把行指针排序好后,要再进行一次 IO 将具体的行查询字段读出,才能返回结果。单路排序:根据查询条件取出排序字段和需要查询的行字段(一次 IO),然后在 sort buffer 中进行排序。排序后就可以返回结果了。

2022-10-29 11:52:41 685

原创 Class.forName() 与 ClassLoader.loadClass() 的区别

Class.forName() 的方式加载类时,默认会执行类的初始化。ClassLoader.loadClass() 的方式加载类时,类不会被初始化,只有显式调用加载的类时才会进行初始化。采用 ClassLoader 进行懒加载,不会调用类的 static 代码块,实现延迟加载。

2022-10-28 23:09:11 605

原创 mysql 与 es 数据同步常见方案

这种方式能否实现秒级的数据同步,取决于 mysql 表中的数据量和用来收集数据的 sql 执行时间。当然能否真正做到秒级的数据同步,除了 sql 以外,其他环节(比如整理数据格式,传输至 es)的耗时也要考虑。优点:这种方式的好处是代码侵入性低,不需要在之前写 mysql 的地方加写 es 的代码。缺点:这种方式代码侵入性强,要在之前写 mysql 的地方加写 es 的代码。如果每秒调度一次 logstash 的脚本,就可以每秒执行一次 sql 收集 mysql 表中的数据,然后灌入 es。

2022-10-28 22:59:55 5454

原创 redis 的渐进式 rehash,为什么 java 不采用渐进式 rehash

渐进式 rehash 只适合用在作为共享变量的哈希表中,且多次方法调用(特别是多次请求)都会去操作这个共享变量。这样才能发挥其 rehash 耗时每次调用均分的优势。比如 redis 的 dict 就是很好的例子。

2022-10-28 22:49:33 366

原创 JVM safe point 安全点和 counted loop 可数循环

图中主线程在进入 safe point 后,发现 STW 标志位为 true(为什么 STW 标志位为 true 后面再分析),阻塞在安全点,需要等待一次 GC 执行后才能离开安全点。而且由于 counted loop 花费的时间更长了,导致主线程要在安全点等更久,其他线程才能完成 counted loop,进入安全点。Thread.sleep() 方法是一个 native 方法,在从 native 方法返回后,JVM 会在当前线程设置一个安全点,让线程进入这个安全点。

2022-10-28 22:48:00 939

原创 各种开源许可 Lincense

Apache Licence 2.0 是著名的非盈利开源组织 Apache 采用的协议。鼓励代码共享和尊重原作者的著作权,允许修改代码、发布 (作为开源或商业软件均可)。

2022-10-28 22:46:58 3373

原创 redis cluster 集群模式存在的问题

如果用子线程去执行 migrate,那么 redis 就是多线程操作数据,这样会引入线程之间的锁竞争和并发控制,这就违背了最初的设计。此外,RDB 的生成是 fork 了主进程,生成快照,不是子线程。咨询了 DBA 同事,解决方案是用 DBA 自己的工具(这个工具可以根据具体情况去开发),将数据拆分迁移到其他分片,并没有使用 redis 官方的命令 migrate。migrate 命令是一个原子操作,它在执行的时候会阻塞进行迁移的两个实例,直到以下任意结果发生:迁移成功,迁移失败,等待超时。

2022-10-28 22:45:07 2246

原创 设计模式--builder 模式

拥有一个负责组装的方法 void construct(Builder builder),在这个方法中通过组织并调用 builder 的方法,可以设置 builder。设置完成后,通过 builder 的构建方法 getProduct() 获得最终的产品。定义了构建 Product 的构建用抽象方法,其 Builder 实现类需要实现这些构建用方法。ConcreteBuilder: Builder 的实现类,实现 Builder 的抽象方法,编写此种 Builder 实现的方法。

2022-10-28 22:42:41 752

原创 适配器模式

适配器模式(Adapter)的定义如下:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。自己的理解,使用一个类 A 去实现接口 B,这样可以做到让类 A 兼容接口 B。

2022-10-28 22:40:33 96

原创 ConfigurableBeanFactory 源码分析

可配置的 BeanFactory,声明了对 BeanFactory 各种各样的配置能力,如 bean 的作用域,bean 的 classLoader,bean 的元数据缓存,bean 的表达式解析器,类型转换器,属性编辑器等。实现此接口即拥有对 BeanFactory 的配置能力。

2022-10-28 22:38:29 304

原创 无状态编程, lambda 表达式中传入的局部变量,为什么需要是不可变的(final)

本文将会根据以下顺序进行叙述:lambda 表达式中传入的局部变量,为什么需要是不可变的(final)?函数式编程提倡的无状态。无状态服务。

2022-10-28 22:36:12 1105

原创 guava cache 源码分析 -- 缓存机制

这样性能会有一些损耗,可预见的,频繁的过期和加载,阻塞等待过程会让性能有较大的损耗。默认的 CacheLoader#reload 方法会同步调用我们重写的 CacheLoader#load,所以如果我们传入的 CacheLoader 未重写 reload 方法,默认实现是同步加载。请注意,这里同步还是异步加载,主要看传入的 CacheLoader 实现类是否重写了 reload 方法。请注意,这里同步还是异步加载,主要看传入的 CacheLoader 实现类是否重写了 reload 方法。

2022-10-24 23:39:39 658

原创 guava cache 源码分析 -- builder 模式

guava cache 的 builder 模式,Product 类有两个,一个是 LocalCache,一个是 LocalLoadingCache。可以认为 build 出来的是对外暴露的 Product 类–LocalLoadingCache,LocalLoadingCache 使用了内部的 Product 类 LocalCache。stats 方法,返回此 cache 的累积统计信息的当前快照。asMap 方法,返回一个线程安全的 map,此 map 是 cache 的视图。

2022-10-24 23:38:43 380

原创 apache.commons.lang3 中的 Pair 源码分析

Pair 用于存储左右元素对,Pair。主要有两个子类,ImmutablePair 和 MutablePair。

2022-10-24 23:36:46 1024

原创 dubbo ExtensionLoader 源码分析

主要是一些缓存 ConcurrentMap,ExtensionLoader 和 extension 创建时的部分线程安全,借助于 ConcurrentMap 的原子化 api 保证。使用 holder 用于持有目标 extension 实例,并在 extension 实例缓存中根据 name 获取。具体地说,指定的 instance 属性如果有 extension,此方法将会给这些属性注入 extension。获取 extension,如果 extension 不存在,会进行创建。

2022-10-24 23:34:29 206

原创 java SPI 机制与 dubbo 对 SPI 机制的扩展

SPI,全称为 Service Provider Interface,是一种服务发现机制,在 classpath 路径下的 META-INF/service 路径查找以接口的全限定名命名的文件,文件内容是接口实现类的全限定名,自动加载实现类。简单来说是一种动态替换发现机制,接口运行时才发现具体的实现类,只需要在运行前添加一个实现即可,并且将实现描述给 jdk 即可,这里的描述便是上面提到的 META-INF/service 下的配置。也可以随时对该描述进行修改,完成具体实现的替换。

2022-10-24 23:31:28 171

空空如也

空空如也

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

TA关注的人

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