- 博客(159)
- 收藏
- 关注
原创 自定义全局过滤器统计接口调用耗时
微服务架构已经是现代应用程序开发的主流方式,同时于我们而言,也是面试中必须掌握的重中之重。微服务架构是将之前的单体应用拆分成多个小型微服务,每个服务都可以独立部署、扩展和维护。然而,微服务架构也带来了一些挑战,其中之一就是服务间通信的管理。这时候,微服务网关就成为了必不可少的组件。微服务网关是一个位于微服务架构前端的组件,它充当了所有微服务的入口。微服务网关负责路由请求、负载均衡、安全认证、流量控制、监控和日志记录等任务。
2024-10-23 17:23:25
1195
原创 在项目中如何实现 Redis 分布式锁?
锁我想对大家都不陌生,在我们刚学习 Java 的时候,肯定知道synchronized和Lock锁;这两者都是本地锁。何为本地锁呢?本地锁就是该锁只针对当前节点有效,也就是当 node A 获取锁时,那么 node B 同样还可以获取锁,这种情况就是本地锁。如果服务只部署了一个节点的话,用这种本地锁是没有问题的。现现在很多系统为了抗高并发、高可用和高性能,会部署多节点(集群部署),那么此时如果还用本地锁的话就会出现问题,因此分布式锁就诞生了。
2024-10-23 17:10:12
1046
原创 数据管理_DM的实现
/TM事务管理器//PC页面缓存//数据库日志//页面索引//第一页DataItem和是数据库系统中数据管理的关键组件。DataItem提供了数据的存储和访问接口,支持数据修改和事务管理。而负责管理底层数据的访问、缓存、事务处理和日志记录,通过这些功能的实现,为上层模块提供了安全、高效的数据操作接口。两者的协作使得数据库系统能够以高效、可靠的方式管理和操作底层数据,确保数据的安全性和一致性。
2024-10-01 22:43:58
813
原创 自定义注解加 AOP 实现服务接口鉴权以及内部认证
1.定义注解:使用@interface关键字定义注解。2.注解元素:在注解中定义元素,就像在接口中定义方法。3.元注解:使用元注解(如@Retention、@Target等)来描述注解的行为。1. 定义注解可以使用@interface关键字来定义一个注解。在上面的例子中, MyAnnotation 注解有两个元素: value 和 number。其中, number 有一个默认值 0。2. 元注解元注解是注解的注解,用来描述注解本身的行为。
2024-10-01 22:43:11
1746
原创 4.4 版本管理器——VM实现
同时,可以看到其中有一个,说明也是实现了抽象缓存的,用到了模板方法设计模式,这个在介绍日志模块和数据管理器时也见到过。VM 的实现类还被设计为**Entry**** **的缓存,需要继承。
2024-09-07 17:49:23
745
1
原创 实战MYDB的mvcc与mysql的mvcc详解
最近做的一个简易版的MySQL-MYDB。里面也实现了mvcc。趁这个机会结合项目深入理解一下mvcc的机制。先来看MySQL的mvcc讲了啥?
2024-09-04 08:54:07
1068
原创 MySQL事务
原子性子性意味着事务中的所有操作要么全部完成,要么全部不完成,它是不可分割的单位。如果事务中的任何一个操作失败了,整个事务都会回滚到事务开始之前的状态,如同这些操作从未被执行过一样。一致性确保事务从一个一致的状态转换到另一个一致的状态。比如在银行转账事务中,无论发生什么,转账前后两个账户的总金额应保持不变。假如 A 账户(100 块)给 B 账户(10 块)转了 10 块钱,不管成功与否,A 和 B 的总金额都是 110 块。隔离性意味着并发执行的事务是彼此隔离的一个事务的执行不会被其他事务干扰。
2024-09-04 08:32:59
770
原创 95-不同的二叉搜索树2
当给定的范围内没有数字时(即 start>end)这意味着此处的子树为nul,所以我们应该返回一个列表,其中只包含一个null元素。对于范围内的每个数字 i,我们都尝试将其作为当前树的根节点。我们选择一个数作为根节点,然后分配左右子树,最后按照左右子树的大小继续递归建树即可得到答案。遍历每个数字 i从1到 3,将其视为根节点,并递归地为其左右子树生成所有可能的结构。当输入n=3时,我们需要构造所有可能的二又搜索树,其中树的节点值从1到3。这题的核心思想是采用递归的方法来生成所有可能的二又搜索树。
2024-09-03 10:02:35
589
原创 4.3 版本管理器——版本条约与死锁检测
/ 事务1请求资源1// 事务2请求资源2// 事务3请求资源3// 事务1请求资源2// 事务2请求资源3// 事务3请求资源1在这些数据添加完毕之后,事务1在等待事务2,事务2在等待事务3,事务3又在等待事务1,此时就触发了死锁!
2024-09-03 09:30:05
1183
1
原创 4.2 版本管理器——Entry与事务隔离级别
VM是基于两段锁协议实现调度序列的可串行化,并实现了MVCC以消除读写阻塞。同时也实现了两种隔离级别,所以我们还需要明确版本的概念;DM 层向上层提供了数据项(Data Item)的概念,VM 通过管理所有的数据项,向上层提供了记录(Entry)的概念。上层模块通过 VM 操作数据的最小单位,就是记录。VM 则在其内部,为每个记录,维护了多个版本(Version)。每当上层模块对某个记录进行修改时,VM 就会为这个记录创建一个新的版本对于一条记录来说,MYDB 使用Entry类维护了其结构。
2024-08-31 11:43:54
872
原创 4.1 版本管理器——2PL与MVCC
MVCC(,多版本并发控制)是一种数据库并发控制机制,用于解决数据库中多个事务并发执行时的读写冲突问题。MVCC通过维护数据的多个版本,允许并发的读操作和写操作更有效地进行,从而提高数据库的并发性能和系统吞吐量。
2024-08-31 10:45:32
1226
原创 什么是大小顶堆。
按照堆的特点可以把堆分为大顶堆和小顶堆。大顶堆:每个结点的值都大于或等于其左右孩子结点的值;小顶堆:每个结点的值都小于或等于其左右孩子结点的值。(堆的这种特性非常的有用,堆常常被当做优先队列使用,因为可以快速的访问到“最重要”的元素)大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
2024-08-09 23:18:11
481
原创 043字符串相乘
讲真心话,我对这种题目不是很感冒,觉得已有乘法运算的话,直接调用就好了呀。😄但是有时候,算法考察的就是我们的思维能力,或者叫造轮子能力,一道乘法运算的题目,最终考察的还是我们对数组、for 循环和进位的理解。以及一些细节处理,比如说去掉前导零。99*99的结果是9801,不用考虑 0 的问题;但11*11的结果是121,按照我们的题解方法数组的千位就是 0,所以我们要去掉。. - 力扣(LeetCode)
2024-08-09 23:01:05
962
原创 MYDB 之九 | TableManager (TBM) 字段解析与表管理
而记录本身的结构, 将由TBM来维护, TBM维护记录的方式非常简单: 直接将记录的值, 转换成二进制的字节数组, 然后将该字节数组, 当做数据, 交给VM进行存储和管理. 之后, 当需要某条数据时, 则通过其地址, 从VM将其读出, 然后反解析出其值.NYADB会对上述的文法进行解析, 解析的方法也很简单: 首先将语句给token化, 然后之后就是if-else的方法进行判断和进行语句组装了. token化的方法也很简单, 分析出文法的词素, 然后写一个小自动机, 不断的切分就行了.
2024-07-21 21:29:51
1062
原创 MYDB 之十 | 客户端与服务端
若 flag 为 0,表示发送的是数据,那么 data 即为这份数据本身;如果 flag 为 1,表示发送的是错误,data 是 Exception.getMessage() 的错误提示信息。客户端连接服务器的过程,实际上只是读入用户的输入,并调用 Client.execute()。是一个服务器类,主要作用是监听指定的端口号,接受客户端的连接请求,并为每个连接请求创建一个新的线程来处理;数据,这样可以避免特殊字符造成的问题,并在信息末尾加上换行符。这个类是服务器的启动入口,这个类解析了命令行参数。
2024-07-21 16:12:48
547
原创 技术派全局异常处理
全局的异常处理是Java后端不可或缺的一部分,可以提高代码的健壮性和可维护性。在我们的开发中,总是难免会碰到一些未经处理的异常,假如没有做全局异常处理,那么我们返回给用户的信息应该是不友好的,很抽象的,用户会认为我们的程序是不安全的。相反,如果有了全局异常处理,那么我们就可以给用户提供更友好的反馈。
2024-07-01 22:21:01
1249
原创 xxl-job实现定时任务
下面先放一张我从官网找的的最新的架构图,是v2.1.0版本的,不是代码最新的架构图但是几乎大差不差,右下角红框标出来的自研 RPC(xxl-rpc),在 V2.2.0 里面已经替换成了restful风格的 http 请求方式。4、xxl-job-executor-samples:执行器,sample 示例项目,其中的 spring boot 工程,可以直接启动。3、xxl-job-admin:调度中心,项目源码,spring boot 项目,可以直接启动。2、xxl-job-core:公共 Jar 依赖。
2024-06-26 22:37:44
1186
原创 021.合并两个有序链表,递归和遍历
这道题目是链表的基础题,递归和迭代都可以解决,递归的思路更加简洁,但是对于新手来说,理解起来可能会有些困难,迭代的思路更加直接,但是代码量会多一些。关键还是理解链表的数据结构,这个视频讲的不错,推荐一手。链表 数据结构与算法,完整代码动画版,附在线数据结构交互式工具_哔哩哔哩_bilibili还有这个网站,对链表也进行了详细的讲解,推荐一手。4.2 链表 - Hello 算法。
2024-06-26 22:31:36
696
原创 024.两两交换链表中的节点,用递归和 while 循环
其实有关链表的相关题目,最重要的切入角度,就是理清楚节点之间的关系,然后在纸上画一画,不要一个劲的只靠脑子不靠笔,往往思考了很久的问题,动动笔,就会豁然开朗,再用代码准确的描述出思路,这样子链表的问题便迎刃而解。那这道题考察的还是链表的数据结构,以及递归和 while 循环的一些临时变量和边界条件。. - 力扣(LeetCode)
2024-06-24 20:54:25
731
原创 UDP就一定比TCP快吗?
有时候处理的快些,那就可以收多点数据,处理的慢点那就希望对方能少发点数据。如果想要通过这个 socket 发消息,只需要操作这个 fd 就行了,比如执行 send(fd, msg, ...),内核就会通过这个 fd 句柄找到 socket 然后进行发数据的操作。因为数据发送方和接收方处理数据能力可能不同,因此如果可以根据双方的能力去调整发送的数据量就好了,于是就有了。,此时对方执行接收消息的操作,也就是 recv(fd, msg, ...),就能拿到你发的消息。UDP 表示,"哦,是吗?
2024-06-17 23:59:47
681
原创 第 34 题:在排序数组中查找元素的第一个和最后一个位置
只要遇到要求时间复杂度为 O(log n),那都是要使用二分查找法的,大家一定要学好二分查找。其基本思想就是通过将查找范围每次缩小一半,从而快速定位到目标值。第一步,初始化左右边界 left 和 right。第二步,计算中间位置 mid。如果相等,返回 mid。如果小于目标值,更新 left 为 mid + 1。如果大于目标值,更新 right 为 mid - 1。第四步,重复上述步骤,直到 left 大于 right。return mid;} else {
2024-06-17 22:48:05
948
原创 035.搜索插入位置
这道题仍然考察的是二分查找法,由此可见二分查找法的重要性。去 B站搜了一下,这个 up 讲的不错,推荐大家看一下。数据结构合集 - 折半查找(二分查找). - 力扣(LeetCode)
2024-06-16 11:41:16
1024
原创 第五章.日期类
1.概述:日历类,是一个抽象类2.获取:static Calendar getInstance()3.月份问题:国外: 0 1 2 3 4 5 6 7 8 9 10 11国内: 1 2 3 4 5 6 7 8 9 10 11 121.概述:DateFormat是一个抽象类使用其子类:SimpleDateFormat2.作用:可以按照指定的格式将日期格式化3.创建:SimpleDateFormat(String pattern)pattern:指定的格式yyyy-MM-dd HH:mm:ss ->
2024-06-16 10:22:05
684
原创 第二章.数字相关类
1、概述:Math是一个数学工具类2.作用:主要用于数学运算a.构造私有化,不能new对象b.方法都是静态的4.使用: 类名直接调用1.概述:将来我们操作的整数,有可能非常大,大到比long型还要大,这种整数应该称之为"对象",我们需要用 BigInteger来接收超大整数2.作用: 处理超大整数注意:1、我们不能直接用double和float类型的数据直接参与运算,因为有可能会出现精度损失问题2.解决:我们可以用BigDecimal来解决。
2024-06-12 22:32:13
418
原创 第一章.StringBuilder类
1.概述:一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证线程同步2.作用:主要作用是拼接字符串3.明明String可以做字符串拼接,那为啥还要学StringBuilder?a.String做拼接的时候,会产生新的字符串对象,如果要是频繁用String拼接,会出现很多新的字符串对 象,占用内存b.StringBuilder底层自带缓冲区,我们拼接的字符串都会出现在缓冲区中,不会每次拼接不会随意产生新 字符串对象,效率高,省内存。
2024-06-11 22:24:04
481
原创 033.搜索旋转排序数组
遇到 O(log n) 的题目,首先想到的就是二分查找,这道题也是一样,只不过在二分查找的基础上,增加了一些判断条件。而二分查找的关键是找到有序的部分。. - 力扣(LeetCode)
2024-06-07 21:56:25
821
原创 020.有效的括号,用栈来解决的 Java 版 LeetCode 刷题笔记
本次我们利用了栈这个数据结构来解决了括号匹配问题,实际上,栈还能解决更多问题,如表达式的转换、求值,而且通过保持栈内元素的单调性,还可以离线解决 RMQ 问题(问题,即区间最值问题)。. - 力扣(LeetCode)
2024-05-30 22:18:03
932
原创 032.最长有效括号
这道题依然考察的是栈这个数据结构,只不过是在有效括号的基础上,增加了一个长度的计算,所以我们只需要在遍历的过程中,不断更新最长有效括号的长度即可。当然了,Java 已经不再推荐使用 Stack 这个类,而是使用 Deque 接口的实现类 ArrayDeque,因为 Stack 继承了 Vector,而 Vector 是线程安全的,所以 Stack 的所有方法都是同步的,性能较差。
2024-05-30 21:04:36
807
原创 012整数转罗马数字
本题的关键是通过整数转罗马数字的表象,找出贪心算法的本质。这种找本质的能力,其实是需要大量的练习才能掌握的。比如说,还是找零的问题,面值不再是 1 元、2 元、5 元、10 元、20 元、50 元、100 元,而是 1 元、3 元、4 元,要你找零 6 元。如果是贪心算法,结果会是 1 张 1 元,2 张 1 元。但更优的选择应该是 2 张 3 元,对吧?贪心算法的局限性就在于它总是寻求局部最优解,而不一定能得到全局最优解。
2024-05-29 21:30:21
918
原创 058.最后一个单词的长度
这题如果直接正向去求解,往往会纠结于这个单词是不是最后一个单词,就需要复杂的判断条件,而且也会有一些冗余的比较,可能时间复杂度和反向求解是一样的,但实际运行的时候,会明显地感觉到效率很低。注意到题目的字符串只有空格和字母,所求又是最后一个单词的长度,那么我们只需要过滤掉字符串末尾的空格,然后从后往前数,看有多少个连续的非空的字符即可。解释:最后一个单词是长度为6的“joyboy”。解释:最后一个单词是“World”,长度为5。解释:最后一个单词是“moon”,长度为4。
2024-05-29 21:26:04
547
原创 012整数转罗马数字
本题的关键是通过整数转罗马数字的表象,找出贪心算法的本质。这种找本质的能力,其实是需要大量的练习才能掌握的。比如说,还是找零的问题,面值不再是 1 元、2 元、5 元、10 元、20 元、50 元、100 元,而是 1 元、3 元、4 元,要你找零 6 元。如果是贪心算法,结果会是 1 张 1 元,2 张 1 元。但更优的选择应该是 2 张 3 元,对吧?贪心算法的局限性就在于它总是寻求局部最优解,而不一定能得到全局最优解。
2024-05-21 20:54:41
579
原创 031.下一个排列Java实现
观察nums = [1,3,4,2] -> nums = [1,4,2,3]这一步,因为4比3大,且4的位置在3之后,所以将4与3交换,必然能够使得nums变大,交换了之后,则变成了nums = [1,4,3,2]。但显然这不是最小的比nums = [1,3,4,2]大的一个排列,我们还要把3和2的位置再翻转一下,才能得到nums = [1,4,2,3]这个。例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1]。
2024-05-11 21:08:55
756
原创 028.实现 strStr()
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1。简单输入:haystack = "sadbutsad", needle = "sad"输出:0解释:"sad" 在下标 0 和 6 处匹配。第一个匹配项的下标是 0 ,所以返回 0。输入:haystack = "leetcode", needle = "leeto"
2024-05-11 21:06:25
817
原创 网页使用之如何返回json/xml
后端返回json数据给前端进行渲染的方式比较熟悉,至于返回html页面,返回xml的方式接触逐渐减少,来在项目中熟悉这一点。
2024-04-25 21:50:47
1241
原创 请求参数解析
请求参数想必是很熟悉的,不过还是有许多的需要注意的。以下问题是否注意过?下面结合项目详解一下。如ReqRecordFilter中就对请求参数进行了解析,输出到req-log中。再比如 BodyReaderHttpServletRequestWrapper会对请求参数的流进行封装,避免请求因为i日志的打印提前消耗掉。下面,从get请求参数解析说起。
2024-04-22 22:12:55
954
原创 删除有序数组中的重复项
输入:nums = [1,1,2] 输出:2, nums = [1,2] 解释:返回新数组的长度 2,并且原数组 nums 的前两个元素被修改为 1, 2。输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:方法应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
2024-04-09 13:33:39
647
原创 移除元素Java实现
遍历结束后,j 的位置就是新数组的长度,因为它指向了第一个“空闲”的位置,也就是第一个没有被复制过的元素的位置。例如,方法返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。Java 并不存在引用传递,只有值传递,数组是一种特殊的对象,传递的是对象在堆中的地址,所以在方法中修改数组的内容是会影响到调用者的。输入:nums = [0,1,2,2,3,0,4,2], val = 2。输入:nums = [3,2,2,3], val = 3。
2024-04-09 11:26:47
522
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人