自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

远方的少年

笑看花开花落,坐听风起云动

  • 博客(375)
  • 收藏
  • 关注

原创 对象什么时候进入年老代

1.在年轻代存活超过了一定的年龄,所谓的年龄就是经过minor Gc的次数。2.大对象会直接进入老年代,避免了在年轻代多次拷贝过来拷贝过去的开销。3.当minor gc发生时,如果surivor区放不下会进入年老代。

2024-12-21 19:50:30 272

原创 Sass系统数据隔离的三种方式

缺点:不同租户之间可能会相互影响,例如某些大客户数据量特别大,因为是同一个数据库,那么其他数据量小的也会收到影响。针对一些大客户的定制化开发,比较困难,而且由于所有租户的数据放到了一起,容易导致表的数据量过大,往往需要分库分表来进行解决。优点:达到了真正的按租户进行隔离,不同租户之间相互没有影响,可以针对一些特殊租户例如大客户做一些定制化的开发,计费相对简单,按照资源使用进行计费。缺点:成本高,版本更新迭代的维护成本高,统计,管理租户比较困难,共享数据有多份,有资源浪费。为每一个租户单独部署一个数据库。

2024-12-19 22:05:06 440

原创 volatile浅谈

由于JMM模型中有主内存和线程的工作内存之分,因为每个工作内存里面的变量都是主内存的副本,在没有其他机制保证的情况下,其中一个线程在对一个共享变量修改后,只会修改自己的副本,同步主内存,但是其他线程仍然操作的是自己的副本,这个就是可见性问题,这里需要了解一下操作系统的缓存一致性(MESI机制),加入了volatile修饰后,能保证将修改的值立马从工作线程刷回到主内存,并且让其他线程里面的共享变量变为失效状态,那么当线程需要访问变量时需要重新从主内存读取。下面谈一下volatile如何实现的可见行和有序性。

2024-12-19 17:47:44 351

原创 redis stream轻量级消息队列

redis 5.0 之后新推出了stream数据结构,可以实现一个轻量级的消息队列,下面通过自定义注解和springboot使用一下redis stream。3.将我们的所有消费者注册到redis stream的listener中。2.定义一个listener的父类,让所有的消费者继承该类。5.消费者消费消息,需要继承上面定义的listener的抽象类。

2024-12-15 15:51:37 574

原创 jedis,lettuce,redisson对比

总结一下就是lettuce底层使用netty进行通信,是线程安全的,并且支持异步和响应式编程,在高并发的情况下,效率会更高。jedis是一个老牌的java的redis客户端,仅支持同步的方式连接,redis官网有一句这样的话。官方也推荐如果需要异步或者响应式的支持,可以使用lettuce。下面摘抄一下 lettuce官网的介绍。redisson对分布式的锁,集合提供了更好的支持,通过一些简单的api就可以访问。再来看下redisson的官方介绍。

2024-12-13 16:07:47 637

原创 复现502与504状态码

平常我们在开发的时候可能会遇上502或者504状态码,这两个错误码其实都是nginx类似的代理网关返回的,502 BAD GATEWAY网关错误,通常是由于网与后台服务之间通信出了问题,或者配置出了问题,或者是后台服务宕机了导致的,504 GATEWAY TIMEOUT表示后台服务处理时间过长,导致后台服务返回网关超时了,通常由于后台服务出问题了,响应超时,例如查数据库很慢或者请求外部接口很慢,或者CPU飙高等等。下面我就通过nginx来代理后台的一个简单的springboot项目来复现一下这两种情况。

2024-12-13 14:55:26 315

原创 关于自增id的那些事儿

通常我们会指定自增id作为数据库的主键,但是在分布式场景下,例如分库分表,还有私有化部署与公有云部署共存时可能会有id重复的问题,但是自增id也有它的好处,就是是递增的,能防止页分裂的情况,检索,查询的效率比较高,而且空间占用率低。1.由于数据库的唯一性约束,导致数据插入失败,但是这个时候已经申请了id,导致这个auto_increment的计数器已经加一了。5.7版本及以前,这个自增计数器是存在内存里面的,当重启后,第一次插入时会执行一条sql语句,如下,获取当最大id作为计数器的值。

2024-12-11 18:04:13 310

原创 类加载机制

通过双亲委派模型来保证类的唯一性,需要注意的是类加载的时候是加锁的,所以是线程安全的。执行类的clinit方法,clinit方法是将类的静态成员变量和静态代码块按照代码顺序移入类构造方法。单例模式中静态内部类的形式其实就是利用了类加载的懒加载和加锁的特性,所以才有懒加载和保证线程安全的特性。jvm加载类是通过懒加载的方式,也就是在需要使用的时候才会加载类,包括以下情形。1.2 在方法区中根据字节码的内容生成对应的类的数据就结构。1.1 通过一个类的全名来获取一个二进制的字节流。6.访问类的子类的时候。

2024-12-11 12:59:10 253

原创 常见限流算法

原理:同上面的固定时间窗口类似,也会有时间窗口的概念,只是它将时间窗口划分成了更小的粒度,窗口是可以移动的。常见的限流算法包括 固定时间窗口计数器算法,滑动时间窗口计数器算法,漏桶算法,令牌桶算法。缺点:因为维护了更小力度的窗口及统计,所以空间和时间复杂度更高,而且会直接拒绝超过阈值的请求,没法儿让请求排队。原理:按照时间划分窗口,每个窗口内维护一个计数器,当计数器的值小于限流阈值时,拒绝请求,否则放行。原理:有一个维护令牌的桶,按照一定的速率生成令牌,放入桶中,如果请求获得了令牌就放行,否则就拒绝。

2024-12-09 16:31:10 422

原创 springboot整合liteflow

liteflow是一个轻量级的规则引擎,基于工作台模式,通过抽象出来的组件来将复杂的内部业务逻辑进行解偶,可以在价格,下单等包含复杂业务逻辑的场景中应用。3.定义规则编排的配置文件,在resource/config下面新建flow.el.xml文件。2.在application中添加配置,指定规则编排的配置文件。5.执行规则引擎,通过上面定义的规则名称,chain1,传入参数即可调用。下面演示一下springboot如何整合liteflow。4.定义上面组件的a,b组件。

2024-12-08 19:53:08 509

原创 摩尔投票法

摩尔投票法是用来查找一个给定的数组中出现的大多数元素的问题,最开始设计这个算法是为了统计出选票最多的候选人,它的前提是假定数组中存在超过半数的元素,如果没有这个前提,那么摩尔投票法也没有效果了。原理:将是众数的元素设置为-1,将不是众数的元素设置为1.这样最后和为0的那个就是众数。

2024-12-08 11:09:59 159

原创 负载均衡算法

常见的负载均衡算法主要有以下六种,分为两大类,静态负载均衡,和动态负载均衡两类,所谓静态负载均衡,指的是,负载均衡算法是固定的,跟服务端的性能等指标无关。2.轮询,这个是很多负载均衡器的默认选项,像ribbon,nginx都是使用的这种。1.最少连接数,这个需要统计服务提供者的连接信息,可能会带来额外的性能开销。2.最少响应时间, 这个也需要统计服务提供者的响应信息,也回带来额外的开销。3.加权轮询,这个需要手动配置权重,需要维护,而且权重的值不太好衡量。

2024-12-07 21:50:54 384

原创 页分裂及页合并

当我们插入数据时,如果我们的主键是递增的,那么一个页满了之后,就会在下一个页写数据,但是如果我们插入的主键不是递增的,处于已有数据的中间,那么就需要将页的数据重新进行组织,也就是页分裂,需要移动一部分数据,来维持主键递增排序,这个会对性能造成一部分影响,所以我们在设计数据库主键的时候要尽量保证主键是递增的,顺序插入。当我们删除一些数据的时候,会导致一些页有一部分空出来,那么为了提升页的空间存储效率,会进行页的合并,这个阈值默认是50%。聚簇索引的b+树,叶子结点存放的是我们的数据,通过双向链表进行连接。

2024-12-04 19:18:21 309

原创 GCROOT对象包含哪些

了解程序怎么运行的同学应该知道,我们程序的运行,需要通过压栈和出栈来保存一些程序运行中的中间变量等临时数据,那么栈中的本地变量表正是我们程序正在运行中需要用到的一些变量,所以栈的本地变量表中指向的引用肯定是有用的,所以才是gcroot的其中一种。我个人觉的这些也是jvm设计者的经验得到的。类的静态变量是存在于方法区中,方法区中的内容是所有线程所共享的,属于类的字节码里面的内容,所以不会被回收。这个类似于上面的虚拟机栈的原理,只不过一个是运行java方法的栈,一个是运行native方法用到的栈。

2024-12-02 23:51:27 214

原创 分布式事务之最大努力通知

最大努力通知是分布式事务中对时效不敏感的场景下的一种异步通知的解决方案,通常在第三方支付通知业务系统支付结果的情况下需要使用这种最大努力通知方案。最大努力通知方案需要注意几个问题。因为消息可能丢失,所以需要重复通知,一般像支付宝是按照时间阶梯递增的方式来重复通知,例如支付成功后立刻通知一次,然后是5分钟后,10分钟后,半小时后,2个小时后等等。由于消息会重复通知,所以业务方的回调接口需要做幂等处理,例如根据订单号查询订单如果已经支付,就立刻返回成功,不再做剩下的处理。

2024-12-02 17:51:19 148

原创 滑动窗口解决最长递增子序列问题

给定一个只包含数字的字符串,例如“127343456”,找出最长递增子序列,例如上面的就是3456就是最长递增子序列.可以使用滑动窗口来解决这个问题,从而在O(n)的时间复杂度内完成.

2024-11-30 16:37:06 140

原创 服务器时钟回拨

先来聊一下NTP(network time protocol)互联网时间协议。我们的电脑里面有一个硬件时钟,当我们关机后,我们的硬件时间还在走动。通过NTP,电脑会向时间服务器发送校准请求,校准电脑的时间,这个时候如果我们的硬件时钟走快了,那么就会校准时钟,就会让时间回到过去的时间。这样就出现了时钟回拨的问题。在我们使用雪花算法,或者其他依赖时间戳的中间件时,时钟回拨会带来一些问题,例如会生成重复的id,所以在这些情况下我们需要考虑到时钟回拨的问题,并进行处理,防止对我们的系统或者逻辑产生错误的影响。

2024-11-28 23:37:25 190

原创 如何解决原子类的ABA问题

众所周知,原子类存在ABA问题,如何解决呢,jdk提供了AtomicStampedReference类,通过类似数据库乐观锁的版本号的形式,来解决。

2024-11-25 18:22:21 127

原创 如何防止序列化破坏单例模式

反序列化时会调用readObject方法,里面会判断是否有重写readResolve方法,如果重写了就会执行readResolve方法,并将方法的返回值返回,我们可以利用这一点,在单例模式的类中实现readResolve方法,将单例对象返回回来,这样序列化就不能破坏单例了。反射和序列化都可以破解懒汉式和饿汉式。下面来讨论一下如何防止序列化来破坏单例模式,

2024-11-25 17:53:03 442

原创 @Transactional事务失效的场景

@Transactional事务失效的场景。

2024-11-15 12:35:16 134

原创 docker与虚拟机的区别

docker出现在虚拟机之后,由于虚拟机是模拟一整套操作系统,包括硬件,导致体积大,启动慢,资源浪费。每一个虚拟机都包含一个完整的操作系统,而docker则是复用宿主机的操作系统内核,每一个容器相当于一个独立隔离开的进程,有自己的文件系统,所以体积小,启动快,更加轻量级。

2024-11-12 21:49:43 139

原创 使用bitset判断一亿个数中是否存在某一个数

bitset是一个位的集合,如果添加某个数,就会将该位上设置为true,默认为false.这样可以实现压缩。

2024-11-11 13:26:57 399

原创 三个线程交替打印

思路:使用线程间通信的wait和notify来实现,需要借助额外的一个状态变量来控制打印的顺序,需要通过while循环来判断,如果不是当前线程打印时机,则需要让出锁。问题:启动三个线程,按照第一个线程打印A,第二个线程打印B,第三个线程打印C.交替打印。

2024-11-08 20:50:50 209

原创 事务的 ACID特性及如何保证的

持久性(Durable). 持久性指的是事务一旦提交,那么就应该永久的状态,不会因数据库宕机等意外情况而丢失事务操作的数据。例如转账事务,一个人转出了500,那么另外一个人要收到500,保证最终的状态是一致的,一致性是原子性,隔离性,持久性三个特性共同来保证的。靠undo log来保证,每条sql执行时会在undo log里面记录一条相反的日志,如果要回滚就执行undo log里面的回滚sql来进行回滚。事务是数据库的一个非常重要的特性,包含ACID四大特性,下面详细介绍一下这四大特性及背后是如何保证的。

2024-08-31 00:25:04 579

原创 using filesort优化方案

问题:如果我们排序的时候,不能直接通过有序的索引直接返回排序数据,需要通过内存或者文件排序时,用explain关键字来解释sql时辉出现using filesort,进行了额外的排序,这样会使得排序的效率不高,通常是我们优化的重点方向。2.索引的维护成本很高,如果不好加索引,那么尽量不要使用select *的方式,只查询出需要的字段,这样可以减少需要查询的数据量,可以使用全字段排序和内存排序。1.如果排序的字段是索引,那么查询的数据直接就是有序的,不需要再进行二次的排序。mysql排序的过程。

2024-08-13 19:05:32 475

原创 适配器模式

聋哑人期望获的手语信息,而播音员提供的是语音信息,两者之间不兼容,所以需要手语播音员来作为适配器来转换信息,注意这个不兼容通常是不可调和的矛盾,例如聋哑人一下子治好不现实,或者让播音员不说话,只用手势也不现实,因为要照顾更多的正常人收听新闻。在日常开发中,我们可能经常需要跟外部接口交互,而我们的接口可能不跟外部的接口兼容,例如我们接口需要的是json格式,而外部接口是xml格式,或者报文的字段名不一致,这个时候就可以使用适配器模式。ITarget目标接口类。Adaptee 适配类。Adapter被适配类。

2024-02-01 10:20:58 680

原创 浅谈ICMP协议

ICMP(Internet Control Message Protocol) 网络控制消息协议是网络层的协议,所谓控制,指的是通过下发指令来判断是否当前主机可达目标主机及不可达时的错误报告。通常使用ping命令和traceroute命令来使用。traceroute命令:检测到目标主机中间经过了哪些路由器,并判断最终是否可达目的主机。ping命令:检测到目标主机是否可达、

2024-01-26 19:21:16 302

原创 leetcode 141 环形链表

解题思路:链表类的题,很多都可以使用快慢指针来解决,本题也可以使用快慢指针,如果有环,那么最后快慢指针指向的元素必定相同。leetCode141题:判断一个给定的链表是否有环。

2024-01-21 21:24:56 447

原创 浅谈ARP协议

ARP是 address resolution protocol的缩写,意思是地址解析协议,处于OSI七层模型的网络层,它的作用是根据Ip地址找到mac地址,实际上我们需要访问某一个ip时,是要先找到它的mac地址,也就是物理地址才行的,那么当本机第一次访问一个Ip时,需要通过广播arp请求,传送本机的Ip,mac地址以及目标的ip,然后目标ip收到请求后,会返回它的mac地址,然后本机收到回复后将目标ip和目标mac地址给缓存下来。下面展示一个arp请求的抓包过程,只需要在我们本地ping一个ip即可。

2024-01-20 21:55:19 467

原创 Leetcode160 两个链表是否相交

此题可以说是算法界第一深情,如果我走过你走过的路,那么我们就可能会相遇。leetcode 160题,判断两个链表是否相交。

2024-01-10 21:30:08 466

原创 leetcode231 判断一个给定的整数是否是2的n次幂

解题思路:用二进制来判别,因为2的n次幂是低位为1,末尾全为0的形式,类似a10000...这种形式,那么n - 1 就是a011111...的形式,用N & N - 1的结果为零,即可判断出来。先考虑边界条件,如果一个数小于等于零,那么肯定就不是2的N次幂。

2024-01-05 22:09:22 504

原创 使用图论里面的dfs解决岛屿问题

解题思路:碰到陆地,通过dfs将相邻的陆地置为水域,最后找到岛屿数量。参见leetcode 200题。

2024-01-04 20:55:46 434

原创 利用堆来解决数组的topK问题

可以利用堆来解决这个问题,将数组的元素依次加入最小堆,然后如果堆的大小超过了K,则将堆顶的元素删除,这样,最后堆顶的元素就是第K大的元素,附上java的代码。leetcode 215 数组的第K大元素。

2024-01-03 20:11:40 377

原创 谈谈cpu cache line对程序代码的影响

为了解决cpu运行速度和内存速度不匹配的问题,引入了cpu三级缓存,L1,L2,L3.其中缓存是以缓存行为基本单位的,每次取数据都是取一个缓存行的数据,批量读取。所以肯能会出现多个cpu共享缓存行时,需要进行同步数据的工作。下面就是通过将共享数据放入两个缓存行来提高运行速度的例子,Java中的Thread类也有@Contented也是类似作用。可以看到,利用cpu cache line的特性可以提高约4倍左右的性能。将注释的代码放开,将共享数据放入两个缓存行,运行结果。

2023-12-27 17:26:01 444

原创 毒酒问题算法题

题目:有1000瓶酒,其中一瓶有毒,毒性一周以后会爆发,现在拿小白鼠来做实验,问最少需要多少只小白鼠,才能一周之后知道哪一瓶酒有毒?答案:10只,1000转化成二进制,最多10位,2^10 = 1024 > 1000,最后通过取交集的方式可以判断出哪一瓶酒有毒。

2023-12-26 15:18:37 654

原创 java-thread-affinity线程绑核

通过将线程绑定到指定的cpu上,可以提高执行效率。因为每次都是相同的cpu,可以充分利用高速缓存,在java中可以使用以下依赖来使用。具体使用可以自行查阅。

2023-09-02 19:51:46 421

原创 Thread.enumerate方法

Thread.enumerate方法的作用是将当前线程所对应的的线程组包含的所有线程放入一个数组。

2023-08-30 20:48:54 300

原创 XML与JAVA对象之间的相互转换

(Java Architecture for XML Binding简称JAXB)允许Java开发人员将Java类映射为XML表示方式.使用起来极其的方便。先看一下JAXB的源码注释。jdk中默认提供了一个。1.创建java对象 Person。查看person.xml内容。下面来写一个简单的例子。

2023-05-11 11:12:17 247

原创 Mybatis使用java方法返回调用的sql语句

3.使用@SelectProvider,@UpdateProvider,@InsertProvider,@DeleteProvider通过调用java方法返回sql语句。2.使用@Select,@Update,@Insert,@Delete在注解里面写上sql。1.在mapper.xml中定义sql语句,关联dao中的接口方法。我们在使用mybatis时,可以有三种方式。下面看下源码中的注释SelectProvider。

2023-04-29 22:05:30 724

原创 mysql数据碎片整理

mysql中的表在delete操作后并没有真的清理调,而是标记为已删除,内存空间依然占用,后续插入的时候会优先使用这些碎片。这些碎片的存在会加大存储空间的占用,还会导致查询效率的降低,定期的清理mysql表的碎片还是很有必要的,清理碎片可以使用Optimize table tab_name语句。但是清理碎片会导致锁表,所以清理周期不能太频繁。

2023-04-21 10:38:52 474

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除