- 博客(62)
- 收藏
- 关注
原创 Spring 三级缓存&手写demo ---- 简单明了豆包版
二级缓存是这样解决循环依赖的,先 new A() 出来,此时它是个半成品,放入二级缓存,发现 A 依赖B,然后去创建 B,初始化B的属性时发现 B 要获取 A 的实例,B发现一级缓存没有 ,就去二级缓存找,正好找到了 A 的实例化对象,设置,然后 B 就可以放入一级缓存,而A 此时正好也在一级缓存找到 B 的实例,然后把 A 也移入到 一级缓存。下面的代码 A和 B 可以通过 set 的方式解决,但构造器不行,因为Spring 中的 bean 都是单例的,所以 通过 C c=new C(new D());
2026-04-13 17:37:04
45
原创 几种背包算法的区别--------学习
0-1 背包的 dp[i][j] 是指在第 1到 i 个物品中在容量为 j 的条件下选取最大价值物品,每个物品只能选一次,在考虑装不装第 i 个物品时,它的上一步只能考虑 dp[i-1][xx]。完全背包和 0-1 背包的代码几乎完全相同,只是它可以选取无限个 i 物品,只在计算dp[i][j] 扩大一个选择范围,每次都可以在 0到 i 范围内选择,而不是 0到 i-1 内选择。在完全背包里,它每次都选择最后一个物品n多次直到剩余空间不能装下才考虑其他物品,这种遍历搜索方式就大体就能找到最优。
2026-03-30 16:05:04
121
原创 Kafka 原子更新,精确一次消费 Exactly-Once --------- 学习笔记
Kafka 的生产者写入是原子性的,一条消息要么持久化成功,要么失败。支持消息生产者写入幂等和事务消息。保证消息 “仅一次交付”,避免重复写入。支持消费者手动提交位移 offset 是原子提交,原子更新,确保消费状态不丢失、不重复。即操作要么完全成功、要么完全失败,无中间状态。核心结论是:Kafka 本身不直接提供 “更新” 语义,但可通过原子写入 + 消费语义 + 外部协调实现业务层面的原子更新。其中:幂等性仅保证单生产者单分区的 “仅一次写入”,事务可实现跨分区 / 跨主题的原子写入;
2026-03-05 16:42:18
245
原创 动态规划-------- dp数组套路学习
所以 dp[i][j] 就是 s[0:i] 和 t[0:j] 在做比较,如果它们的最末尾字符 s[i-1]==t[j-1] ,那么dp[i][j]=dp[i-1][j-1] +1;dp[i-1][j-1] 代表 s[0:i-1] 和 t[0:j-1] 在做比较。如果 s[i-1]!=t[j-1],那么就 j 前进一位,让 s[0:i] 和 t[j+1] 做比较,其实此时的比较结果和 s[0:i] 和 t[0:j-1] 的比较结果一样,即 dp[i][j]=dp[i][j-1]。
2026-01-30 17:08:35
97
原创 全排列,求所有子集--------回溯算法学习
每次回溯时都要对当前所有可能的选择依次进行遍历,全排列就是 从 0到 n-1 下标元素遍历所有没有被选择的元素一次,如果该元素已选择,那就跳过,如果没选就选择它,更新 visited[i]=true,然后进行下次回溯;当遍历某一个元素时,不选择,在下次回溯中它还是什么都不选,再在下次回溯中它还是什么都不选.......最终死循环,而且我们也不需要这个可能,在全排列中我们每次都必须选择一个,然后撤销选择,恢复原状,这就算是没选择这个元素 X 了,其他元素还可以在它们的回溯中继续选择 X。
2026-01-29 17:44:10
72
原创 最长回文子串---------动态规划学习
显然 dp[0][0],dp[1][1],dp[2][2] .... 等单个字符都是子串。如果 s[i]==s[j] 且 dp[i+1][j-1] == true,或者 s[i]==s[j] && j-i<=2,那么 dp[i][j] 也为true,即 s[i:j+1] 是回文子串,这就是状态转移方程。显然在求 dp[i][j] 前必须先知道 dp[i+1][j-1],dp[i+2][j-2].....等的值,可以看到循环中 i 下标是递增而 j 下标是递减的。]的值,那么就构造扫描的先后次序,让dp[?
2026-01-29 16:40:21
246
原创 算法 198. 打家劫舍系列 ---------动态规划学习
要么是 dp[i-2],要么是 dp[i-1],其实小偷还可以选择dp[i-3],dp[i-4]....一直到 dp[0],但是选择dp[i-3],dp[i-4]...这些数字很明显不可能比 dp[i-1]和 dp[i-2] 中的更大,因为 dp[i-1] 和 dp[i-2] 就是从 dp[i-3],dp[i-4],dp[i-5]......中得来的。所以在 nums[i] 位置处的 dp[i] 要想最大,只可能是 max(dp[i-2]+nums[i], dp[i-1])。
2026-01-27 17:05:32
183
原创 记录一个死锁异常--循环打印 AB go语言
1,触发第一次打印 A 的代码是 ch1 <- struct{}{},如果这行代码在主线程执行,那么在给阻塞在 ch1 的 go程唤醒的时候这个 go程可能还没有启动运行,所以 ch1 <- struct{}{} 最好要放在一个单独的 go程里运行。2,当打印完最后一个 B 的时候不要再往 ch1 发送 struct{}{} 了,除非有程序接收。如果没有接收的话第一个 go程里的 for 循环已经结束了,第一个 go程已经结束运行,第二个go程被阻塞挂起,主线程也被阻塞,,就会发生死锁报错。
2025-12-24 16:53:38
158
原创 Java NIO 手写 Reactor 模式
如果请求过多,一般会分成两个部分,一个部分即主线程负责处理客户端的连接请求,每个主线程持有一个 ServerSocketChannel,当它监听到有新连接时;另一个部分即工作线程池负责处理已连接客户端的读写请求,每一个工作线程持有一个 Selector 选择器,在客户端建立连接时把客户端 Channel 注册到这个选择器上,后续的读写请求都通过唤醒这个 工作Selector 来进行处理。一个简单的NIO demo 一般就是这样,只有一个主线程完成监听和处理工作,可以同时处理多个请求。
2025-12-16 16:08:14
285
原创 Java 无锁编程
下面就是一个无锁编程的例子,它通过 AtomicBoolean 的CAS 操作完成了锁的功能。无锁编程的关键是 “可见性 + 原子操作+自旋”,使用 synchronized 和 Lock 通过阻塞程序保证原子性,有上下文切换开销,无锁编程(volatile+CAS)通过自旋重试保证原子性,无阻塞开销,适合短时间,低线程竞争的场景,另外自旋重试会导致在高冲突场景下频繁重试,导致 CPU 使用率飙升,此时加锁更合适;仅支持单个变量 / 操作原子性,更适合单个变量的原子修改,复杂业务逻辑最好还是加锁或事务。
2025-11-22 21:16:47
390
原创 Zookeeper 笔记
主要作用:在 Hadoop ,Kafka 这些早期的大数据生态主要做集群选主的分布式协调中间件,在 Java 中做分布式锁,在 Dubbo 等 RPC 框架中做注册和配置中心,Watch 机制可以监控配置数据变化,也可以存储少量数据。缺点:性能一般,因为强一致性要求集群中只有一个 Leader 节点,只有 Leader 节点可以写入数据,写入数据时需要多数节点投票同意。Zookeeper 是一个分布式协调中间件,使得分布式系统中各个节点达成共识,完成数据一致性,数据同步,配置管理,服务发现等功能。
2025-11-13 15:57:47
322
原创 分段锁降低锁竞争 Java
涉及到同一张表的增删改操作全部都竞争相同的一把锁,即表名 hash值 取锁数组大小模 后得到的那把锁,如果锁很少,多张表可能要抢同一把锁,因为数据库执行不同表的 sql 互不影响,所以最好锁多一点。任务 0,3,6,9 都抢同一把锁 0,任务 1, 4,7 抢统一把锁 1,任务 2,5,8抢同一把锁 2,大大地减少了锁竞争,同一个任务组内只有一个 1 个任务能执行,消除了数据库表锁。更好的方式是同一组任务使用只有一个线程的线程池去执行,它无锁,但这样线程池的数量就多了。
2025-01-14 18:00:09
325
原创 Java 获取方法签名的具体类型参数
这样的方法签名字符串,那么我们就很容易知道 这个方法的参数列表是 (List,String) ,返回值是 String,这个字符串也可以使用 SignatureVisitor 去解析浏览,但此时已达到了我们的目的。第一种办法就是我们直接读取代码源文件,然后我们读取某行代码时根据某些特征确定了它是方法头,那么我们就读取方法参数列表字符串,一个一个地解析,把方法id和它的参数类型列表关联起来。
2025-01-03 17:18:47
546
原创 Java 解析离线 MySQL binlog 文件
这个需要我们在线查询源数据库的表元数据,它能查询某张表的所有属性名称,属性的数据类型,是否是主键,是否自增等信息。5,现在我们已经知道表名,数据库名,列名,前后发生变化的数据值以及这些数据值的类型,这样我们就可以根据这些信息构造 sql 了。在数据同步的时候,有时候无法在线实时同步,需要解析已归档的 MySQL binlog 文件做数据补偿,此时就需要解析已归档的 binlog 文件为我们需要的 sql 文本文件,再把这个 sql 文本文件到数据库里按时间顺序依次执行。
2024-11-30 11:06:39
990
2
原创 Nginx 网关解决 Geoserver 图层访问控制
要对 Geoserver 进行图层访问控制,有很多种办法,最简单的是通过 Geoserver 本身提供的图层访问权限设置,比如RBAC 基于用户角色权限进行控制,基于Geoserver 的 Jetty 容器的 IP 过滤器设置黑名单,比较复杂的是基于Geoserver插件 AuthKey 的访问控制,基于 GeoNode 程序的访问控制,后面两个不好操作。
2024-10-31 18:08:32
896
原创 Python Fiona 生成 Geopackage 文件
我们项目原本使用 Shapefile 格式存储 GIS 信息,Shapefile 优点是比较简单,网上资料多,但 Shapefile 格式比较古老,有时候就不太够用了,限制较多,比如 Shapefile 里一个要素的属性名称长度不能超过10 字符,属性内容不能超过 255 个字符,超过了就要被截断,这个就很麻烦,比如图层中不能直接获取到要素的 path 字段,因为 path 太长会被截断,导致查询这个信息的时候还有走后端接口;当 Shapefile 中的地理要素数量非常庞大时,数据的读取和查询性能会下降;
2024-10-29 18:26:29
628
原创 Debezium Kafka 全量同步,处理大量写入问题
Kafka 一个主题可以有多个分区,每个分区都可以被一个线程所消费,因为要写入消息到MySQL ,批量插入比单次插入效率高很多,如果还是单次插入到MySQL,那么引入这个Kafka就没什么用,还是那么慢,所以我们决定多开几个线程批量拉取Kafka里的数据,并批量插入到MySQL,因为当前我们程序每秒能单次插入1700多条数据到Kafka,所以我们的Kafka 一个主题开4个分区,每个分区都有一个线程批量拉取消息进行消费,到此消息消费速度刚好赶上了消息生成速度了。最终我们决定使用 Kafka。
2024-10-22 17:46:24
1514
1
原创 Debezium 同步 MySQL 实时数据并解决数据重复消费问题
之后我们使用 binlog2sql 这个 python 工具读取了已归档的 binlog 文件,发现里面没有重复的 sql ,这说明 MySQL binlog 还是没有问题的,问题在 Debezium,但 Debezium 作为一个成熟的 cdc 工具应该也不会有什么大的问题,可能是 Debezium 的配置问题,但检查了 Debezium 的所有配置后还是没发现有什么问题,配置改了后重新运行结果还是一样。后面我们使用 gtid 过滤相同属性就解决了数据重复问题。我们的 MySQL 的版本是 5.7。
2024-06-25 16:44:49
1466
原创 常用位算法
3,n&(~n+1) 获取 n 最后的 1的数字,假设 n 为 110010,n&(~n+1) 就是 000010。4,n&(n-1), 它会删除 n 中最后一个1。2, 判断奇偶,n&1,即判断最后一位是0还是1,如果结果为0,就是偶数,是1 就是奇数。获取 32 位二进制的 1 的个数,它会循环遍历 n 中为 1 的个数的次数。获取 32 位二进制的 1 的个数,它会循环遍历 n 中为 1 的个数的次数。1,位翻转 n^1 ,n 是0 或 1,和 1 异或后位翻转了。
2024-06-06 11:16:36
366
原创 双指针: 盛水最多的容器
当左指针在 0 处,右指针在 height.length -1 处,此时容器的底最长,但要想盛最多的水,就要让容器的底乘高数值最大,容器的高取左右两指针所指向的元素最小值。给定一个数组height,长度为n,每个数代表坐标轴中的一个点的高度,height[i]是在第i点的高度,请问,从中选2个高度与x轴组成的容器最多能容纳多少水。当左指针指向的高比右指针所指向的高小,左指针往右前进 1;当左指针指向的高比右指针所指向的高大,右指针往左前进 1;2.当n小于2时,视为不能形成容器,请返回0。
2024-06-05 17:41:30
426
原创 回溯算法解法 针对数组或字符串
例如:给出的字符串为"25525522135",返回["255.255.22.135", "255.255.221.35"]. (顺序没有关系)2,确定 dfs() 的结束状态,本地中是找到一个合法的ip字符串,如果发现中间状态 tmp 不是一个合法的ip,就终止本次回溯。dfs(s,0,"") s 是不变的,我们要搜索它得到整个解,0是索引初始位置,"" 是初始中间状态。注意:ip地址是由四段数字组成的数字序列,格式如 "x.x.x.x",其中 x 的范围应当是 [0,255]。
2024-06-05 16:23:44
395
原创 GIS Java 生成四至图
对于地图上的一个多边形地块,其四至图就是能够覆盖这个多边形的最小矩形,也就是求出这个多边形的最东点,最西点,最南点,最北点,即四至点,其中最西点和最北点构成左上角,最南点和最东点构成右下点,只要知道了左上角和右下角,就知道这个最小覆盖矩形了。前端生成四至图是比较简单的,后端如何生成四至图呢?后端生成四至图得到的是一个图片,图片的底图是天地图,在这个底图之上就是多边形。
2024-05-31 16:44:36
2319
原创 ThreadLocal
Java 中的 ThreadLocal 是一个线程的局部变量,它消除了多线程的数据读写争用,它一般用于一个线程在多个不同方法里的数据传递,比如会话登录,一请求一线程,Spring 事务等。
2024-01-25 16:05:54
558
原创 Netty Pipeline
Netty 中的业务处理流程都是在 Pipeline 中被处理的,它底层是一个双向链表,链表元素是ChannelInBoundHandler 和 ChannelOutBoundHandler,二者都是 ChannelHandler 接口类,一个 Channel 拥有一个 Pipeline, 当 Channel 被创建时会创建一个空的Pipeline。
2024-01-25 10:13:24
529
原创 Netty Reactor 模式解析
上面短短的服务端代码做了很多工作,当它刚启动还没有客户端请求连接时,bossGroup 连接线程池里的一个线程 EventLoop 会初始化一个 NioServerSocketChannel ,并把这个Channel注册到这个EventLoop 持有的IO多路复用选择器Selector里,Selector 会监听Channel里的 SelectionKey.OP_ACCEPT 事件,一旦有客户端连接过来,它会通过下面代码获取到一个。在写Netty 服务端代码的时候,下面的代码时必不可少的,这是为什么呢?
2024-01-24 15:26:37
900
原创 Netty 中的读和写
ChannelInboundHandler 使用了责任链模式,每个 ChannelInboundHandler 就相当于一个拦截器,对它感兴趣的数据进行处理,比如编解码,解析http,websocket协议等,ChannelOutboundHandler 对数据进行写操作,它底层是一个Entry 链表。1,在简单的手写Netty demo项目中,Netty 读和写数据都是对 Channel 的读和写,也就是对NioSocketChannel 中的 SelectableChannel 的读和写。
2024-01-23 10:34:56
629
原创 python 全量同步和增量同步实践
简单的增量同步可以使用定时断点同步,即使用定时任务获取从库的上次备份的最后一条数据,从最大的id处开始定时同步数据,同时多传递一个 id 参数,我们的id是long类型,是有序递增的,如果id 不是有序递增的,如果 create_time 是有序递增的也可以。我们可以监听主库的binlog,然后把 insert,update,delete 语句解析出来,到从库重新执行一遍。如果我们要做整库数据迁移和同步,我们可以先同步库表结构等元数据,再去同步表数据。它要求数据库开启 binlog,且数据格式为 row。
2024-01-16 16:22:50
2034
1
原创 写一个水平分表插件
2,SQL 解析,使用 JSqlParser 或 druid 的 SQL 解析器去获取静态 SQL 的路由键和路由键实际参数。因为如果找不到路由键,那就扫全表,如果找不到路由键实际参数,就不知道要路由到哪些子表,也要扫全表。这些只能完成比较简单的单表增删改查,无法应对项目里复杂的 SQL 需求,还需要做其他的工作。1, 解析路由配置,知道哪些表需要路由,哪些表不需要路由,并知道路由参数;3,根据路由键和路由参数计算目标路由表,生成新的 SQL。
2023-09-07 16:06:19
253
原创 Spring Boot 制作 Windows 客户端
2,当客户端更新时就下载一个新的 exe 文件到本地,使用 sc config 修改 exe 文件的地址,然后使用 taskkill 杀死服务,因为该服务有崩溃重启功能,所以过了几秒钟后,服务重启了,服务变为新服务。1,之前我们使用 Spring Boot 去做 Windows 的客户端,使用 exe4j 这个工具把 jar 包打成 exe 文件,选择“服务”模式,最后使用 Windows 的 sc 命令注册该 exe 文件为 windows 服务,并设置为自动模式,失败重启。.bat 批处理脚本。
2023-08-17 19:12:15
560
原创 Netty 大概组件
但它的所有的 IO 操作都是异步的,全是各种 Future,Promise(Promise也是一种特殊的Future),因为 jdk 1.5 的 Future 没有事件监听功能,所以Netty 自己实现的 Future 具有事件监听回调,这是常规的异步操作,jdk 1.8 有了 CompleteFuture ,就不需要自己手动实现异步监听回调了,非常方便。2,Java 里的异步操作,底层基本上都是通过线程池去实现的,因为新开一个线程去执行任务,其实就是最基本的异步操作。
2023-08-17 18:53:23
115
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅