- 博客(66)
- 收藏
- 关注
原创 Kafka权威指南(第2版)读书笔记
一个应用程序会在很多情况下向Kafka写入消息:记录用户的活动(用于审计和分析)、记录指标、记录日志、记录从智能家电收集到的信息、与其他应用程序进行异步通信、缓冲即将写入数据库的数据,等等。如果消息写入成功,就返回一个RecordMetaData对象,其中包含了主题和分区信息,以及消息在分区中的偏移量。不管是把Kafka作为消息队列、消息总线还是数据存储平台,总是需要一个可以往Kafka写入数据的生产者、一个可以从Kafka读取数据的消费者,或者一个兼具两种角色的应用程序。
2025-01-12 21:29:23 257
原创 Redis 5设计与源码分析读书笔记
Redis源代码主要存放在src文件夹中,作者没有整理这些文件,统一存放到了一个文件夹中,如图所示。其中server.c为服务端程序,redis-cli.c为客户端程序。Redis源代码的核心部分主要如下。基本的数据结构动态字符串sds.c整数集合intset.c压缩列表ziplist.c快速链表quicklist.c字典dict.cStreams的底层实现结构listpack.c和rax.cRedis数据类型的底层实现Redis对象object.c。
2025-01-01 21:56:37 982
原创 操作系统导论读书笔记
例如,给定一组可能的程序要在CPU上运行,操作系统应该运行哪个程序?操作系统中的调度策略(scheduling policy)会做出这样的决定,可能利用历史信息(例如,哪个程序在最后一分钟运行得更多?通过让一个进程只运行一个时间片,然后切换到其他进程,操作系统提供了存在多个虚拟CPU的假象。进程的非正式定义非常简单:进程就是运行中的程序。,它让操作系统能够停止运行一个程序,并开始在给定的CPU上运行另一个程序。潜在的开销就是性能损失,因为如果CPU必须共享,每个进程的运行就会慢一点。
2024-12-25 21:49:10 171
原创 Java并发编程实战读书笔记
Java内存模型要求,变量的读取操作和写入操作都必须是原子操作,但对于非volatile类型的long和double变量,JVM允许将64位的读操作或写操作分解为两个32位的操作。当读取一个非volatile类型的long变量时,如果对该变量的读操作和写操作在不同的线程中执行,那么很可能会读取到某个值的高32位和另一个值的低32位[插图]。因此,即使不考虑失效数据问题,在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非用关键字volatile来声明它们,或者用锁保护起来。
2024-12-12 12:55:08 704
原创 ES中间件学习书籍阅读笔记
数据索引化指的是数据在写入搜索引擎(本书中主要指Elasticsearch)的过程中,扫描文档中的每一个词项,结合分词器和词典对必要的词项建立倒排索引,同时指明该词项在文章中出现的次数和位置。特点如下:对外提供服务的是整个集群,一个集群可以由多个节点组成,不同的节点根据用途不同会划分成不同的角色,每个节点的数据会划分出多个索引,一个索引对应多个分片数据。如果用MySQL做对比的话如图所示(感觉意思上是仅供参考的,也不是完全对应的)
2024-12-02 22:02:31 411
原创 Tomcat源码学习
配置文件的每一个标签就对应这一个类,创建对象封装好标签配置的属性内容,Host里面并不会在此时扫描加载Context应用组件(只是单纯的解析xml中的架构,按照层次封装到Catalina对象中)日志阀门,可以用来记录请求的日志,阀门机制是Tomcat中,控制数据流向处理的核心,利用阀门来做类似Filter的预处理,阀门属于一个责任链的模式。容器接口,上述的Host,Engine,Context,Wrapper等都是他的实现,容器可以继续添加子组件,并且容器中有一个特性是拥有一个管道。
2023-07-18 10:56:59 419
原创 Spring源码学习-SpringBoot原理解析
这里的主流程就是通过run方法去创建IOC容器,然后开始容器刷新,过程中就会通过之前的配置类创建启动Tomcat的web服务(在onRefresh方法启动tomcat),然后DispatcherServlet初始化到容器中在注册进入tomcat,之后DispatcherServlet开始初始化,继续调用容器刷新的后续步骤。会通过生命周期初始化九大组件,在通过Tomcat启动的钩子会初始化父子容器,将整个的容器启动起来,,随后注册到了Tomcat里面,之前的博客文章讲过,同时导入了三种不同的内嵌式的服务器,
2023-07-18 10:53:07 551
原创 Spring源码学习-MVC的WEB源码解析
通过servlet规范中的init初始化方法调用过来(tomcat进行触发),在的方法中的//先尝试获取一下之前的父容器 WebApplicationContext rootContext = WebApplicationContextUtils . getWebApplicationContext(getServletContext());= null) {//当前的web-ioc容器 wac = this . webApplicationContext;if(!
2023-07-18 10:52:12 849
原创 Spring源码学习-SPI机制与Tomcat结合SpringMVC原理剖析
属于Java的Servlet(servlet是接口,其余是抽象类)Servlet定义了最初始重要的五个方法留给子类去实现定义了一个简单版本的servlet但是无法使用,允许你继承实现这个接口去扩展(init方式是空的)没有提供init初始化方法的实现,把service处理进一步细化,分为get,post等等属于Spring的Servlet重写了init方法,并且继续给子类留下了模板方法由子类去任意发挥重写了上面留下的模板方法initServletBean,在这个里面调用了。
2023-07-18 10:51:17 588
原创 Spring源码学习-Aop原理,事件机制
通过操作代理类,先把所有的增强器再转变为真正的方法拦截器增强器只是保存了切面执行方法的一些信息,转为拦截器才能真正执行目标的方法接下来是责任链的设计模式,在方法执行的前后执行对应的通知方法(构造成为了一个拦截器链list)把构造好的链还有很多其他信息传进去,构造一个类,并调用它的proceed方法,在此步骤拦截器生效了其内包含一个。
2023-07-18 10:50:02 629
原创 Spring源码学习-后置处理器,Autowired实现原理
给创建好的bean实例进行普通属性的赋值这个就是用来完成Autowired注解能够自动装配的bean后置处理器这个方法初始化了一个set,用来存放需要解析的自动装配注解,里面就包括Autowired,Value和Inject等,之后Spring拿到这些元数据信息直接反射赋值后置处理器BeanFactory的后置处理器BeanDefinitionRegistryPostProcessor在容器刷新12步骤中由方法调用,是bean定义信息注册中心的增强,先去执行实现了PriorityOrdered接
2023-07-18 10:44:02 419
原创 Spring源码学习-核心注解,架构以及整体流程
这是spring的关键类,属于是spring的’档案馆’,他继承和实现一系列的接口并且通过组合的方式,保存了spring的bean实例信息(通过多个ConcurrentHashMap),后续spring拿到这些读取到的bean图纸信息,再根据信息去创建相应的Bean。它是spring自己定义的一个资源抽象接口,表示所有需要加载到spring的bean容器中的资源,来自于xml以及注解的bean,甚至是网络和本地磁盘当中,都可以用它表示。读取Bean信息的策略接口,他是Bean信息的一个读取器,他有。
2023-07-18 10:36:09 557
原创 JVM垃圾回收篇之垃圾收集器
吞吐量:程序的运行时间 《程序的运行时间十内存回收的时间 )垃圾收集开销:吞吐量的补数,垃圾收集器所占时间与总时间的比例。暂停时间: 执行垃圾收集时,程序的工作线程被暂停的时间。收集频率:相对于应用程序的执行,收集操作发生的频率。内存占用: java 堆区所占的内存大小。快速: 一个对象从诞生到被回收所经历的时间。串行回收器:Serial,Serial Old并行回收器:ParNew,Parallel Scavenge,Parallel Old并发回收器:CMS,G1。
2023-05-30 17:42:02 956
原创 JVM垃圾回收篇之相关概念和算法
垃圾就是指在运行程序中没有任何指针指向的对象,这个对象就是需要被回收掉的垃圾,如果不及时进行清理,越积越多就会导致内存溢出.
2023-05-30 17:40:26 910
原创 JVM之栈和堆运行时内存深度剖析
通过类加载器可以实现非常绝妙的插件机制.自定义的类加载器能够实现应用隔离,tomcat和spring都在内部实现了自定义类加载器,这样的机制比c/c++要优秀太多,自定义的类加载器通常都需要继承自抽象类ClassLoader在加载器加载类的时候,如果加载器有父类(一般是组合定义为父类),先让父类去加载,一层层往上找,如果父类都没有再由自己加载,否则由某一个父类加载进来.//转换为以文件路径表示的文件 String filePath = classToFilePath(name);
2023-05-30 17:39:48 1757
原创 JVM之对象内存布局和编译器
如果内存是规整的,那么虚拟机将采用的是指针碰撞法(Bump The Pointer)来为对象分配内存。意思是所有用过的内存在一边,空闲的内存在另外一边,中间放着一个指针作为分界点的指示器,分配内存就仅仅是把指针向空闲那边挪动一段与对象大小相等的距离罢了。如果垃圾收集器选择的是Serial、ParNew这种基于压缩算法的,虚拟机采用这种分配方式。一般使用带有compact(整理)过程的收集器时,使用指针碰撞。
2023-05-30 17:39:37 823
原创 JVM之类的初始化与类加载机制
通过类加载器可以实现非常绝妙的插件机制.自定义的类加载器能够实现应用隔离,tomcat和spring都在内部实现了自定义类加载器,这样的机制比c/c++要优秀太多,自定义的类加载器通常都需要继承自抽象类ClassLoader在加载器加载类的时候,如果加载器有父类(一般是组合定义为父类),先让父类去加载,一层层往上找,如果父类都没有再由自己加载,否则由某一个父类加载进来.//转换为以文件路径表示的文件 String filePath = classToFilePath(name);
2023-05-30 17:38:31 690
原创 JVM-基础知识
魔数每个class文件开头的4个字节的无符号整数称为魔数他的唯一作用是确定这个文件是否为一个能被虚拟机接受的有效合法的Class文件(魔数就是Class文件的标识符)魔数值固定为0xCAFFBABE不会改变之所以用魔数不用扩展名是出于安全方面的考虑(因为扩展名可以随意的更改)Class文件版本排列在magic后的第5个和第6个字节所代表的含义就是编译的副版本号minor_version,而第7个和第8个字节就是编译的主版本号major_version。
2023-05-30 17:32:49 912
原创 Redis缓存双写一致性
先删除缓存的值在更新数据库,有可能缓存击穿打满MySQL,并且也避免不了数据不一致的问题如果业务应用中读取数据库和写缓存的时间不好估算,那么延迟双删中的等待时间就不好设置。
2023-03-10 17:18:05 1439 1
原创 redis杂谈
首先肯定是用Redis,redis天生单线程高可用,可以无锁实现加锁的代码效果,其次红包数值存储应该用list数据结构(set不允许重复,但是红包金额能够重复),并且list的pop出栈操作自动是原子性的不需要加锁,其次需要存储用户的抢红包记录。可以用hash结构.最后如果这些需要持久化的话可以最后开启异步线程同步到MySQL或者消息队列.用新浪微博的短链接算法来生成对应的短链接地址字符串,然后存入redis的hash结构当中。
2023-03-10 17:16:34 113
原创 ReentrantLock、ReentrantReadWriteLock、StampedLock解读
ReentrantReadWriteLock本质上是一种悲观锁,如果有线程正在读,写线程需要等待读线程释放锁后才能获取写锁,ReadWriteLock读的过程中不允许写,只有等待线程都释放了读锁,当前线程才能获取写锁,也就是写入必须等待,这是一种悲观的读锁.代码中声明了一个volatile类型的cacheValid变量,保证其可见性。如果违背锁降级的步骤。...
2022-07-30 16:25:47 442
原创 AQS深度剖析
AQS使用一个volatile的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作将每条要去抢占资源的线程封装成一个Node节点来实现锁的分配,通过CAS完成对State值的修改。,他是公平锁加锁时判断等待队列中是否存在有效节点的方法,如果已经存在节点了,公平锁会去直接排队,非公平锁会直接尝试去抢占锁,但是一旦线程进入了fifo队列,就会遵循先进先出的原则,要有先来后到。CLH队列(三个大牛的名字组成),为一个双向队列,注意他是先进先出的队列。那些锁的实现基本都用到了他。..
2022-07-30 16:24:36 480
原创 Synchronized与锁升级
java的线程是映射到操作系统原生线程之上的,如果要阻塞或唤醒一个线程就需要操作系统介入,需要在户态与核心态之间切换,这种切换会消耗大量的系统资源,因为用户态与内核态都有各自专用的内存空间,专用的寄存器等,用户态切换至内核态需要传递给许多变量、参数给内核,内核也需要保护好用户态在切换时的一些寄存器值、变量等,以便内核态调用结束后切换回用户态继续工作.在Java早期版本中,synchronized属于重量级锁,效率低下,因为监视器锁(monitor)是依赖于底层的操作系统的MutexLock来实现的。...
2022-07-21 11:15:03 178
原创 Java对象内存布局和对象头
java-XX这个可以显示JVM自带的的一些默认参数出来64位的JVM自己默认就开启了压缩指针默认是这个参数-XX。
2022-07-21 11:11:54 661
原创 ThreadLocal类详细剖析
深度解析一下子,基础的就略过去不讲了,想知道基础用法的请自行百度ThreadLocal并不解决线程间共享数据的问题ThreadLocal适用于变量在线程间隔离且在方法间共享的场景ThreadLocal通过隐式的在不同线程内创建独立实例副本避免了实例线程安全的问题每个线程持有一个只属于自己的专属Map并维护了ThreadLocal对象与具体实例的映射,该Map由于只被持有它的线程访问,故不存在线程安全以及锁的问题。...
2022-07-15 18:03:20 900
原创 原子操作18个类详解
数组类型的原子类操作方法都需要传入数组的下标值 构造的时候不赋值默认就是基本类型的初始值,比如int类型就是0引用类型原子类引用类和邮戳类CAS的基础介绍解决引用对象是否修改过的问题对象的属性修改原子类达成的效果: 以一种线程安全的方式操作非线程安全对象内的某些字段AtomicReferenceFieldUpdater原子操作增强类LongAdder与LongAccumulatorLongAdder必须从0开始,而且只有加减法 具有非常大的局限性,但是LongAccumulator是调
2022-07-14 18:42:37 1096
原创 CAS和Unsafe类
CAS是JDK提供的非阻塞原子性操作,它通过硬件保证了比较-更新的原子性。它是非阻塞的且自身原子性,也就是说这玩意效率更高且通过硬件保证,说明这玩意更可靠。CAS是一条CPU的原子指令(cmpxchg指令),不会造成所谓的数据不一致问题,Unsafe提供的CAS方法(如compareAndSwapXXX)底层实现即为CPU指令cmpxchg。执行cmpxchg指令的时候,会判断当前系统是否为多核系统,如果是就给总线加锁,只有一个线程会对总线加锁成功,加锁成功之后会执行cas操作,也就是说CAS的原子性
2022-07-14 18:40:45 466
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人