- 博客(112)
- 收藏
- 关注
原创 单体到微服务拆分方案
摘要: 微服务迁移需采用渐进式策略,以绞杀者模式逐步替换单体应用功能,确保业务连续性。迁移分为四个阶段:评估规划、服务拆分(通过API网关路由逐步迁移模块)、数据库迁移(四阶段双写方案保障数据一致性)及治理优化(监控、分布式事务)。关键挑战是解决拆分后的数据耦合问题,推荐四种策略:API组合(简单实时)、数据冗余(读多写少)、事件驱动同步(复杂查询)和CQRS(读写分离),其中数据冗余+事件驱动为常用方案,通过异步事件更新冗余数据,实现服务解耦。最终需建立完善的监控与治理体系,保障系统稳定运行。
2025-09-13 23:32:53
907
原创 通俗易懂地讲解JAVA的BIO、NIO、AIO
摘要:本文通过快递站类比生动解释了Java的三种I/O模型:BIO(阻塞式,每个连接独占线程)、NIO(非阻塞式,单线程轮询多连接)和AIO(异步式,操作系统主动回调)。重点分析了各模型的核心原理、代码实现和适用场景:BIO简单但扩展性差;NIO高性能但编程复杂;AIO真正异步但JDK支持有限。文章还同步对比了阻塞/非阻塞、同步/异步的核心概念差异,并附有各模型的代码示例和架构图示,帮助开发者深入理解不同I/O模型的特点和选型考量。
2025-09-13 15:37:01
943
原创 Synchronized原理解析
摘要: Java的synchronized通过三种方式(实例方法、静态方法、代码块)实现线程同步,底层基于对象头和Monitor机制。JVM优化了锁升级(无锁→偏向锁→轻量级锁→重量级锁),根据竞争智能切换。最佳实践包括减小锁粒度、缩短持有时间、使用专用锁对象,高并发场景可选用ReadWriteLock或原子类替代。synchronized保证了原子性、可见性和有序性,是线程安全的核心机制。
2025-09-11 20:50:19
837
原创 ConcurrentHashMap解析
ConcurrentHashMap是Java并发包中的线程安全哈希表实现,采用分段锁(JDK1.7)和CAS+synchronized(JDK1.8)两种机制保证并发安全。1.7版本通过Segment分段锁实现并发控制,而1.8版本优化为更细粒度的桶级别锁,并引入红黑树解决哈希冲突。关键改进包括:更细的锁粒度、多线程协同扩容、链表转红黑树优化查询性能。其原子操作方法(如putIfAbsent)和弱一致性迭代器适合高并发场景,但需注意内存开销和扩容成本。建议JDK1.8+环境下优先使用,特别适用于缓存、计数器
2025-09-04 23:09:46
1020
原创 TreeMap 和 LinkedHashMap原理介绍
本文对比分析了Java中的TreeMap和LinkedHashMap两种有序Map实现。TreeMap基于红黑树,自动按key排序,查找效率O(logN),适合排行榜等排序场景;LinkedHashMap在HashMap基础上增加双向链表维护插入/访问顺序,查找效率O(1),适合缓存等顺序敏感场景。两者在底层结构(红黑树vs哈希表+链表)、排序方式、查询效率等方面存在显著差异。若需排序选TreeMap,需保持插入顺序选LinkedHashMap,仅需快速查找则用普通HashMap。文中通过代码示例和结构图解
2025-09-04 16:31:21
638
原创 SpringCloud整合分布式事务Seata
本文介绍了Spring Cloud Alibaba集成Seata分布式事务的配置步骤,包括:1)添加依赖管理;2)引入Seata依赖和适配器;3)初始化达梦或MySQL的undo_log表结构;4)配置客户端TC连接信息;5)使用@GlobalTransactional注解实现AT模式事务。同时解释了Seata的三个核心组件:TC(事务协调者)、TM(事务管理器)和RM(资源管理器)的角色分工。配置适用于JDK17和Seata 1.6.1环境,通过Nacos实现配置中心和注册中心功能。
2025-09-03 16:47:21
338
原创 介绍分布式事务之Seata
Seata是一款开源的分布式事务解决方案,提供四种主要模式:AT模式(自动事务,基于本地事务+Undo Log)、TCC模式(Try-Confirm-Cancel三阶段)、SAGA模式(长事务补偿)、XA模式(基于数据库XA协议)。AT适合电商订单类系统,TCC适合金融交易,SAGA适合长业务流程,XA适合强一致性金融场景。四种模式在一致性、性能和开发成本上各有优劣,可根据业务需求选择。
2025-08-30 22:28:30
1132
原创 SpringCloud 配置中心的核心原理
本文深入探讨了SpringCloud配置中心的核心原理,主要包含以下内容: SpringBoot启动时通过BootstrapApplicationListener创建专门用于配置中心交互的Spring容器 配置中心客户端配置需放在bootstrap文件中的原因:该容器默认加载bootstrap配置文件 通过PropertySourceLocator接口实现从不同配置中心(如Nacos、Apollo)获取远程配置 @RefreshScope实现动态刷新的机制:会生成代理Bean和原始Bean两个实例 整体流程
2025-08-27 20:57:36
770
原创 MCP Model Context Protocol(模型上下文协议)原理
MCP(模型上下文协议)是一种标准化协议,充当AI模型与外部工具的"翻译官+管理员"。它定义了模型、服务器、客户端和主机的交互方式,使不同AI模型(如GPT、Claude)能够通过统一协议调用数据库、API等外部工具。MCP通过初始化连接、工具发现、异步调用循环等机制工作,具有标准化、扩展性强和安全可控等优势。该协议仅规范客户端与服务端的通信,不涉及模型交互标准,因此实际作用是为模型提供上下文可调用工具的标准化方案。使用需注意工具调用的异步性、错误处理和权限控制等问题。
2025-08-27 09:44:35
730
原创 JWT通俗易懂讲解
JWT(JSON Web Token)是一种用于身份验证的无状态令牌机制。它由三部分组成:头部(说明算法)、载荷(存放用户信息)和签名(防伪标记)。用户登录后获得JWT,后续请求携带该令牌即可验证身份,无需重复输入密码。JWT的优点是服务端无需保存会话状态,适合分布式系统,且信息可扩展。但要注意载荷是Base64编码的明文,不可存放敏感数据。整个流程包括:登录生成JWT、前端存储、请求时验证签名和有效期。相比传统session,JWT就像全国通用的快递单号,任何服务持有密钥即可验证真伪。
2025-08-19 09:28:46
882
4
原创 通俗易懂解释Java8 HashMap
Java 8 HashMap 原理解析 HashMap 是 Java 中基于哈希表的键值对集合,采用数组+链表+红黑树结构存储数据。核心原理如下: 存储结构 数组(桶)存储节点,每个位置可挂载链表或红黑树(冲突时)。 当链表长度>8且数组长度≥64时,链表转为红黑树以提升查询效率(O(n)→O(log n))。 哈希计算 通过扰动函数(hashCode ^ (hashCode >>> 16))混合高低位,减少哈希冲突。 数组下标计算:hash & (table.length
2025-08-02 22:25:21
1125
原创 Oracle11g数据库迁移达梦8数据库方案
SpringBoot项目从Oracle迁移至达梦数据库方案摘要 本文详细介绍了将SpringBoot项目从Oracle迁移至国产达梦数据库(DM)的完整方案。主要内容包括: 迁移准备工作 - 环境确认、工具准备(达梦客户端、数据迁移工具等) 迁移步骤 - 从Oracle数据备份、达梦初始化、表结构迁移、数据迁移到SpringBoot配置调整 兼容性处理 - 数据类型映射、SQL语法适配、存储过程调整等关键技术点 注意事项 - 字符集设置、NULL值处理、自增字段实现等细节问题 测试验证 - 数据一致性检查、
2025-07-30 21:52:47
1301
6
原创 通俗易懂的解释G1垃圾收集器
Java的G1垃圾收集器采用"垃圾优先"策略,将堆内存划分为多个Region区域。其工作流程分为四个阶段:初始标记(短暂STW)、并发标记(后台统计垃圾最多的Region)、最终标记(最终确认)和筛选回收(优先清理垃圾最多的Region)。G1的优势包括并发收集、区域化管理、可预测停顿时间和适合大内存场景,但存在老年代Full GC性能较差和管理复杂的缺点。G1通过智能选择垃圾最多的Region进行回收,同时进行内存整理,有效平衡了回收效率和内存碎片问题。
2025-07-30 21:30:07
350
原创 通俗理解CMS垃圾收集器
CMS垃圾回收器工作原理类比 CMS(Concurrent Mark Sweep)是一种以低延迟为目标的垃圾回收器,其工作过程可类比为高效清理房间: 初始标记(短暂暂停):快速标记正在使用的对象(如手边的物品)。 并发标记(不暂停):后台标记所有关联的存活对象,同时用户线程继续运行。 重新标记(短暂暂停):修正并发标记期间遗漏的新引用。 并发清除(不暂停):清理未标记的垃圾对象,避免碎片问题。 特点:减少停顿时间,适合响应敏感应用,但存在内存碎片和并发失败风险。 核心:像智能清洁工,边工作边打扫,但需短暂停
2025-07-30 09:29:37
424
原创 JUC中的LockSupport工具类的使用上篇
输出了上面2行之后,程序一直无法结束,t1线程调用wait()方法之后无法被唤醒了,从输出中可见, notify()方法在 wait()方法之前执行了,等待的线程无法被唤醒了。说明:唤醒方法在等待方法之前执行,线程无法被唤醒。t1线程中调用 lock.wait()方法让t1线程等待,主线程中休眠5秒之后,调用 lock.notify()方法唤醒了t1线程,输出的结果中,两行结果相差5秒左右,程序正常退出。唤醒方法需要在等待方法之后调用,线程才能够被唤醒。
2025-06-18 17:25:25
282
原创 大模型使用
本文介绍了大模型部署的两种主要方式(本地部署和云平台部署)及其优缺点比较。本地部署分为云服务器和本地机器两种形式,分别存在数据安全性和成本效益上的差异;云平台部署则无需自行维护但存在长期成本问题。详细讲解了使用Ollama工具在本地电脑上部署Qwen3模型的步骤,包括安装、运行和HTTP接口调用方法。同时介绍了阿里云百炼平台的大模型调用流程和API使用要点,重点解析了请求参数中model、messages、stream、enable_search的作用以及响应数据的结构。通过对比不同部署方式的特性,为用户选
2025-06-17 17:16:55
1103
原创 linux安装node版本管理工具NVM
以下路径/usr/local/nvm/nvm-0.39.3为nvm安装路径,编辑vim ~/.bashrc。nvm 的卸载也比较简单,直接删除相关文件和配置项即可。配置环境变量:在文件末尾加上以下配置。
2025-03-12 14:39:15
209
原创 OpenResty开发环境搭建
OpenResty® 是一个基于 Nginx的高性能 Web 平台,用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。官方地址:http://openresty.org/cn/具备Nginx的完整功能基于Lua语言进行扩展,集成了大量精良的 Lua 库、第三方模块允许使用Lua自定义业务逻辑、自定义库。
2024-12-24 10:10:10
555
原创 Consul安装和使用:服务注册与发现
Consul是一个开源的分布式服务发现和配置管理工具。它提供了一个分布式的、高可用的数据存储,可以用来存储键值对、配置数据、服务发现信息等。同时,Consul还提供了HTTP和DNS接口,可以用来查询服务、配置和健康状态等信息。service discovery:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。health checking:健康检测使consul可以快速的告警在集群中的操作。
2024-12-22 22:05:09
491
原创 JUC中的LockSupport工具类的使用下篇
LockSupport类可以阻塞当前线程以及唤醒指定被阻塞的线程。主要是通过park()和unpark(thread)方法来实现阻塞和唤醒线程的操作的。每个线程都有一个许可(permit),permit只有两个值1和0,默认是0。当调用unpark(thread)方法,就会将thread线程的许可permit设置成1(注意多次调用unpark方法,不会累加,permit值还是1)。当调用park()方法,如果当前线程的permit是1,那么将permit设置为0,并立即返回。
2024-12-09 22:24:20
502
原创 JUC中的LockSupport工具类的使用上篇
输出了上面2行之后,程序一直无法结束,t1线程调用wait()方法之后无法被唤醒了,从输出中可见, notify()方法在 wait()方法之前执行了,等待的线程无法被唤醒了。说明:唤醒方法在等待方法之前执行,线程无法被唤醒。t1线程中调用 lock.wait()方法让t1线程等待,主线程中休眠5秒之后,调用 lock.notify()方法唤醒了t1线程,输出的结果中,两行结果相差5秒左右,程序正常退出。唤醒方法需要在等待方法之后调用,线程才能够被唤醒。
2024-12-09 22:23:34
479
原创 JUC中的Semaphore(信号量)
Semaphore(信号量)为多线程协作提供了更为强大的控制方法,前面的文章中我们学了synchronized和重入锁ReentrantLock,这2种锁一次都只能允许一个线程访问一个资源,而信号量可以控制有多少个线程可以访问特定的资源。
2024-12-05 08:28:26
1256
原创 JUC中的循环栅栏CyclicBarrier的6种使用场景
主管相当于 CountDownLatch,干活的小弟相当于做事情的线程。老板交给主管了一个任务,让主管搞完之后立即上报给老板。主管下面有10个小弟,接到任务之后将任务划分为10个小任务分给每个小弟去干,主管一直处于等待状态(主管会调用await()方法,此方法会阻塞当前线程),让每个小弟干完之后通知一下主管(调用countDown()方法通知主管,此方法会立即返回),主管等到所有的小弟都做完了,会被唤醒,从await()方法上苏醒,然后将结果反馈给老板。期间主管会等待,会等待所有小弟将结果汇报给自己。
2024-12-04 08:27:09
976
原创 JUC中等待多线程完成的工具类CountDownLatch,必备技能
CountDownLatch称之为闭锁,它可以使一个或一批线程在闭锁上等待,等到其他线程执行完相应操作后,闭锁打开,这些等待的线程才可以继续执行。确切的说,闭锁在内部维护了一个倒计数器。通过该计数器的值来决定闭锁的状态,从而决定是否允许等待的线程继续执行。常用方法:public CountDownLatch(int count):构造方法,count表示计数器的值,不能小于0,否者会报异常。
2024-12-03 10:00:34
945
原创 同步和异步、并发和并行、阻塞和非阻塞的区别
实际上,如果系统内只有一个CPU,而使用多进程或者多线程任务,那么真实环境中这些任务不可能是真实并行的,毕竟一个CPU一次只能执行一条指令,在这种情况下多进程或者多线程就是并发的,而不是并行的(操作系统会不停地切换多任务)。这天你热的是在不行了,就催着商家赶紧给你送货,于是你就在商店里面候着他们,直到商家把你和空调一起送回家,一次愉快的购物就结束了。从严格意义上来说,并行的多任务是真的同时执行,而对于并发来说,这个过程只是交替的,一会执行任务A,一会执行任务B,系统会不停地在两者之间切换。
2024-12-03 09:59:27
339
原创 spring事务源码解析-前篇
事务启动的过程中需要定义事务的一些配置信息,如:事务传播行为、隔离级别、超时时间、是否是只读事务、事务名称,spring中使用TransactionDefinition接口表示事务定义信息,下面看一下TransactionDefinition接口源码,主要有5个信息事务传播行为事务隔离级别事务超时时间是否是只读事务事务名称//传播行为:REQUIRED//传播行为:SUPPORTS//传播行为:MANDATORY//传播行为:REQUIRES_NEW。
2024-11-26 08:24:02
637
原创 Spring中的@Import-注解探讨----批量注册bean
现在我们来引出关于@Import的问题,带着问题去讨论,效果更好首先我们讨论一下为什么要用@Import我们都知道,spring批量注册组件两种方式。
2024-11-19 10:48:46
892
原创 spring-@Configuration原理解析
环境版本:java8,spring5.2.x,maven3.6@Configuration注册类的全过程,话不多说,上代码,我这里是从关键的方法人手了说明:doRegisterBean方法很复杂,我们的主题是@Configuration,所以省略一些不重要的代码。将获取到的 scope 赋值给 BeanDefinition(这步完成后刚刚创建的 AnnotatedGenericBeanDefinition 对象的 scope 属性为 scope 值)。
2024-11-19 10:47:01
1210
1
原创 SpringBoot整合Liquibase对数据库管理和迁移
Liquibase是一个用于用于跟踪、管理和应用数据库变化的开源工具,通过日志文件(changelog)的形式记录数据库的变更(changeset),然后执行日志文件中的修改,将数据库更新或回滚(rollback)到一致的状态。它的目标是提供一种数据库类型无关的解决方案,通过执行schema类型的文件来达到迁移。本文主要介绍SpringBoot与Liquibase的集成。
2024-11-07 15:32:29
1209
原创 Mybatis一级缓存,二级缓存探讨上篇
从输出中可以看出2次查询都访问了db,并且两次查询的结果是不一样的,两个集合也不相等,插入数据让缓存失效是可以理解的,插入操作可能会改变数据库中的数据,所以如果再从缓存中去获取,可能获取到的数据和db中的数据不一致的情况,mybatis为了避免这种情况,在执行插入操作的时候,会将SqlSession中的一级缓存清空。同一个SqlSession中查询同样的数据,mybatis默认会从一级缓存中获取,如果缓存中没有,才会访问db,那么我们如何去情况一级缓存呢,强制让查询去访问db呢?
2024-11-07 11:43:48
741
原创 Mybatis延迟加载、鉴别器、继承
4张表:t_user(用户表)t_goods(商品表)t_order(订单表)t_order_detail(订单明细表)表之间的关系:t_order和t_user是一对一的关系,一条订单关联一个用户记录t_order和t_order_detail是一对多关系,每个订单中可能包含多个子订单,每个子订单对应一个商品。
2024-11-07 11:41:25
1006
原创 Mybatis入门篇,带你感受一下mybatis独特的魅力!
准备数据库mysql中运行下面脚本:我们的需求:对t_user表,我们有以下这些需求:实现一个通用的插入操作:支持动态插入,可以根据传入的字段的值,动态生成所需要的各种insert语句批量插入功能实现一个通用的更新操作:支持动态更新操作,可以根据传入的字段,动态生成所需要的各种update语句实现一个通用的查询操作:支持各种组合条件查询、支撑排序、分页、支持返回列的控制等各种复杂的查询需求引入mybatis依赖:子项目为:创建mybatis相关文件user.xmlchat01/src/mai
2024-11-05 14:20:42
423
原创 Mybatis类型处理器,这个你得会玩!
id int AUTO_INCREMENT PRIMARY KEY COMMENT '用户id',name VARCHAR(32) NOT NULL DEFAULT '' COMMENT '用户名',age SMALLINT NOT NULL DEFAULT 1 COMMENT '年龄',sex SMALLINT DEFAULT 0 COMMENT '性别,0:未知,1:男,2:女') COMMENT '用户表';
2024-11-05 14:19:25
606
原创 JVM调优(jdk8)与垃圾回收器详解
负载屏障的目标是在指针加载时插入一个处理逻辑。在压缩阶段,如果指针指向将要被移动的对象的区域,指针指向的对象将被移动,然后纠正指针。如果你要创建一个大于这个大小的对象,比如一个超大的数组,或者是别的啥东西,此时就直接把这个大对象放到老年代里去,压根不会经过年轻代,有一个JVM参数,就是“-XX:PretenureSizeThreshold”,可以把它的值设置为字节数,比如“1048576”字节,就是1MB。在这个阶段,ZGC会遍历堆中的所有活动对象,并将它们移动到新的位置,以便将未使用的内存空间紧凑起来。
2024-11-05 14:16:25
1152
原创 JVM出现OOM错误排查
对应线程出现的OOM错误,其实分好几类:堆内存溢出、栈溢出、方法区溢出,下面我们要区分两个概念内存泄漏是指GC垃圾回收的速度跟不上内存消耗的速度,造成OOM的情况内存溢出是指程序员在申请内存时,没有足够的内存空间供其用,OutOfMemoryError。
2024-10-31 08:54:53
634
1
原创 Forest入门和使用
ForestForest是一个开源的Java HTTP客户端框架,它能够将 HTTP 的所有请求信息(包括URL、Header以及Body等信息)绑定到您自定义的Interface方法上,能够通过调用本地接口方法的方式发送HTTP请求,类似于的openFeign框架。创建一个interface,比如命名为MyClient,并创建一个接口方法名为,用@Get注解修饰之。
2024-10-31 08:53:09
1179
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人