- 博客(41)
- 收藏
- 关注
原创 【Spring Boot】定时任务
在Spring Boot中,定时任务的实现通常使用@Scheduled注解。@Scheduled可以用于在指定的时间间隔或特定的时间点执行任务。Spring提供了多种方式来配置定时任务,如使用固定速率,固定延迟或Cron表达式等。如果是分布式系统或者想要时间可以灵活变化,可以选择一些定时任务框架xxl-job,elastic-job等在 Spring Boot 中,通过使用@Scheduled。
2024-08-17 21:24:20
4033
2
原创 【Spring Boot】拦截器的使用
在Spring Boot中,拦截器(interceptor)是一种用于拦截和处理请求的机制。通过拦截器,可以在请求到达控制器之前,响应发送到客户端之前进行一些预处理或后处理操作。
2024-08-17 14:51:54
932
原创 【Spring Boot】全局异常处理
在Spring Boot中捕获全局异常是一种有效的方式,可以将应用程序中的所有异常集中处理,提供统一的错误响应,并且可以避免重复编写异常处理逻辑。实现全局异常处理通常使用@ControllerAdvice注解来定义一个全局的异常处理类。在类中编写异常处理方法,并使用@ExceptionHandler注解指定要处理的异常类型。以下是具体的步骤和示例。
2024-08-16 21:12:56
1795
1
原创 【java】java延迟队列DelayQueue
DelayQueue是 Java 中一个实现延时任务的无界阻塞队列。它是 Java 并发包()的一部分,专门用于在延迟一定时间后才能提取元素的场景。
2024-08-14 14:24:16
1055
原创 【java】方法回调
方法回调(Method Callback)是指在编程中将一个方法作为参数传递给另一个方法,并在适当的时机调用这个方法的编程技术。方法回调是一种设计模式,允许某个方法在另一个方法执行过程中或执行之后被调用。它本质上是一种函数指针机制,常见于需要延迟执行或异步执行的场景。通常,回调函数由接口(或抽象类)定义,这个接口声明了回调方法。方法回调是一种强大的编程技术,通过解耦调用者和执行者,使代码更加灵活和模块化。它广泛应用于异步操作、事件驱动开发、多态设计等场景。掌握方法回调可以帮助开发者设计出更优雅和高效的程序。
2024-08-13 17:08:16
1054
原创 【Redis进阶】Redis集群
数据分片(Data Sharding)是一种将数据集分割成更小的部分(称为"片"或"分片")并分布到多个存储单元(如数据库或服务器)上的技术。每个分片只存储数据集的一部分,从而使得系统能够水平扩展,处理更大规模的数据量和更高的并发请求。Redis Cluster使用数据分片实现key的存储分布Redis Cluster将集群划分为16384个槽位,数据库中所有的key进行hash计算后,都会落到16384个槽位中的其中一个槽位。
2024-08-12 22:04:08
1501
原创 【Redis进阶】Redis哨兵Sentinel
Redis哨兵机制(Redis Sentinel)是Redis提供的一种高可用性解决方案,用于监控Redis主从复制的架构,,自动实现故障转移和系统通知,从而确保Redis服务的高可用性。
2024-08-12 10:18:15
806
原创 【Redis进阶】主从复制
但是如果数据是存储在单点服务器上,当服务器出现宕机情况下,由于数据恢复是需要时间,这个时间无法处理请求或者更严重的情况下,如果服务器硬盘出问题,那么会造成数据的无法恢复。在主服务器进行命令传播时,不仅会将写命令发送给从服务器,还会将写命令写入到 repl_backlog_buffer 缓冲区里,因此 这个缓冲区里会保存着最近传播的写命令。当前数据的偏移量,例如执行一条指令后,产生一条数据后,会增大偏移量,从节点请求复制主节点的时候,会带上这个信息,让主节点从这个偏移量之后的数据返回给我。
2024-08-11 17:24:14
1071
原创 【Redis进阶】缓存一致性问题
缓存一致性问题指的是缓存中的数据和数据库中的数据不一致的情况,这在分布式系统中尤其常见。:通过延迟第二次删除缓存,降低了在更新数据库和缓存期间发生的并发问题,从而提高了缓存和数据库的一致性。:通过监听 Binlog,可以实时捕获数据库的变化并更新缓存,确保缓存数据的新鲜度和一致性。:两次删除操作增加了缓存的开销,特别是在高频读写的场景下,可能对缓存性能产生一定影响。:通过重试机制,即使缓存删除失败,也能够在重试后成功删除,确保系统的稳定性。如图所示,更新请求进来,先更新数据,再删除缓存。
2024-08-11 14:23:07
1296
原创 【Redis进阶】缓存设计模式
在Cache Aside中,应用层需要和缓存和数据库两个数据源打交道,这增加了应用层的复杂度,而Read/Write Through Pattern就是来解决这个问题的,在这两种模式下,应用层只需要将缓存作为主要数据源,不需要感知数据库,更新和读取的任务都交给缓存来处理。缓存设计模式在分布式系统中起着至关重要的作用,它们帮助开发者在不同的业务场景下有效管理缓存,提高系统的性能和响应速度。根据具体的需求和场景,开发者可以选择适合的缓存设计模式,以确保系统的高效和稳定。
2024-08-11 09:47:40
1661
原创 【Redis进阶】缓存应用
缓存击穿是指缓存中不存在但数据库中存在的数据请求,由于缓存没有命中,导致请求直接落到数据库上,造成数据库压力骤增。缓存击穿常常发生在某些热点数据上,比如某个高访问频率的热点键突然失效时,大量请求直接穿透缓存访问数据库。缓存穿透是指请求的数据既不在缓存中,也不存在于数据库中,导致每次请求都直接达到数据库。恶意攻击:攻击者故意构造大量不存在的key进行请求,绕过缓存,直接打到数据库,造成数据库压力骤增。在缓存失效前主动更新缓存。热点数据缓存失效:高访问频率的热点数据在缓存中失效,导致大量请求直接访问数据库。
2024-08-08 16:59:29
907
原创 【Redis进阶】Redis单线程模型和多线程模型
文件事件处理器是单线程模式运行的,但是通过IO多路复用机制监听多个socket,并根据socket目前执行的任务来为套接字关联不同的事件处理器。可以实现高性能的网络通信模型。又可以跟内部其他单线程的模块进行对接,保证了Redis内部的线程模型的简单性。
2024-08-07 12:06:46
2017
原创 【Redis进阶】Redis的持久化RDB和AOF
在服务线上请求的同时,Redis还需要进行内存快照,内存快照要求必须进行文件IO操作,文件IO操作会严重降低服务请求的性能,还可能会阻塞处理线上的请求业务。Redis在收到客户端修改命令后,先进性响应的校验如果没问题,就立刻将该命令追加到.aof文件中,也就是先存到磁盘中,然后服务器再执行命令。假设 AOF 日志记录了自 Redis 实例创建以来所有的修改性指令序列,那么就可以通过对一个空的 Redis 实例顺序执行所有的指令,也就是「重放」,来恢复 Redis 当前实例的内存数据结构的状态。
2024-08-06 18:08:56
1189
原创 【MySQL进阶】Explain关键字详解
PRIMARY:复杂查询中最外层查询,比如使用 union 或 union all 时,id 为 1 的记录 select_type 通常是 primary,如上图所示。eq_ref:基于主键或唯一索引连接两个表,对于每个索引键值,只有一条匹配记录,被驱动表的类型为 eq_ref,这种类型只出现在 join。range:范围扫描,检索指定范围的行,一般出现在 where 语句出现 between、< 、>、in 等的查询。索引使用的字节数,可通过该列计算查询中使用的索引的长度,主要用于联合索引。
2024-08-05 09:50:01
782
原创 【MySQL进阶】MySQL主从复制
当从库线程连接的时候, 主库可以将二进制日志发送给从库,当主库读取事件(Event)的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。他再执行完一个事务之后,也不会立刻给客户端反馈,但是也不会等所有从库都完成事务,而是等其中一个从库完成接收到事件之后,再反馈给客户端。全同步复制的这个方式中,当主库执行完一个事务之后,他会等待所有的从库完成数据复制之后,才会给客户端反馈。从库 SQL 线程会读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步。
2024-08-04 19:45:32
813
原创 【MySQL进阶】事务隔离级别 MVCC
隔离级别脏读不可重复读幻读并发性应用场景读未提交可能可能可能最高几乎不用读已提交不可能可能可能较高读取一致性要求不高的场景可重复读不可能不可能可能中等MySQL默认,适用于大多数应用程序串行化不可能不可能不可能最低数据严格一致性要求高的场景,但较少使用。
2024-08-01 15:54:55
1072
原创 【MySQL进阶】索引
创建索引可以大幅提高查询性能,但需要根据具体应用场景和查询模式来合理创建索引。避免不必要的索引,选择性高的列和常用的查询条件、排序、连接、分组列是创建索引的主要考虑因素。
2024-08-01 11:20:29
901
原创 Mybatis二级缓存四种回收策略的原理分析
LRU 算法通过双向链表和哈希表的结合,实现了高效的缓存访问和更新。其在操作系统、数据库、浏览器等场景中广泛应用,是一种经典且有效的缓存淘汰策略。FIFO 算法通过队列实现了先进先出的缓存策略,简单且高效。在需要保证数据处理顺序的应用场景中,FIFO 算法非常适用。相比于 LRU 算法,FIFO 算法实现更加简单,但可能会出现“Belady's Anomaly”,即增加缓存大小反而增加缺页率的现象。
2024-07-30 13:10:20
820
原创 Mybatis缓存详解
缓存(Cache)是一种用于提高数据访问速度的技术,通过在存储系统中(内存)保留一部分常用或者最近使用的数据,减少访问底层数据源(如数据库,文件系统等)的频率,从而提供系统性能和响应速度。
2024-07-30 10:45:30
1184
原创 JVM基础面试题第一篇
可作为GC roots的对象包括虚拟机栈和本地方法栈中引用的对象,类静态属性引用的对象,常量引用的对象。常见的内存溢出包括堆内存溢出、栈溢出等。运行时常量池是方法区的一部分,Class文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项是常量池表,用于存放编译器生成的各种字面量与符号引用,这部分内容在类加载后存放到运行时常量池。引用计数:在对象中添加一个引用计数器,如果被引用,计数器加1,引用失效,计数器减1,如果计数器为0,则可以被当成垃圾回收,但是避免不了循环引用的问题,就是两个对象相互指向。
2024-04-18 21:54:41
1306
原创 JVM基础第二篇
可达性分析法是Java中主要采用的垃圾回收算法,它通过从一组称为"GC Roots"的根对象开始,递归遍历所有对象的引用关系图,标记所有能够被从GC Roots到达的对象为存活对象,而无法被到达的对象则被判定为可回收对象。这种方法可以有效处理循环引用的情况,是Java中主要的垃圾回收算法。标记-清除算法是最早期的垃圾回收算法之一,它分为标记和清楚两个阶段在标记阶段,从跟对象开始,递归遍历所有可达对象,并对它们进行标记。在清除阶段,遍历整个堆内存,将未标记的对象进行清除。
2024-04-15 19:35:23
976
原创 并发基础面试题第一篇
多线程编程中一般线程的个数大于CPU核心的个数,而一个CPU核心在任意时刻只能被一个线程使用,为了让这些线程都能得到有效执行,CPU采取的策略是为每个线程分配时间片并轮转的形式,当一个线程时间片用完的时候就会重新处于就绪状态让给其他线程使用,这个过程就属于一次上下文切换。死锁是指两个或者两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞现象,若无外力作用,它们都将无法推进下去。此时系统产生了死锁。多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。
2024-04-11 08:10:32
1272
原创 JVM基础第一篇
虚拟机栈(Virtual Machine Stack)是Java虚拟机(JVM)内存结构中的一部分,用于存储方法执行的信息,每个线程都有自己独立的虚拟机栈。每个方法在执行时都会在虚拟机栈上创建一个栈帧本地方法栈是java虚拟机内存结构中的一部分,与虚拟机栈类似,但是是专门用于执行本地方法(native method)的过程。每个线程都有自己独立的本地方法栈。用于存储java程序运行时创建的对象实例和数组。所有对象的实例都存储在堆中。Java 虚拟机有一个在所有 Java 虚拟机线程之间共享的方法区。
2024-04-10 07:31:45
2195
1
原创 并发线程基础第九篇
AQS(AbstractQueuedSynchronizer)是java中用于构建锁和同步器的抽象基类。它提供了一种基于FIFO等待队列的锁和同步器的实现框架,是并发编程中实现锁和同步器的重要基础。AQS提供了两种基本的同步原语:独占锁和共享锁。独占锁是指同一时刻只能有一个线程持有的锁,典型的代表是ReentrantLock。共享锁是指同一时刻可以被多个线程持有的锁,典型的代表是 CountDownLatch 和 Semaphore。
2024-04-05 20:08:13
1405
1
原创 并发线程基础第八篇
FunctionalInterface // 拒绝策略//1.任务队列//2.锁//生产者条件变量//4.消费者条件变量//5.容量//超时的阻塞添加try{//将时间统一转化为纳秒try {//awaitNanos()方法,返回的时间是一个剩余时间,把返回的时间重新赋值给它,防止虚假唤醒,从头再等return t;}finally {//阻塞获取//获取任务的时候需要保证线程安全,需要加一把锁try{try {return t;
2024-04-04 10:10:32
1075
原创 并发线程基础第六篇
Unsafe对象提供了非常底层的,操作内存,线程的方法,Unsafe对象不能直接调用,只能通过反射获得。AtomicInteger,LockSupport中的park,unpark方法底层都是采用Unsafe实现的。获取Unsafestatic {try {设置自定义AtomicDatastatic {try {// data 属性在 DataContainer 对象中的偏移量,用于 Unsafe 直接访问该属性。
2024-03-31 11:52:46
2822
原创 并发线程基础第五篇
happens-before 规定了对共享变量的写操作对其它线程的读操作可见,它是可见性与有序性的一套规则总结,抛 开以下 happens-before 规则,JMM 并不能保证一个线程对共享变量的写,对于其它线程对该共享变量的读可见。它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取到它的值,线程操作volatile变量都是直接操作主存。读屏障保证在该屏障之后,对共享变量的读取,加载的是主存中最新的数据,而不是缓存中的。
2024-03-29 07:11:27
829
原创 并发线程基础第四篇
可重入(Reentrancy)指的是一个线程或进程可以再次进入自己已经持有的锁,而不会出现死锁或其他异常情况。在Java中,重入性是指同一个线程在持有锁的情况下能够再次获取该锁,而不会被自己所持有的锁所阻塞。synchronized关键字和ReentrantLock类都是可重入锁的典型代表。当一个线程已经持有了某个对象的锁时,它可以再次获取这个锁而不会被阻塞,这种机制就是可重入性的体现。
2024-03-27 06:58:43
924
原创 并发线程基础第三篇
obj.wait()让进入到Object监视器的线程到waitSet等待obj.notify()从监视器的waitSet等待的线程挑一个唤醒obj.notifyAll()唤醒全部在Object上waitSet等待的线程obj.wait(Long)让该线程等待一定的时间,到时间自动唤醒示例@Slf4jlog.debug("我是线程一");//让线程在obj上一直等待下去log.debug("我是线程一,我被唤醒了");}).start();
2024-03-26 07:45:18
1195
原创 并发线程基础第二篇
把锁想象称一个房子,锁对象就是一把钥匙,钥匙不同,房子不同,如果操作同一静态变量,还是会造成线程不安全的问题。每个java对象都可以关联一个Monitor对象,如果使用synchronized给对象上锁之后,该对象头的Mark Word(可以去搜一下具体的java对象头底层是什么)中就被设置指向Monitor对象的指针。:如果在尝试加轻量级锁的过程中,cas操作无法成功,这时一种情况就是有其他线程已经为此对象加上了轻量级锁(表明有竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。
2024-03-24 15:53:05
1171
原创 并发线程基础第一篇
有一种特殊的线程叫做守护线程,只要其他非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。垃圾回收器线程就是一种守护线程,Tomcat中的Acceptor和Poller线程都是守护线程,所以Tomcat接收到shutdown命令后,不会等它们处理完当前请求。当Context Switch发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java中对应的概念就是。启动线程,前面我们已展示过,注意,一个线程只能一次,只能调用一次start()方法。以调用角度来讲,如果。
2024-03-23 08:00:00
2417
原创 Java基础面试题第四篇
try、catch和finally都不能单独使用,只能是try-catch、try-finally或者try-catch-finally。try语句块监控代码,出现异常就停止执行下面的代码,然后将异常移交给catch语句块来处理。finally语句块中的代码一定会被执行,常用于回收资源。throws:声明一个异常,告知方法调用者。throw :抛出一个异常,至于该异常被捕获还是继续抛出都与它无关。
2024-03-22 07:43:05
738
原创 Java基础面试题第三篇
保存字符串的数组被final修饰且为私有,并且String类没有提供/暴露修改这个字符串的方法String类被final修饰导致其不能被继承,进而避免了子类破坏String不可变。在Java9之后,String,StringBuilder,StringBuffer的实现改用byte数组存储字符串。
2024-03-21 08:08:48
739
原创 Java基础面试题第二篇
浅拷贝是指在复制对象时,只复制对象本身和其内部的基本数据类型的成员变量,而不会复制对象内部的引用类型成员变量。新对象和原对象中的引用类型成员变量将引用相同的对象。因此,对于浅拷贝的新对象和原对象来说,它们共享相同的引用类型成员变量,对其中一个对象的引用类型成员变量进行修改会影响另一个对象。深拷贝是指在复制对象时,不仅复制对象本身,还会递归复制对象内部所有的引用类型成员变量,直到复制完所有的引用对象。深拷贝生成的新对象和原对象完全独立,对新对象进行修改不会影响原对象,因为它们引用的是不同的对象。
2024-03-20 08:16:56
853
空空如也
Map集合,修改key
2024-04-02
TA创建的收藏夹 TA关注的收藏夹
TA关注的人