- 博客(46)
- 问答 (6)
- 收藏
- 关注
原创 讨论:延迟双删,要延迟多久呢?
Write-behind 跟Read-Through/Write-Through有相似的地方,都是由Cache Provider来负责缓存和数据库的读写。它们又有个很大的不同:Read/Write-Through是同步更新缓存和数据的,Write-Behind则是只更新缓存,不直接更新数据库,通过批量异步的方式来更新数据库。不管是延时双删还是Cache-Aside的先操作数据库再删除缓存,都可能会存在第二步的删除缓存失败,Cache-Aside缓存模式中,有些小伙伴还是会有疑问,在写请求过来的时候,
2025-01-26 17:33:48
1184
原创 从零搭建xxl-job(七):xxl-job执行器服务端的简单搭建-2
上面我为大家引入了执行器端的服务器组件,并且讲解到了最核心的EmbedServer类,该类就是执行器端服务器的启动类,并且是以Netty构建的服务器。请看下面的代码块。public class EmbedServer { private static final Logger logger = LoggerFactory.getLogger(EmbedServer.class); // 启动执行器的内嵌服务器,其中address参数就是执行器的IP地址,要封装到RegistryPa
2024-08-19 16:47:39
935
原创 从零搭建xxl-job(六):xxl-job执行器服务端的简单搭建
经过前面的学习,相信大家对XXL-JOB调度中心的核心知识点和定时任务的调度流程已经了如指掌了,接下来,我们的重心就要从调度中心过渡到定时任务程序了,接下来,我会为大家搭建起一个简易的可运行的定时任务的体系,然后在这个体系内进一步迭代演变,最终实现一个高性能的执行调度中心远程调度的定时任务的执行器模块。所以,在接下来的章节中,我将程序执行定时任务的程序为执行器。这样一来,我们的程序也就进一步接近XXL-JOB了,调度中心和执行器这两大模块就构成了XXL-JOB的全部。众所周知,在业务开发中,XXL-JO
2024-08-18 02:49:35
1351
原创 从零搭建xxl-job(五):查询待执行任务逻辑优化
先不说任务调度会不会拖累后续任务的远程调用,也不考虑scheduleThread线程和数据库打交道时的耗时异常状况,就只考虑最实际的问题,如果一次取出一分钟以内要执行的定时任务,但是当前时间可能才是第一分钟,现在取出了1-2分钟之内要执行的定时任务,如果有定时任务是在一分一秒就要执行,那直接调度就行了,可是一分50秒要执行的任务该怎么办呢?再比如,如果要调度的定时任务在第2秒,服务器在第1秒宕机了,但是服务器在第3秒重启成功了,这时候,错过的定时任务仍然在我的5秒调度周期内,这时候又该怎么办呢?
2024-08-16 18:29:28
950
原创 从零搭建xxl-job(四):xxljob进行一些性能优化
上面的代码就目前来说很简单,因为我的调度中心要去触发定时任务,让定时任务执行了,所有我就又搞了一个触发任务的类,这个类就负责把定时任务的信息向程序内部继续传递下去。其实很简单,就是定时任务方法的名 字。并且,调度任务去执行时,最终会一路调用YyJobTrigger类中的runExecutor方法,在该方法中,会通过http协议,把封装好的定时任务信息的对象发送给定时任务程序,并且——注意里这是是必须要强调清楚的——scheduleThread会等待定时任务程序执行完定时任务后把执行的结果回复过来。
2024-08-12 19:17:44
1057
4
原创 可重复读事务隔离级别查询问题
原因是可重复读事务隔离级别,查询的一直是事务开启时的快照。两个事务,一个事务插入了数据,另一个事务一直查询不到。
2024-07-08 15:12:17
175
1
原创 从零搭建xxl-job(二):项目搭建
编辑pom文件-继承 spring-boot-starter-parent。创建一个新的java项目,然后转成maven项目并依赖spring。7.引入 org.springframework.boot 依赖。6.引入 @SpringBootApplication 启动类。8.引入 spring-boot-starter-web。3.选择maven,使项目变为maven项目。1.创建一个新的java项目。此时启动项目会有tomcat。4.修改maven配置。
2024-05-07 15:40:08
326
原创 从零搭建xxl-job(一) :单体项目多模块项目搭建
在Maven中,groupId是一个项目的唯一标识符,它通常是公司或组织的反向域名,例如com.example.project。在一个 Maven 工程中,ArtifactId 用来命名生成的 jar 或 war 包,同时也会在 pom.xml 文件中使用,作为依赖项的标识符。在Maven的pom.xml文件中,finalName字段表示构建后的文件或目录的名称。在Maven的pom.xml文件中,repositoryId字段表示Maven仓库的ID。它是一个字符串,通常是一个唯一的标识符。
2024-05-06 19:36:43
972
原创 二叉树的遍历
首先给出二叉树的节点代码 public static class TreeNode { String nodeName ; TreeNode left = null; TreeNode right = null; public TreeNode(String nodeName) { this.nodeName = nodeName; } }先序遍历先看下先序遍历的流程图,接下来的代码也会
2022-05-17 11:50:44
247
原创 从0到1实现自己的阻塞队列
什么是阻塞队列?阻塞队列是这样的一种数据结构,它是一个队列(类似于一个List),可以存放0到N个元素。我们可以对这个队列执行插入或弹出元素操作,弹出元素操作就是获取队列中的第一个元素,并且将其从队列中移除;而插入操作就是将元素添加到队列的末尾。当队列中没有元素时,对这个队列的弹出操作将会被阻塞,直到有元素被插入时才会被唤醒;当队列已满时,对这个队列的插入操作就会被阻塞,直到有元素被弹出后才会被唤醒。在线程池中,往往就会用阻塞队列来保存那些暂时没有空闲线程可以直接执行的任务,等到线程空闲之后再从阻塞
2022-04-07 10:32:59
312
原创 并发编程的艺术读后感
时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停的切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换死锁避免死锁的几个常见方法:避免一个线程同时获取多个锁。避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资
2022-03-24 16:23:26
210
原创 算法--刷算法时需要理解的点
链表中环的入口结点思路:设置快慢指针,都从链表头出发,快指针每次走两步,慢指针一次走一步,假如有环,一定相遇于环中某点(结论1)。接着让两个指针分别从相遇点和链表头出发,两者都改为每次走一步,最终相遇于环入口(结论2)。以下是两个结论证明:两个结论:1、设置快慢指针,假如有环,他们最后一定相遇。2、两个指针分别从链表头和相遇点继续出发,每次走一步,最后一定相遇与环入口。证明结论1:设置快慢指针fast和low,fast每次走两步,low每次走一步。假如有环,两者一定会相遇(因为l..
2022-02-11 17:42:49
175
原创 IO多路复用底层原理全解
预备知识:在TCP协议中,建立连接的两个进程各自有一个socket来标识,那么两个socket组成的socket pair就唯一标识一个连接。1.Linux操作系统中断举个例子:比如你在家打游戏,这时候你很饿,点了个外卖,然后你继续打游戏,打到boss剩一丝血的时候,外卖小哥来敲门了,此时你不好意思让外卖小哥一直敲门啊,你就中断了你的游戏,暂停存档了,然后去拿外卖了,回来继续打游戏。上述例子中的外卖小哥来敲门就是系统收到了中断请求,游戏暂停存档去拿外卖就是系统被中断了。先来看一个简单的.
2021-11-13 20:13:05
2425
原创 分布式事务
分布式事务随着互联网的快速发展,软件系统由原来的单体应用转变为分布式应用。分布式系统会把一个应用拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如用户注册送积分事务,创建订单减库存事务,银行转账事务等都是分布式事务。我们知道本地事务依赖数据库本身提供的事务特性来实现,因为以下逻辑可以控制本地事务:begin transaction: //1.本地数据库操作:张三减少金额
2021-11-02 14:59:51
894
原创 ELK实现日志全局搜索
ELK:E代表Elasticsearch K代表Kibana L代表LogStash什么是LogStash?Logstash是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的"存储库"中。为什么使用LogStash?通常当系统发生故障时,工程师需要登录到各个服务器上,使用grep / sed/ awk 等Linux脚本工具去日志里查找故障原因。在没有日志系统的情况下,首先需要定位处理请求的服务器,如果这台服务器部署了多个实例,则需要去每个应..
2021-11-01 12:17:24
1154
原创 经典的超卖问题
库存超卖是如何产生的?库存为1,但是第一个线程在库存-1的事务未提交的时候被第二个线程读到了,此时第二个线程会认为当前库存仍然是1,然后也会-1.相当于减掉了两次1,最后发生超卖。解决方法:首先在redis里面通过定时任务调度设置秒杀商品的库存,比如1001号商品的库存是10.1.首先通过NGINX反向代理,实现网关2.通过redis的lua脚本 decr 原子性的缩减库存3.大于0的话就会生成一个订单号,将生成的订单号返回,通过订单号轮询获取订单状状态4.生成订..
2021-10-28 01:55:29
313
原创 FutureTask 源码解析
先看一下参数// 表示当前task状态 private volatile int state;// 当前任务尚未执行private static final int NEW = 0;// 当前任务正在结束,尚未完全结束,一种临界状态。private static final int COMPLETING = 1;// 当前任务正常结束private static final int NORMAL = 2;// 当前任务执行过程中发生了异常,内部封装.
2021-10-19 16:04:28
181
原创 SpringBoot自动装配原理
每次问到 Spring Boot, 面试官非常喜欢问这个问题:“讲述一下 SpringBoot 自动装配原理?”。我觉得我们可以从以下几个方面回答:什么是 SpringBoot 自动装配? SpringBoot 是如何实现自动装配的?如何实现按需加载? 如何实现一个 Starter?篇幅问题,这篇文章并没有深入,小伙伴们也可以直接使用 debug 的方式去看看 SpringBoot 自动装配部分的源代码。前言使用过 Spring 的小伙伴,一定有被 XML 配置统治的恐惧。即使 Spr
2021-10-16 17:48:57
152
原创 详解布隆过滤器
海量数据处理以及缓存穿透这两个场景让我认识了 布隆过滤器 ,我查阅了一些资料来了解它,但是很多现成资料并不满足我的需求,所以就决定自己总结一篇关于布隆过滤器的文章。希望通过这篇文章让更多人了解布隆过滤器,并且会实际去使用它!下面我们将分为几个方面来介绍布隆过滤器:什么是布隆过滤器? 布隆过滤器的原理介绍。 布隆过滤器使用场景。 通过 Java 编程手动实现布隆过滤器。 利用 Google 开源的 Guava 中自带的布隆过滤器。 Redis 中的布隆过滤器。1.什么是布隆过滤器?首先
2021-10-14 14:36:39
289
原创 缓存与数据库双写时的数据一致性
先列出所有的解决方案,并且讨论他们的优劣性。1.先更新数据库,后更新缓存2.先更新数据库,后删除缓存3.先更新缓存,后更新数据库4.先删除缓存,后更新数据库1.先更新数据库,后更新缓存这种场景一般是没有人使用的,主要原因是在更新缓存那一步,为什么呢?因为有的业务需求缓存中存在的值并不是直接从数据库中查出来的,有的是需要经过一系列计算来的缓存值,那么这时候后你要更新缓存的话其实代价是很高的。如果此时有大量的对数据库进行写数据的请求,但是读请求并不多,那么此时如果每次写请求都更新一下缓存
2021-10-14 11:22:18
90
原创 浅谈Redis底层原理
Redis的单线程和多线程5.x之前 有两个命令过来 读取io流--->计算值--->写入io流--->读取io流--->计算值--->写入io流这些都是一个线程完成的6.x以后 计算过程还是由一个线程来执行 io的读取和写入有子线程完成,相当于有很多大堂经理负责招待客人 送走客人,但是技师从始至终就一个人。子线程最多8个 4个就差不多了。BIO如何处理多用户访问?public class JamesRedis { static List&...
2021-10-14 04:51:25
217
原创 Redis介绍
简单介绍一下 Redis 呗!简单来说Redis 就是一个使用 C 语言开发的数据库,不过与传统数据库不同的是Redis 的数据是存在内存中的,也就是它是内存数据库,所以读写速度非常快,因此 Redis 被广泛应用于缓存方向。另外,Redis 除了做缓存之外,也经常用来做分布式锁,甚至是消息队列。Redis 提供了多种数据类型来支持不同的业务场景。Redis 还支持事务 、持久化、Lua 脚本、多种集群方案。分布式缓存常见的技术选型方案有哪些?分布式缓存的话,使用的比较多的主要是...
2021-10-12 19:03:35
232
原创 MySql三大日志
MySQL日志 主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中,比较重要的还要属二进制日志binlog(归档日志)和事务日志redo log(重做日志)和undo log(回滚日志)。redoLogredo log(重做日志)是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。比如MySQL实例挂了或宕机了,重启时,InnoDB存储引擎会使用redo log恢复数据,保证数据的持久性与完整性。MySQL中数据是以页为单位,你查询一条记录...
2021-10-12 17:51:10
1521
1
原创 ConcurrentHashMap解析
创建new ConcurrentHashMap();官方建议加上初始化大小(前提你确定大小的情况下),new ConcurrentHashMap(32);比如因为扩容是个很耗费资源的事情。// 传入的初始化数组大小如果是32的话 最终结果是tableSizeFor(32+32/2+1) = 64public ConcurrentHashMap(int initialCapacity) { if (initialCapacity < 0) th..
2021-10-10 04:31:37
430
原创 HashMap底层原理解析
数组数组因为有下标,所以查询很快。但是由于创建的时候内存大小就已经被设定好,所以扩容很麻烦,要将原来的数组复制到一个更大的数组中。链表链表中的每一项都占有各自的内存,他们不是存在于一块内存中,每一项都是靠互相引用链接到一起的。优势:增删很方便,查询麻烦,只能从head元素遍历。散列表整合了上述二者HashHash也称散列、哈希,对应的英文都是Hash。基本原理就是把任意长度的输入,通过Hash算法变成固定长度的输出。这个映射的规则就是对应的Hash算法,而原始数据映射后的二进
2021-10-09 05:26:01
177
原创 AQS的源码解析
先看自己实现的一个AQS的代码示例package mashibing;import java.util.concurrent.locks.AbstractQueuedSynchronizer;public class MyAQSDemo { private MyLock myLock; public MyLock getMyLock() { return new MyLock(); } class MyLock extends Abs..
2021-10-06 19:29:35
295
原创 JVM 垃圾回收
JVM的垃圾回收主要发生在堆内存中,堆内存分为新生代,老年代,新生代分为伊甸园区(Eden),幸存者区1(S0),幸存者区2(S1)大部分情况下(当对象很大的时候,直接进入老年代),对象首先都会在Eden分配,在一次新生代垃圾回收之后,如果对象还存在的话,就会进入S0或者S1,并且对象的年龄会加1,经历这次GC后,Eden和From区会被清空,这个时候,from和to会调换位置,minor Gc一直重复这个过程,最后超过15岁的时候,对象就会进入老年代。为什么大对象要直接进入老年代呢?为
2021-09-28 16:54:22
161
原创 JDK 监控和故障处理工具总结
这些命令在 JDK 安装目录下的 bin 目录下:jps(JVM Process Status): 类似 UNIX 的ps命令。用于查看所有 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息; jstat(JVM Statistics Monitoring Tool): 用于收集 HotSpot 虚拟机各方面的运行数据; jinfo(Configuration Info for Java) : Configuration Info for Java,显示虚拟机配置信息; jm...
2021-09-22 19:54:44
145
原创 创建线程的方式
1: 继承Thread public static void main(String[] args) throws ExecutionException, InterruptedException{ Thread01 thread01 = new Thread01(); thread01.start(); } public static class Thread01 extends Thread { @Override
2021-09-22 02:24:09
156
原创 JVM知识点总结
1.我们自己编写的java代码,是如何在各个平台运行的?java代码通过javac编译成class文件,这种中间码称为字节码,然后通过jvm加载字节码。运行时,解释器将字节码解释为一行行机器码来执行。在程序运行期间,即时编译器会针对热点代码,将该部分代码编译成机器码以获得更高的执行效率。在整个运行过程中,解释器和即时编译器共同作用,使java程序几乎能够达到和编译型语言一样的执行速度。2.什么是类加载器 类加载器就是将javac编译成的class文件,通过加载,生成...
2021-09-10 19:03:53
170
原创 java并发系列八---ThreadPoolExecutor
线程池的意义在讲解线程池之前,有些读者可能存在这样的疑惑:为什么需要线程池,线程池有什么优越性?关于这个问题,主要从两个角度来进行解答:•减少开销在大部分JVM上,用户线程与操作系统内核线程是1:1的关系,也就是说每次创建回收线程都要进行内核调用,开销较大。那么有了线程池,就可以重复使用线程资源,大幅降低创建和回收的频率。此外,也能一定程度上避免有人在写BUG时,大量创建线程导致资源耗尽。•便于管理线程池可以帮你维护线程ID,线程状态等信息,也可以帮你统计任务执行状态等信息。理解了线程池
2021-08-11 18:27:09
700
原创 Java并发系列七--ConcurrentHashMap
回顾HashMap既然说到HashMap了,那么我们就先来简单总结一下HashMap的重点。1.基本结构HashMap存储的是存在映射关系的键值对,存储在被称为哈希表(数组+链表/红黑树)的数据结构中。通过计算key的hashCode值来确定键值对在数组中的位置,假如产生碰撞,则使用链表或红黑树。需要注意的是,key最好使用不可变类型的对象,否则当对象本身产生变化,重新计算key的hashcode时会与之前的不一样,导致查找错误。由这一点可知,在存储键值对时,我们希望的情况是尽量避免碰撞。那
2021-08-06 18:58:46
452
原创 Java并发系列六:JUC.CountDownLatchCountDownLatch
CountDownLatch作为开发中最常用的组件,也作为面试中被问到的最高频的锁之一,我们有必要来聊聊它的作用以及内部构造。首先尝试用一句话对CountDownLatch进行概括:CountDownLatch基于AQS,它实现了闩锁,在开发中可以将其用作任务计数器。简单直译过来就是:CountDownLatch 这种同步工具允许一条或多条线程等待其他线程中的一组操作完成后,再继续执行。例子好像还是有点拗口,举个简单的例子来辅助理解一下。比如我需要收集七颗龙珠才能召唤神龙,这七颗龙珠没有.
2021-08-05 16:36:05
631
原创 Java并发五---JUC.ReentrantLock
Java并发系列五:JUC.ReentrantLockReentrantLock作为开发中最常用的组件,也作为面试中被问到的最高频的锁之一,我们有必要来聊聊它的作用以及内部构造。首先尝试用一句话对ReentrantLock基于AQS,它实现了公平锁和非公平锁,在开发中可以用它对共享资源进行同步。此外,和syhchronized一样,ReentrantLock支持可重入,但ReentrantLock在调度上更灵活,支持更丰富的功能。这段话中,包含了一些关键词,我将其标注出来,并且形成一张思维导图,这张
2021-08-03 19:24:42
223
原创 JAVA并发四--重中之重AQS
Java并发系列四:重中之重AQS上一期,我们介绍了乐观锁,而乐观锁的本质即是CAS,操作系统提供了支持CAS修改内存值的原子指令,所以乐观锁得以实现。从软件的工程角度去看,虽然底层已经通过CAS实现了乐观锁,Java的底层已经在Unsafe这个类中封装了compareAndSwap方法,支持了对CAS原语的调用,为了使上层更加易用,需要经过进一步的抽象和封装。抽象这个词虽然简单,但私以为要作出高内聚低耦合的抽象绝对是难点。在Java中最著名的并发包就是JUC,其中的组件和日常Java开发息息相关。在
2021-07-30 18:11:16
161
原创 Java并发系列三-乐观锁
乐观与悲观:假设现在有多个线程想要操作同一个资源对象,很多人的第一反应就是使用互斥锁。但互斥锁的同步方式是悲观的,什么是悲观呢?简单来说,就是操作系统将会悲观的认为,如果不严格同步线程调用,那么一定会产生异常,所以互斥锁将会锁定资源,只供一个线程调用,而阻塞其他线程,让其他线程等待,因此,这种同步机制也叫做悲观锁。但悲观锁不是在所用情况下都适用,比如在一些情况下,同步代码块执行的耗时远远小于线程切换的耗时,这样就很不划算。程序员们可能更加希望一些场景下,能够在用户态中对线程的切换进行管理,这样效率更高
2021-07-26 18:30:36
329
原创 由浅入深讲并发----2.悲观锁机制
什么是锁?在并发环境下,会出现多个线程对同一个资源进行争抢的情况,假设A线程对资源进行修改,此时B线程又对资源进行了修改,这种可能会导致数据不一致的问题。为了解决这个问题,很多变成语言引入了锁机制,通过一种抽象的“锁”来对资源进行锁定,当一个线程持有”锁“的时候,其他线程必须等待”锁“,我认为这本质上就是在临界资源上对线程进行一种串行化。Java语言中的锁机制是怎么设计的?在谈锁之前,我们需要简单了解一些Java虚拟机的内存结构。如图2.1JVM运行时内存结构主要包含了五个部分:程序计数器(PC寄
2021-07-23 19:39:13
187
原创 由浅入深讲并发----1.JVM线程模型
有一道面试题非常普遍:“说说线程和进程的区别”。网上流传的答案之一是“线程属于进程”,这个说法是不准确的。Linux线程又被称为“轻量级进程”,这就使很多同学摸不着头脑,那到底是线程还是进程?我们可以这么去理解,“线程”是抽象概念(KLT,内核线程),因为Linux内部没有专门为线程定义的数据结构和调度算法,所以Linux去实现“线程”的方式是“轻量级进程”(LWP,轻量级进程),本质还是进程。只不过加了一个“轻量级”的修饰词 如图1.2“轻量级进程”与“进程”的区别在哪?一个Linux进程拥.
2021-07-23 19:37:16
260
空空如也
TigerVnc 的编译问题 #include <sys/time.h>
2018-08-07
TCP通讯协议的代码问题
2018-08-01
C++ 读取本地bmp文件,文件类型是hbitmap类型的
2018-07-24
bitmap的打印机打印问题
2018-07-23
wxwidgets中的bitmap句柄问题
2018-07-23
C++的连接打印机显示图片的问题
2018-07-20
TA创建的收藏夹 TA关注的收藏夹
TA关注的人