- 博客(49)
- 收藏
- 关注
原创 BIO、NIO编程与直接内存、零拷贝详解
什么是 NIO?NIO 库是在 JDK 1.4 中引入的。NIO 弥补了原来的 BIO 的不足,它在标准 Java 代码中提供了高速的、面向块的 I/O。NIO 被称为 no-blocking io 或者 new io 都说得通。和BIO 的主要区别面向流与面向缓冲Java NIO 和 IO 之间第一个最大的区别是,IO 是面向流的,NIO 是面向缓冲区的。 Java IO 面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。
2024-08-28 23:27:30
551
原创 网络通信和TCP/IP协议详解
计算机网络的标准定义是:利用通信线路将地理上分散的、具有独立功能的计算机系统和通信设备按不同的形式连接起来,以功能完善的网络软件及协议实现资源共享和信息传递的系统。计算机网络从覆盖范围上划分可以分为三类:局域网、城域网、广域网。局域网LAN(作用范围一般为几米到几十公里)、城域网MAN(界于WAN与LAN之间)、广域网WAN(作用范围一般为几十到几千公里)。
2024-08-26 00:03:32
1282
原创 Zookeeper分布式一致性协议ZAB介绍
ZAB 协议全称:Zookeeper Atomic Broadcast(Zookeeper 原子广播协议)。Zookeeper 是一个为分布式应用提供高效且可靠的分布式协调服务。在解决分布式一致性方面,Zookeeper 并没有使用 Paxos ,而是采用了 ZAB 协议,ZAB是Paxos算法的一种简化实现。ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复和原子广播的协议。
2024-08-24 23:37:32
1530
原创 Zookeeper集群Leader选举源码
整个zookeeper选举底层可以分为选举应用层和消息传输层,应用层有自己的队列统一接收和发送选票,传输层也设计了自己的队列,但是按发送的机器分了队列,避免给每台机器发送消息时相互影响,比如某台机器如果出问题发送不成功则不会影响对正常机器的消息发送。1、将conf文件夹里的zoo_sample.cfg文件复制一份改名为zoo.cfg,将zoo.cfg文件位置配置到启动参数里。源码导入idea后,org.apache.zookeeper.Version类会报错,需要建一个辅助类。
2024-08-22 00:08:37
441
原创 Zookeeper应用场景实战二
在单体的应用开发场景中涉及并发同步的时候,大家往往采用Synchronized(同步)或者其他同一个JVM内Lock机制来解决多线程间的同步问题。在分布式集群工作的开发场景中,就需要一种更加高级的锁机制来处理跨机器的进程之间的数据同步问题,这种跨机器的锁就是分布式锁。(1)基于数据库的分布式锁。这种方案使用数据库的事务和锁机制来实现分布式锁。虽然在某些场景下可以实现简单的分布式锁,但由于数据库操作的性能相对较低,并且可能面临锁表的风险,所以一般不是首选方案。(2)基于Redis的分布式锁。
2024-08-20 00:00:00
1203
原创 Zookeeper应用场景实战一
1. Zookeeper Java客户端实战ZooKeeper应用的开发主要通过Java客户端API去连接和操作ZooKeeper集群。可供选择的Java客户端API有:ZooKeeper官方的Java客户端API。第三方的Java客户端API,比如Curator。ZooKeeper官方的客户端API提供了基本的操作。例如,创建会话、创建节点、读取节点、更新数据、删除节点和检查节点是否存在等。不过,对于实际开发来说,ZooKeeper官方API有一些不足之处,具体如下:
2024-08-18 13:09:30
1110
原创 Zookeeper数据结构与集群架构详解
ZooKeeper 是一个开源的分布式协调框架,是Apache Hadoop 的一个子项目,主要用来解决分布式集群中应用系统的一致性问题。Zookeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。ZooKeeper本质上是一个分布式的小文件存储系统(Zookeeper=文件系统+监听机制)。提供基于类似于文件系统的目录树方式的数据存储,并且可以对树中的节点进行有效管理,从而用来维护和监控存储的数据的状态变化。
2024-08-16 23:33:13
1130
原创 Redis缓存架构设计与性能优化
缓存穿透是指查询一个根本不存在的数据, 缓存层和存储层都不会命中, 通常出于容错的考虑, 如果从存储层查不到数据则不写入缓存层。缓存穿透将导致不存在的数据每次请求都要到存储层去查询, 失去了缓存保护后端存储的意义。造成缓存穿透的基本原因有两个:第一, 自身业务代码或者数据出现问题。第二, 一些恶意攻击、 爬虫等造成大量空命中。
2024-08-14 23:02:33
1257
原创 [Redis] Redisson分布式锁原理及源码分析
使用 Redis 的 SETNX 命令(Set if Not Exists)来确保只有一个客户端可以成功创建一个锁键。使用 EXPIRE 命令设置键的过期时间,防止死锁。如果客户端成功设置了锁键,它就获得了锁;如果失败,则表示锁已被其他客户端占用。为了解决锁失效或客户端故障问题,可以使用 Redisson 或者实现 Redlock 算法来增强锁的可靠性。
2024-08-12 23:43:16
910
原创 Redis集群搭建与原理分析
Redis Cluster 将所有数据划分为 16384 个 slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。同时因为槽位的信息可能会存在客户端与服务器不一致的情况,还需要纠正机制来实现槽位信息的校验调整。
2024-08-11 16:22:27
1352
原创 Redis持久化机制,主从与哨兵架构详解
1. Redis持久化1.1 RDB快照(snapshot)在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:#save 60 1000 //关闭RDB只需要将所有的save保存策略注释掉即可
2024-08-09 21:00:00
1012
原创 Redis数据结构与原理解析
5.1 Redis是单线程吗?Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。5.2 Redis 单线程为什么还能这么快?因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如key
2024-08-07 23:43:38
1263
原创 Spring事务源码解析
开启Spring事务本质上就是增加了一个Advisor,但我们使用@EnableTransactionManagement注解来开启Spring事务,该注解代理的功能就是向Spring容器中添加了两个Bean:AutoProxyRegistrarProxyTransactionManagementConfigurationAutoProxyRegistrar主要的作用是向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的Bean。
2024-08-05 21:30:43
973
原创 SpringAOP-底层实现源码解析
OOP表示面向对象编程,是一种编程思想,AOP表示面向切面编程,也是一种编程思想,而我们上面所描述的就是Spring为了让程序员更加方便的做到面向切面编程所提供的技术支持,换句话说,就是Spring提供了一套机制,可以让我们更加容易的来进行AOP,所以这套机制我们也可以称之为Spring AOP。
2024-08-04 18:29:39
1253
原创 SpringIoC-循环依赖源码解析
1. 什么是循环依赖?很简单,就是A对象依赖了B对象,B对象依赖了A对象。那么循环依赖是个问题吗?如果不考虑Spring,循环依赖并不是问题,因为对象之间相互依赖是很正常的事情。这样,A,B就依赖上了。但是,在Spring中循环依赖就是一个问题了,为什么?因为,在Spring中,一个对象并不是简单new出来了,而是会经过一系列的Bean的生命周期,就是因为Bean的生命周期所以才会出现循环依赖问题。当然,在Spring中,出现循环依赖的场景很多,有的场景Spring自动帮我们解决了,而有的场景
2024-08-02 00:01:02
1356
原创 SpringIoC-依赖注入源码解析
2. Spring中到底有几种依赖注入的方式?2.1 手动注入在XML中定义Bean时,就是手动注入,因为是程序员手动给某个属性指定了值。2.2 自动注入2.2.1 XML的autowire自动注入2.2.2 @Autowired注解的自动注入
2024-07-31 00:00:58
1301
原创 SpringIoC-Bean源码解析
Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的。
2024-07-29 00:03:39
1124
原创 Spring源码架构-核心概念解析
BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点。比如:class,表示Bean类型scope,表示Bean作用域,单例或原型等lazyInit:表示Bean是否是懒加载initMethodName:表示Bean初始化时要执行的方法destroyMethodName:表示Bean销毁时要执行的方法
2024-07-27 17:22:10
1165
原创 手写模拟Spring底层原理-简易实现版
这里实现一个简化版的 Spring 框架的核心功能,模拟应用程序上下文(ApplicationContext)的创建、bean 的定义、依赖注入、作用域管理和后置处理等过程。实际的 Spring 框架在此基础上还有更多功能和复杂性,这里只提供一个基础的理解。通过手写模拟Spring。
2024-07-26 00:02:01
758
原创 Spring框架底层原理脉络梳理
AOP就是进行动态代理,在创建一个Bean的过程中,Spring在最后一步会去判断当前正在创建的这个Bean是不是需要进行AOP,如果需要则会进行动态代理。如何判断当前Bean对象需不需要进行AOP:找出所有的切面Bean遍历切面中的每个方法,看是否写了@Before、@After等注解如果写了,则判断所对应的Pointcut是否和当前Bean对象的类匹配如果匹配则表示当前Bean对象有匹配的的Pointcut,表示需要进行AOP
2024-07-24 00:57:54
926
原创 Java并发可见性、有序性、原子性与JMM内存模型解析
Java线程之间的通信由Java内存模型(Java Memory Model,简称JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在,它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。根据JMM的规定,线程对共享变量的所有操作都必须在自己的本地内存中进行,不能直接从主内存中读
2024-07-22 09:30:00
1065
原创 Java线程池ForkJoinPool原理分析
Fork/Join是一个并行计算的框架,主要就是用来支持分治任务模型的,这个计算框架里的 Fork 对应的是分治任务模型里的任务分解,Join 对应的是结果合并。它的核心思想是将一个大任务分成许多小任务,然后并行执行这些小任务,最终将它们的结果合并成一个大的结果。
2024-07-20 20:01:45
1591
原创 Java线程池ThreadPoolExecutor原理、源码分析
为什么要使用线程池?使用线程池相对于直接创建线程有以下优点:资源管理:线程池可以管理线程的创建和回收,避免频繁地创建和销毁线程,从而减少资源开销。线程复用:线程池中的线程可以被复用,避免了频繁地创建和销毁线程,提高了线程的利用率。控制并发数:线程池可以限制线程的数量,避免线程数过多导致系统资源耗尽,从而避免了系统崩溃或变得不稳定。队列机制:线程池通过使用任务队列来存储等待执行的任务,当线程池中的线程满了时,新的任务可以被放入队列中等待执行,避免了任务丢失。线程生命周期管理:线程池可以对线程的生
2024-07-18 23:53:34
1434
原创 Java阻塞队列BlockingQueue原理解析
阻塞队列 (BlockingQueue)是Java util.concurrent包下重要的数据结构,BlockingQueue提供了线程安全的队列访问方式:当阻塞队列插入数据时,如果队列已满,线程将会阻塞等待直到队列非满;从阻塞队列取数据时,如果队列已空,线程将会阻塞等待直到队列非空。并发包下很多高级同步类的实现都是基于BlockingQueue实现的。
2024-07-17 00:59:25
1305
原创 Java并发容器原理解析
基于CopyOnWriteArrayList实现,其唯一的不同是在add时调用的是CopyOnWriteArrayList的addIfAbsent方法,其遍历当前Object数组,如Object数组中已有了当前元素,则直接返回,如果没有则放入Object数组的尾部,并返回。所以,Java先提供了同步容器供用户使用。利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用,并通过volatile 保证其可见性,当然写操作的锁是必不可少的了。
2024-07-15 23:30:06
1033
原创 AQS之ReentrantLock源码分析
java.util.concurrent包中的大多数同步器实现都是围绕着共同的基础行为,比如等待队列、条件队 列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称 AQS)实现的,AQS是一个抽象同步框架,可以用来实现一个依赖状态的同步器。JDK中提供的大多数的同步器如Lock, Latch, Barrier等,都是基于AQS框架来实现的一般是通过一个内部类Sync继承 AQS将同步器所有调用都映射到Sync对应的方法阻塞等待队列共享/独占。
2024-07-13 16:06:44
1131
原创 JUC并发工具类的应用场景详解
解决多线程竞争资源的问题,例如多个线程同时对同一个数据库进行写操作,可以使用ReentrantLock保证每次只有一个线程能够写入。实现多线程任务的顺序执行,例如在一个线程执行完某个任务后,再让另一个线程执行任务。实现多线程等待/通知机制,例如在某个线程执行完某个任务后,通知其他线程继续执行任务。限流:Semaphore可以用于限制对共享资源的并发访问数量,以控制系统的流量。资源池:Semaphore可以用于实现资源池,以维护一组有限的共享资源。
2024-07-12 09:30:00
1011
原创 Java并发CAS详解与并发安全问题
什么是原子性?事务的一大特性就是原子性(事务具有ACID四大特性),一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。并发里的原子性和原子操作是一样的内涵和概念,假定有两个操作A和B都包含多个步骤,如果从执行A的线程来看,当另一个线程执行B时,要么将B全部执行完,要么完全不执行B,执行B的线程看A的操作也是一样的,那么A和B对彼此来说是原子的。指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2024-07-10 23:58:15
992
原创 JVM内存泄露的ThreadLocal详解
JVM利用设置ThreadLocalMap的Key为弱引用,来避免内存泄露。JVM利用调用remove、get、set方法的时候,回收弱引用。当ThreadLocal存储很多Key为null的Entry的时候,而不再去调用remove、get、set方法,那么将导致内存泄漏。使用线程池+ ThreadLocal时要小心,因为这种情况下,线程是一直在不断的重复运行的,从而也就造成了value可能造成累积的情况。
2024-07-09 23:57:56
826
原创 Java并发/多线程CompleteableFuture详解
JDK1.8 才新加入的一个实现类 CompletableFuture,很好的解决了这些问题,CompletableFuture 实现了 Future, CompletionStage两个接口。实现了Future 接口,意味着可以像以前一样通过阻塞或者轮询的方式获得结果。
2024-07-08 23:57:03
1224
原创 深入理解Java并发、线程与等待通知机制
为什么用户线程又被称为协程呢?内核线程的切换开销是来自于保护和恢复现场的成本,那如果改为采用用户线程,这部分开销就能够省略掉吗?答案还是“不能”。但是,一旦把保护、恢复现场及调度的工作从操作系统交到程序员手上,则可以通过很多手段来缩减这些开销。由于最初多数的用户线程是被设计成协同式调度(Cooperative Scheduling)的,所以它有了一个别名——“协程”(Coroutine) 完整地做调用栈的保护、恢复工作,所以今天也被称为“有栈协程”(Stackfull Coroutine)。
2024-07-06 23:57:49
1154
原创 阿里巴巴Arthas分析调优JVM实战及常量池详解
Arthas 是 Alibaba 在 2018 年 9 月开源的 Java 诊断工具。支持 JDK6+, 采用命令行交互模式,可以方便的定位和诊断线上程序运行问题。Arthas 官方文档十分详细。由于 Arthas 是用 Java 编写的,因此它是跨平台的,可以在 Linux、macOS 和 Windows 上运行。
2024-07-05 00:27:13
1353
原创 JVM调优命令工具使用与调优实战
S0:幸存1区当前使用比例S1:幸存2区当前使用比例E:伊甸园区使用比例O:老年代使用比例M:元数据区使用比例CCS:压缩使用比例YGC:年轻代垃圾回收次数FGC:老年代垃圾回收次数FGCT:老年代垃圾回收消耗时间GCT:垃圾回收消耗总时间。
2024-07-04 00:36:10
1161
原创 高并发场景JVM优化参数配置与垃圾收集底层三色标记算法详解
对于对象年龄应该为多少才移动到老年代比较合适,本例中一次minor gc要间隔二三十秒,大多数对象一般在几秒内就会变为垃圾,完全可以将默认的15岁改小一点,比如改为5,那么意味着对象要经过5次minor gc才会进入老年代,整个时间也有一两分钟了,如果对象这么长时间都没被回收,完全可以认为这些对象是会存活的比较长的对象,可以移动到老年代,而不是继续一直占用survivor区空间。在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。
2024-07-03 00:05:46
986
原创 JVM垃圾收集器Serial、Parallel Scavenge、ParNew、CMS、G1、ZGC详解
如何选择垃圾收集器?1.优先调整堆的大小让服务器自己来选择2.如果内存小于100M,使用串行收集器3.如果是单核,并且没有停顿时间的要求,串行或JVM自己选择4.如果允许停顿时间超过1秒,选择并行或者JVM自己选5.如果响应时间最重要,并且不能超过1秒,使用并发收集器6.4G以下可以用parallel,4-8G可以用ParNew+CMS,8G以上可以用G1,几百G以上用ZGC
2024-07-02 09:30:00
1041
原创 深入解析JVM对象创建与内存分配机制
jdk1.6 update14开始,在64bit操作系统中,JVM支持指针压缩jvm配置参数:UseCompressedOops,compressed--压缩、oop(ordinary object pointer)--对象指针启用指针压缩:-XX:+UseCompressedOops(默认开启),禁止指针压缩:-XX:-UseCompressedOops。
2024-07-01 00:30:00
983
原创 JVM内存模型剖析与参数设置
但在Java 8及以后的版本,永久代被元数据区(Metaspace)取代,元数据区是一块位于本地内存中的区域,与堆内存分开。对象在堆内部挪动的过程其实是复制,原有区域对象还在,一般不直接清理,JVM内部清理过程只是将对象分配指针移动到区域的头位置即可,比如扫描s0区域,扫到gcroot引用的非垃圾对象是将这些对象复制到s1或老年代,最后扫描完了将s0区域的对象分配指针移动到区域的起始位置即可,s0区域之前对象并不直接清理,当有新对象分配了,原有区域里的对象也就被清除了。本地方法执行期间,栈帧会保持在栈顶。
2024-06-30 09:15:00
1580
原创 深入JDK源码-剖析JVM的类加载机制
commonLoader:Tomcat最基本的类加载器,加载路径中的class可以被Tomcat容器本身以及各个Webapp访问;catalinaLoader:Tomcat容器私有的类加载器,加载路径中的class对于Webapp不可见;sharedLoader:各个Webapp共享的类加载器,加载路径中的class对于所有Webapp可见,但是对于Tomcat容器不可见;
2024-06-29 09:30:00
1038
原创 MySQL 8.0新特性详解
从上图可以看出SQL及索引的优化效果是最好的,而且成本最低,所以工作中我们要在这块花更多时间。配置文件my.ini(windows)或my.cnf(linux)的全局参数:下面参数都是服务端参数,默认在配置文件的 [mysqld] 标签下连接的创建和销毁都需要系统资源,比如内存、文件句柄,业务说的支持多少并发,指的是每秒请求数,也就是QPS。一个连接最少占用内存是256K,最大是64M,如果一个连接的请求数据超过64MB(比如排序),就会申请临时空间,放到硬盘上。
2024-06-28 00:12:19
751
原创 [MySQL] Innodb底层原理与MySQL日志机制深入剖析
注意:如果要恢复大量数据,比如程序员经常说的删库跑路的话题,假设我们把数据库所有数据都删除了要怎么恢复了,如果数据库之前没有备份,所有的binlog日志都在的话,就从binlog第一个文件开始逐个恢复每个binlog文件里的数据,这种一般不太可能,因为binlog日志比较大,早期的binlog文件会定期删除的,所以一般不可能用binlog文件恢复整个数据库的。redo log 从头开始写,写完一个文件继续写另一个文件,写到最后一个文件末尾就又回到第一个文件开头循环写,如下面这个图所示。
2024-06-27 00:10:19
1415
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人