- 博客(89)
- 收藏
- 关注
原创 【八股文系列】Java并发
同一个object中多个方法都加了synchronized关键字的时候,其中调用任意方法之后需等该方法执行完成才能调用其他方法,即同步的,阻塞的;此结论同样适用于对于object中使用synchronized(this)同步代码块的场景;synchronized锁定的都是当前对象!
2023-05-23 11:47:41
390
1
原创 【八股文系列】JVM
在发生 Minor GC 之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间,如果大于,则此次 Minor GC 是安全的如果小于,则虚拟机会查看 HandlePromotionFailure 设置值是否允许担保失败。如果 HandlePromotionFailure=true,那么会继续检查老年代最大可用连续空间是否大于历次晋升到老年代的对象的平均大小,如果大于,则尝试进行一次 Minor GC,但这次 Minor GC 依然是有风险的;
2023-05-23 10:32:23
324
原创 【 Tech Lead 系列】关于 Tech Lead 这个角色
Tech Lead 是一个跨越技术和管理的角色。技术是其背景属性,但其职责又不单单是管理。带领团队冲锋陷阵,身先士卒才是 Lead 的精髓所在。主管、经理的意思却大相径庭。Tech Lead 好比战场上将帅的综合体。不但要能力过硬,可以带队冲锋陷阵。同时又要懂得调兵遣将,稳定军心,顾全大局。
2023-05-19 15:44:01
1222
原创 如何保证数据库和缓存一致性
1、想要提高应用的性能,可以引入「缓存」来解决2、引入缓存后,需要考虑缓存和数据库一致性问题,推荐用「先更新数据库,再删除缓存」的方案3、在「先更新数据库,再删除缓存」方案下,为了保证两步都成功执行,需配合「消息队列」或「订阅变更日志」的方案来做,本质是通过「重试」的方式保证数据一致性。
2023-05-18 15:40:01
273
原创 如何解决大事务问题
大家在实际项目开发中,我们在业务方法加上@Transactional注解开启事务功能,这是非常普遍的做法,它被称为声明式事务。为什么少用@Transactional注解。我们知道@Transactional注解是通过spring的aop起作用的,但是如果使用不当,事务功能可能会失效。如果恰巧你经验不足,这种问题不太好排查。至于事务哪些情况下会失效,可以参考。
2023-05-18 11:43:38
268
原创 spring事务不生效的多种场景
Spring事务的底层,还是依赖于数据库本身的事务支持。在MySQL中,MyISAM存储引擎是不支持事务的,InnoDB引擎才支持事务。因此开发阶段设计表的时候,确认你的选择的存储引擎是支持事务的。
2023-05-17 17:42:01
177
原创 如何保证接口幂等性
因为在很多业务场景中,为了保证业务正确性,往往会出现重复请求或着重复消息的情况。特别是在分布式系统中,由于网络不稳定或者负载均衡等原因,可能会出现重复请求的情况。如果接口不具备幂等性,则会导致多次重复执行相同的操作,从而导致数据的错误更新或其他问题。
2023-05-17 15:07:20
171
原创 微服务治理
即便是现有的开源方案同样无法完全自动化运维,肯定需要具备相关经验的架构师参与进来解决问题,尤其是随着公司本身的业务迭代速度,包括业务体量增长,对分布式架构包括分布式组件、中间件的要求会越来越复杂,很多能力是开源组件无法提供的,这就需要提供各种需求支撑业务发展,需要越来越庞大的团队去支撑。总体来说,一是有些行业中存在微服务的拆分原则,比如领域驱动设计等成熟的解决方案,其本身的理念是组织、团队跟着整个业务形态走,组织与系统架构结合越紧密,越能实现往前迭代的发展,从而避免过度拆分的问题;
2023-05-17 11:29:30
232
原创 DDD与微服务的关系
DDD是一种拆解业务、划分业务、确定业务边界的方法, 是一种高度复杂的领域设计思想,将我们的问题拆分成一个个的域, 试图分离技术实现的复杂性,主要解决的是软件难以理解难以演进的问题,DDD不是一种架构, 而是一种架构方法论, 目的就是将复杂问题领域简单化, 帮助我们设计出清晰的领域和边界, 可以很好的实现技术架构的演进。1、领域驱动设计基于领域建模而非数据建模。
2023-05-12 18:18:02
662
原创 什么是事件驱动(EDA)
事件驱动架构(Event-Driven Architecture, EDA)是一种基于事件的软件架构模式,它通过异步、松耦合的方式实现系统中各个组件之间的消息传递,从而支持高可扩展性、高可用性、高性能和灵活性。在事件驱动架构中,所有的信息都以事件的形式进行表达和处理。一个事件是一个抽象的、有意义的数据集,这些数据集可以被其他的服务接收、解码并做出对应的响应。事件可以由客户端、服务端或第三方应用程序生成,根据需要发送到任何其他服务以触发后续操作。
2023-05-12 10:28:58
1025
原创 Apache Pulsar 计算存储分离
Pulsar使用Bookeeper作为存储层,Pulsar将逻辑上的分区,在实际存储层面,分为多个段(segment)进行管理和存储。如果出现某个存储的机器有瓶颈,直接禁用该机器上segment,在新的机器上拉起新的Segment即可。从架构的角度出发,我个人理解,解决的思路就是:计算存储分离 + 存储分段。计算存储分离:解决的是计算压力的快速转移。计算节点只负责计算逻辑的处理,是无状态的节点。总结一下,一旦Pulsar集群遇到上面说的Kafka集群类似的瓶颈,从扩容的角度来说,会更优雅和便捷。
2023-05-01 10:39:11
328
原创 Kafka的Rebalance机制可能造成的影响及解决方案
在Kafka中,当有新消费者加入或者订阅的Topic数发生变化时,会触发Rebalance(再均衡:在同一个消费者组当中,分区的所有权从一个消费者转移到另外一个消费者)机制,Rebalance顾名思义就是重新均衡消费者消费。Rebalance的过程如下:第一步:所有消费成员都向Coordinator发送请求,请求入Consumer Group。一旦所有成员都发送了请求,Coordinator会从中选择一个Consumer担任Leader的角色,并把组成员信息以及订阅信息发给Leader。
2023-05-01 10:11:21
1341
原创 HashMap何时扩容以及它的扩容机制
当向容器添加元素的时候,会判断当前容器的元素个数,如果大于等于阈值(即当前数组的长度乘以加载因子的值的时候),就要自动扩容了。默认长度16,加载0.75扩容(resize)就是重新计算容量,向HashMap对象里不停的添加元素,而HashMap对象内部的数组无法装载更多的元素时,对象就需要扩大数组的长度,以便能装入更多的元素。当然Java里的数组是无法自动扩容的,方法是使用一个新的数组代替已有的容量小的数组,就像我们用一个小桶装水,如果想装更多的水,就得换大水桶。
2023-04-16 09:49:58
884
原创 ES深分页方案
如果数据量小(from+size在10000条内),或者只关注结果集的TopN数据,可以使用from/size 分页,简单粗暴数据量大,深度翻页,后台批处理任务(数据迁移)之类的任务,使用 scroll 方式数据量大,深度翻页,用户实时、高并发查询需求,使用 search after 方式,Search_After本身就是一种业务折中方案,它不允许指定跳转到页面,而只提供下一页的功能。
2023-04-15 21:04:04
788
原创 分布式事务框架 DTM 对比 SEATA
分布式系统最大的敌人可能就是NPC了,在这里它是Network Delay, Process Pause, Clock Drift的首字母缩写。我们先看看具体的NPC问题是什么:Network Delay,网络延迟。虽然网络在多数情况下工作的还可以,虽然TCP保证传输顺序和不会丢失,但它无法消除网络延迟问题。Process Pause,进程暂停。有很多种原因可以导致进程暂停:比如编程语言中的GC(垃圾回收机制)会暂停所有正在运行的线程;
2023-04-15 20:24:06
1131
原创 分布式链路追踪
上一篇文章介绍了分布式链路追踪的一种方式:Spring Cloud Sleuth+ZipKin,这种方案目前也是有很多企业在用,但是作为程序员要的追逐一些新奇的技术,Skywalking作为后起之秀也是值得大家去学习的。skywalking是一个优秀的国产开源框架,2015年由个人吴晟(华为开发者)开源 , 2017年加入Apache孵化器。短短两年就被Apache收入麾下,实力可见一斑。
2023-04-12 21:20:17
140
原创 分布式事务总结
分布式事务本身就是一个技术难题,业务中具体使用哪种方案还是需要不同的业务特点自行选择,但是我们也会发现,分布式事务会大大的提高流程的复杂度,会带来很多额外的开销工作,「代码量上去了,业务复杂了,性能下跌了」。我们真实开发的过程中,能不使用分布式事务就不使用。
2023-04-12 11:35:46
128
原创 Mybatis 缓存原理
第一次发出一个查询 sql,sql 查询结果写入 sqlsession 的一级缓存中,缓存使用的数据结构是一个 map。key:MapperID+offset+limit+Sql+所有的入参value:用户信息同一个 sqlsession 再次发出相同的 sql,就从缓存中取出数据。如果两次中间出现 commit 操作(修改、添加、删除),本 sqlsession 中的一级缓存区域全部清空,下次再去缓存中查询不到所以要从数据库查询,从数据库查询到再写入缓存。
2023-04-12 09:28:50
93
原创 Spring AOP与AspectJ
当你不用Spring AOP提供的注解时,Spring AOP和AspectJ没半毛钱的关系,前者是JDK动态代理(接口级别),用到了CGLIB(Code Generation Library),CGLIB是一个代码生成类库,可以在运行时候动态是生成某个类的子类。代理模式为要访问的目标对象提供了一种途径,当访问对象时,它引入了一个间接的层。后者是静态代理,在编译阶段就已经编译到字节码文件中。这种情况下不使用注解,使用xml配置。
2023-04-11 10:37:10
669
原创 Java 定时任务选型
创建 java.util.TimerTask 任务,在 run 方法中实现业务逻辑。通过 java.util.Timer 进行调度,支持按照固定频率执行。所有的 TimerTask 是在同一个线程中串行执行,相互影响。也就是说,对于同一个 Timer 里的多个 TimerTask 任务,如果一个 TimerTask 任务在执行中,其它 TimerTask 即使到达执行的时间,也只能排队等待。如果有异常产生,线程将退出,整个定时任务就失败。
2023-04-10 00:04:39
189
原创 Java实现浅复制和深复制
该方法会创建一个新的对象,并将原对象的非静态字段复制到新对象中。如果原对象的字段是引用类型,则只复制引用而不复制对象本身。浅复制:将原对象的所有非静态字段复制到新对象中,如果字段是引用类型,则只复制引用而不复制对象本身。这意味着新对象和原对象引用的是同一个对象,任何一个对象的改变都会影响另一个对象。深复制:将原对象的所有非静态字段复制到新对象中,如果字段是引用类型,则创建一个新的对象,并将引用指向新对象。这意味着新对象和原对象引用的是不同的对象,它们之间的改变不会相互影响。通过序列化和反序列化实现深复制。
2023-04-09 23:30:35
273
原创 静态内部类
静态内部类Node与HashMap的实例无关,它具有独立的作用域和生命周期,避免了与HashMap的耦合,提高了代码的可复用性和可扩展性。使用静态内部类Node可以将键值对的数据封装在一个独立的类中,避免了对外暴露过多的类和接口,提高了代码的安全性和可维护性。静态内部类Node可以继承HashMap.Entry类,同时还可以重写父类的方法,从而具有更好的多态性和灵活性。使用静态内部类Node可以让代码更加清晰和易读,它可以将复杂的逻辑封装在一个独立的类中,从而降低了代码的复杂性。
2023-04-09 23:06:24
104
原创 ThreadLocal 原理
并发编程是一项非常重要的技术,它让我们的程序变得更加高效。但在并发的场景中,如果有多个线程同时修改公共变量,可能会出现线程安全问题,即该变量最终结果可能出现异常。为了解决线程安全问题,JDK出现了很多技术手段,比如:使用synchronized或Lock,给访问公共资源的代码上锁,保证了代码的原子性。但在高并发的场景中,如果多个线程同时竞争一把锁,这时会存在大量的锁等待,可能会浪费很多时间,让系统的响应时间一下子变慢。因此,JDK还提供了另外一种用的新思路:ThreadLocal。
2023-04-09 12:11:29
103
原创 volatile关键字
1、volatile保证变量对所有线程的可见性:当volatile变量被修改,新值对所有线程会立即更新。或者理解为多线程环境下使用volatile修饰的变量的值一定是最新的。2、jdk1.5以后volatile完全避免了指令重排优化,实现了有序性。
2023-04-09 10:29:11
87
原创 JAVA 锁
乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。
2023-04-09 10:14:58
93
原创 CopyOnWriteArrayList
首先我讲一下什么是Copy-On-Write,顾名思义,在计算机中就是当你想要对一块内存进行修改时,我们不在原有内存块中进行写操作,而是将内存拷贝一份,在新的内存中进行写操作,写完之后呢,就将指向原来内存指针指向新的内存,原来的内存就可以被回收掉嘛!这是一种用于程序设计中的优化策略,是一种延时懒惰策略。
2023-04-09 00:01:56
112
原创 ConcurrentHashMap
ConcurrentHashMap使用分段锁技术,将整个数据结构分段(默认为16段)进行存储,然后给每一段数据配一把锁(继承ReentrantLock),当一个线程占用锁访问其中一个段的数据的时候,其他段的数据仍然能被其他线程访问,能够实现真正的并发访问。。数据结构:取消了Segment分段锁的数据结构,取而代之的是Node数组+链表+红黑树的结构,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。
2023-04-08 21:03:12
379
原创 HashMap
JDK 7 中,HashMap 由“数组+链表”组成,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。在 JDK 8 中,HashMap 由“数组+链表+红黑树”组成。链表过长,会严重影响 HashMap 的性能,而红黑树搜索的时间复杂度是 O(logn),而链表是糟糕的 O(n)。
2023-04-08 20:18:32
180
原创 Redis的rehash原理
由于新哈希表和旧哈希表使用不同的哈希函数,因此在迁移元素时,可能会出现多个元素映射到同一个哈希槽位的情况,这种情况称为哈希冲突。Redis的rehash是指在Redis哈希表的扩容和收缩操作中,为了保证数据的正确性和一致性,需要将哈希表中的所有元素重新映射到新的哈希表中,这个过程就称为rehash。当Redis的哈希表需要进行扩容和收缩操作时,会先创建一个新的哈希表,并将其大小设置为当前哈希表大小的两倍或者一半,以便能够容纳所有元素。新哈希表的大小必须是2的倍数,这是为了保证哈希算法的正确性。
2023-04-08 19:55:46
613
原创 sentinel 限流熔断组件
对于资源的定义有两种,一种是硬编码的方式,一种是通过 @SentinelResource 注解的方式。流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则和 热点参数规则。而定义规则同样支持两种方式:一种是硬编码的方式,一种是通过 sentinel-dashboard 控制台直接配置。
2023-04-08 11:53:28
227
原创 redis-lua实现令牌桶限流算法
流控算法是用来控制流量的一种算法,它可以在高并发场景中避免系统的过载,保证系统的稳定性和可用性。常见的流控算法包括以下几种:漏桶算法漏桶算法是一种常用的流控算法,它将流量视为水流,使用一个固定大小的桶来缓存流量,然后以固定的速率向外输出流量。当桶中的水满时,多余的流量将被丢弃。漏桶算法可以有效地控制流量,避免系统的过载。令牌桶算法令牌桶算法是一种基于令牌的流控算法,它将流量视为令牌,使用一个固定大小的桶来缓存令牌,并以固定的速率向桶中添加令牌。
2023-04-08 11:51:24
649
原创 Arthas - Java 线上问题定位处理利器
Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,提供 Tab 自动补全,可以方便的定位和诊断线上程序运行问题。已经收获 Star 30000+。Arthas 官方文档十分详细,本文也参考了官方文档内容,同时在开源在的 Github 的项目里的 Issues 里不仅有问题反馈,更有大量的使用案例,也可以进行学习参考。
2023-04-06 11:38:34
242
原创 redis执行一条命令的内部底层有哪些流程
在命令执行过程中,Redis 还会进行一些其他的操作,例如命令的缓存、网络 IO 的优化等。在命令执行时,Redis 将会根据具体的命令类型,对数据结构进行相应的操作。在解析请求时,Redis 将会检查请求的格式和参数是否正确,如果发现格式或参数错误,Redis 会发送错误响应给客户端。:当 Redis 客户端向 Redis 服务器发送一条命令请求时,该请求将被发送到 Redis 服务器的 TCP/IP 端口,并被 Redis 服务器接收。:在解析请求后,Redis 会将请求分发到相应的数据结构处理模块。
2023-04-05 17:14:18
149
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人