- 博客(141)
- 收藏
- 关注
原创 带着问题看源码 —— BeanFactory和ApplicationContext的区别
BeanFactoryspring容器的底层接口,可以根据bean定义的信息,返回对应的实例对象。提供了最简单的容器获取和实例化对象的功能。ApplicationContext我们从继承图上可以看到ApplicationContext继承自BeanFactory,所以BeanFactory有的功能,都包含其中,并且对于比BeanFactory,提供了更加丰富的功能。增加那些具体的实现了我们可以总ApplicationContext的描述中看到/* <p>An ApplicationC
2022-05-28 20:50:26
929
原创 带着问题看源码 —— BeanFactory和FactoryBean
BeanFactory说明: spring容器的底层接口,可以根据bean定义的信息,返回对应的实例对象,支持整个sring的生命周期流程。提供的方法:FactoryBean说明: 就是一个简单的对象工程,实现了此接口的方法在整个bean周期中,可以使用自定义的方式来创建对象,而不需要进行默认的bean流程的创建。提供的方法使用public class MyFactoryBean implements FactoryBean<Person> { @Overri
2022-05-22 20:39:51
955
原创 3台linux安装hadoop机群
准备工作:有3台虚拟机,主机名为node1、node2、node3,并且node1为主节点第一步:上传压缩包并解压将压缩的hadoop包上传到第一台服务器并解压;第一台机器执行以下命令cd /usr/soft/tar -xzvf hadoop-3.1.4.tar.gz -C /usr/install第二步:查看hadoop支持的压缩方式以及本地库第一台机器执行以下命令cd /usr/install/hadoop-3.1.4/bin/hadoop checknative如果出
2021-12-11 21:14:43
2555
原创 并发编程的Bug源头与解决思路
因为现代计算机中CPU、内存、I/O操作存在性能差异问题,而一个程序的完整执行往往需要CPU、内存、I/O操作共同完成;例如进行I/O操作时,此时CPU就是空闲状态,浪费其性能,所以需要通过并发程序来提升硬件设备的使用率,提高程序性能。bug源头一:缓存导致的可见性问题现代计算机多核CPU都是标配,普通个人电脑4核、8核都很常见,更不用现代服务器的16核、32核等。因为每个CPU都有自己的高速缓存(1、2、3级缓存),这就会导致我们的线程在处理共享变量时,因为操作的数据在各自CPU的高速缓存中,导致可见
2021-08-02 21:27:59
936
原创 kafka副本机制详解
副本机制(Replication)又称为备份机制,通常是指在分布式系中在多台机器中存储相同的数据进行备份的机制,副本机制只要有3个好处。提供数据冗余:即使部分机器出现故障,系统仍然可以提供服务,增加了整体的可用性和数据持久化。提供高伸缩性:支持横向扩展,可以通过增加副本数,来提供读性能。改善数据局部性:允许将数据放入与用户地理位置相近的地方,从而降低系统延时。但是kafka的副本机制只提供了第一个特点,即提供数据冗余的特性。kafka副本定义在kafka中一个主题下面可以有多个分区(par
2021-07-24 11:37:55
1673
2
原创 kafka消费组重平衡
kafka消费组Consumer Group,是 Kafka 提供的可扩展且具有容错性的消费者机制,一个消费组内可以有一到多个消费实例(Consumer Instance),共享一个id,这个id就是Group ID。Consumer Group下有一个或多个单独的Consumer实例,这个Consumer可以是单独的进程,也可以是一个进程下的多个线程。Group ID是一个字符串,用来表示唯一的消费组。Consumer Group下所有实例订阅的主题的单个分区,只能分配给组内的某个 Consum
2021-07-03 15:31:10
1293
原创 kafka配置详解
broker端参数log.dirs:指定broker端使用那些若干文件来进行日志存储,没有默认值,必须要进行指定。配置格式为csv的样式,如:/home/kafka1,/home/kafka2,/home/kafka3,并且可以将不同的目录挂在不同的磁盘下面,这样可以有如下好处提升读写性能可以实现故障转移,在kafka1.1之后,单个磁盘损坏时,坏掉的磁盘数据会自动转换到正常的磁盘,继续提供服务。log.dir:同log.dirs参数配置效果一样,只不过只能配置单个路径。zookeepe
2021-06-27 14:52:17
2838
1
原创 kafka如何保证消费不丢失
消息可靠性维度消息的可靠性性一般需要从三个维度进行考量。分别是生产端、服务端、消费端。发送端可靠性:生产者需要确保消费发送到了服务端机器上。服务端存储可靠性:服务端需要保证消息的持久化不丢失。消费可靠性:消费端需要确认每条消息都被成功进行消费。producer可靠性对于kafka生产端来说,发送消息主要有两类API可以调用,分别是producer.send(msg)和producer.send(msg,callback)。producer.send(msg):俗称“发后即忘”,不管消息有
2021-06-13 12:51:54
1932
原创 kafka日志详解
kafka中消息是通过主题来进行区分的,一个主题会有多个分区,每个分区会有多个副本,每个副本都会对应有一个log日志进行存储,每个log日志会对应有多个logSegment日志段,每个logSegment包含一个日志文件(.log后缀)和两个索引文件( .index和 .timeindex后缀);按照是否再有消息写入分为活跃日志分段(activeSegment)和非活跃日志分段logSegment;日志文件的命令,都是基于基准偏移量(baseOffset)进行命名的,名称固定为20位数字,没有达到的位数用0
2021-06-02 21:17:44
3158
3
原创 限流算法总结
计时器限流计数器是一种比较简单的限流算法,用途比较广泛,在接口层面,很多地方使用这种方式限流。在一段时间内,进行计数,与阈值进行比较,到了时间临界点,将计数器清0 。优点:实现简单缺点:存在临界问题,如在12:01:00到12:01:58这段时间内没有用户请求,然后在12:01:59这一瞬时发出100个请求,OK,然后在12:02:00这一瞬时又发出了100个请求,那这某个1秒区间内,超过了每秒100次的请求阈值。代码实现public class CounterLimiter { pr
2021-04-24 19:32:58
893
原创 java线程详解
线程状态在java.lang.Thread.State这个枚举类中定义了6种线程,如下图所示New:尚未启动的线程的线程状态。Runnable:可运行线程的线程状态,等待CPU调度(分两种情况,正在运行,另一种等待cpu来执行)。Blocked:线程阻塞等待监视器锁定的线程状态。处于synchronized同步代码块或方法中被阻塞。Waiting:等待线程的线程状态。下列不带超时的方式:Object.wait、Thread.join、LockSupport.parkTimed Waiting
2021-04-11 15:54:38
819
原创 MAC地址,IP地址以及ARP协议
MAC地址MAC地址是以太网的MAC子层所使用的地址,当多个主机连接在同一个广播信道上,要想实现两个主机之间的通信,则每个主机都必须有一个唯一的标识,即一个数据链路层地址;在每个主机发送的帧中必须携带标识发送主机和接收主机的地址。由于这类地址是用于媒体接入控制MAC(Media Access Control),因此这类地址被称为MAC地址,MAC地址一般被固化在网卡(网络适配器)的电可擦可编程只读存储器EEPROM中,因此MAC地址也被称为硬件地址,有时也被称为物理地址。一般情况下,用户主机会包含两个
2021-04-10 15:49:25
2390
原创 计算机网络体系结构
常见的网络分层在计算网络世界里,常见的网络分层结构主要有两种,一个中就是OSI的标准网络7层模型,和实际使用的TCP/IP协议群。分层的好处“分层”可将庞大而复杂的问题,转化为若干较小的局部问题,而这些较小的局部问题就比较易于研究和处理。每层解决的问题:物理层:解决使用何种信号来传输比特的问题数据链路层:解决分组在一个网络(或一段链路)上传输的问题网络层:解决分组在多个网络上传输(路由)的问题会话层:解决进程之间进行会话问题表示层:解决通信双方交换信息的表示问题运输层:解决进程之间
2021-03-24 22:23:46
890
原创 提高思想,写出好代码
内功心法要想写出好的代码,首先我们要有这个认知。在写代码的时候,不能以完成功能需求为目标。个人认为以完成功能需求为目标,永远也写不出优雅的代码,只能是一个需求搬运工。有的时候我们需要多多思考,在看到前人代码时,是否有可以优化的地方,是否有更优雅的写法。从心里不要仅仅把写代码是简单的完成工作,这样只是简单的重复劳动,永远也不会有进步。之前看过一句觉得说的特别好,你写的每一行代码,都是你的名片。 我认为写好代码的第一步,一定是有这个想法,有了想法,才能不是被动的完成任务去写你的代码。人没有梦想和咸鱼有什么区别
2021-03-07 15:28:01
907
2
原创 数据结构之—— 图
定义是一种非线性表结构数据。图中的每个元素称为顶点(vertex),图中的顶点与其他任意顶点建立的连接称为边(edge);。和顶点相连接的边的条数,称为度(degree)。对于图来说,又可以分为有向图和无向图。有向图,顾名思义就是带有方向的图;在有向图中,又将度细分为出度(Out-degree)和入度(In-degree)入度:表示有多少条边指向这个顶点。出度:表示有多少条边以这个顶点为起点,指向外部。无向图,就是没有方向的图;带权图(weighted graph):就是边上增加权重分数的一种
2021-02-21 14:33:13
994
原创 Java SPI机制
定义SPI全称为Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,通过SPI实现接口编程,通过 SPI 服务加载机制进行服务的注册和发现,可以有效的避免在代码中将服务提供者写死。从而可以基于接口编程,实现模块间的解耦,方便我们在代码中进行扩展实现。实现步骤在 META-INF/services/ 目录中创建以接口全限定名命名的文件。 文档的内容,是每个接口的实现类全类名。 使用 ServiceLoader 类动态加载配置文件中的具体实现
2021-02-17 12:05:35
907
1
原创 数据结构源头 —— 数组和链表
一、数组定义:是一种线性表结构数据,它用一组连续的内存空间来存储具有相同数据结构的数据。线性表结构:数据排成一条线的数据结构,只有前后两种方法可以操作,常见的线性表结构数据有:数组、链表、栈、队列。 连续的内存空间:数组在申请内存地址时,内存空间必须是连续的,这样数组在随机访问某个数据的时间复杂度为O(1),但因为为了保存连续的内存结构其新增、修改时,存在挪动数据,性能低效。如何提供随机访问一个数组中的元素的时间复杂度为O(1)?如下图所示,一个int需要占用4字节来存储,每个存储空间都会被分配
2021-01-24 21:09:53
918
原创 数据结构之 —— 堆
一、定义堆是一种特殊的树结构,堆是一个完全二叉树,并且堆中的每个节点必须大于等于(或小于等于)其子树中的每个节点的值。对于大于等于其左右节点的堆称为“大顶堆”;小于等于其左右节点的堆称为“小顶堆”。二、存储方式因为堆是一个完全二叉树的结构,所以可以直接使用数组来进行保存数据,从数组的下标1开始存储数据节点,左子树存储的位置就是2*i的位置,右子树的位置就是2*i + 1的位置进行存储。三、堆提供的操作向堆中添加一个元素:插入数据后,为了保持堆的特性,需要对现有的结构进行调整,
2021-01-18 20:39:28
870
原创 2020年度总结
不知不觉2020年已经离我们而去,新的一年已经到来,回顾过去的2020年自己有做的好的地方,也有做的不足之处;在这里想总结一个自己的2020年,随便展望一下自己的2021年,给自己订个小目标。在学习上,在2020年的上半年的时间,投入的学习时间并不是很满意,主要有两个方面:在学习时间上投入的不足,主要是因为疫情在家期间,基本就是荒废的,然后疫情回来工作后,工作上的事情比较多,每天加班到很多。还有就是心态上的变化,变的有了一些懒惰的心里,导致没有在学习上花费的时间不足;另一个方面就是学习效率不高,总是在追
2021-01-02 19:30:38
838
原创 5种常见排序算法
一、冒泡排序(Bubble Sort)只会操作相邻的两个数据,每次比较相邻的数据大小,不符合要求,就进行一次数据移动,一次冒泡会至少让一个元素处于正确的位置,冒泡n次后,数据符合要求。冒泡排序只会移动相邻元素的变动。是否是稳定排序:是是否是原地排序:是最好情况时间复杂度:O(n)最坏情况时间复杂度:O(n^2)平均情况时间复杂度:O(n^2)代码实现:public static void bubbleSort(int[] a) { for (int i =
2020-12-28 23:19:36
2781
原创 详解TCP协议
一、定义传输控制协议(TCP)是Internet一个重要的传输层协议。TCP提供面向连接、可靠、有序、字节流传输服务。应用程序在使用TCP之前,必须先建立TCP连接;TCP通过校验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。二、如何保证可靠性在TCP的传输中,当发送端数据到达接受主机时,接收端主机回返回一个已收到的消息通知,这个消息就叫做确认应答(ACK);在一定时间内没有收到确认应答,发送端就会认为数据丢失,会进行数据的重发。为了防止接受重复的
2020-12-19 15:58:20
393
1
原创 redis使用中的四大问题
一、数据不一致定义:主要就是指缓存中的数据和数据库中的数据不一致情况。产生的原因:当有数据修改时,无论是先修改数据库的值,还是先修改缓存中的值,都会发生数据不一致的情况,更好的解决方式,就是先更新数据库的值,在进行删除操作,但是这样的操作也会造成数据的不一致问题。主要是在两个方面,一个就是不能保证操作的原则性时,可能出现缓存不一致的情况,另一种就是在并发场景下,出现缓存不一致。原子性问题:先删除缓存,再更新数据库:当我们的删除缓存成功后,这时写入数据库失败,当我们再来请求这个数据时,首先从缓
2020-12-09 22:14:04
263
原创 redis—底层数据结构详解
一、redisObject在redis中基本的结构对象我们称之为RedisObject,其源码如下:typedef struct redisObject {unsigned type:4;unsigned encoding:4;unsigned lru:LRU_BITS;int refcount;void *ptr;} robj;其中:type:表示值的数据类型。 encoding:值的编码方式,就是其底层的数据结构实现。 lru:记录了对象最后一次被访问的时间,用于淘
2020-11-21 22:14:05
306
原创 利用redis实现分布式锁
一、基于单个redis节点实现的分布式锁因为redis是单线程程序,可以天然的保证线程安全,只要我们的命令是单条命令,就可以保证操作的安全性,而redis中给我们提供了setnx key value命令,setnx命令的作用就是当我们的redis中没有这个key的键值队时,就会创建这个键值队的值,如果已经有了这个key就不作操作;所以我们可以使用setnx命令来实现我们的分布式加锁操作。但setnx的命令会存在风险setnx没有给锁设置过期时间,一旦客户端故障没有进行释放锁操作,就将导致没有办法在获
2020-11-15 16:44:52
214
原创 redis性能优化骚操作 —— 绑核
一、现代CPU模式现代一个CPU中,可以有多个运行核心(称之为物理核),每个物理核都有自己独立的一级缓存(L1)和二级缓存(L2)。并且每个物理核一般会有两个超线程(称之为逻辑核);同一个物理核下的两个逻辑核同享L1和L2缓存。并且现在机器主流都是多CPU处理器结构(CPU Socket),每个CPU拥有自己的L1和L2以及L3级缓存和自己所管理的内存空间;不同处理器之间通过总线进行连接。一台机器的cpu构造如下图所示:二、cpu多核对redis的影响因为我们的cpu存在上下文切换(cont
2020-11-10 23:10:25
939
原创 redis——内存满了应该怎么办?
我们的redis使用的时内存空间来存储数据的,但是内存空间毕竟有限,随着我们存储数据的不断增长,当超过了我们的内存大小时,redis会怎么处理呢?今天就来聊聊redis的缓存淘汰策略。一、redis的缓存淘汰策略在redis中,一种有8种对应的缓存淘汰策略根据是否进行数据淘汰可以分为:不淘汰的数据策略(noeviction)和7种淘汰数据策略。在淘汰的数据策略中,又可以根据淘汰数据的样本分为:在设置了过期时间的数据中进行淘汰数据的四种策略(volatile-ttl,volatile-
2020-11-05 22:15:20
873
原创 redis集群架构的演进之路
一、redis的主从架构一开始我们的业务量不大时,一个redis节点就能满足我们的业务需求,当我们的业务量不断上涨,单台redis节点已经不能满足我们的业务需求时,这个时候redis的主从结构就出现了。redis主从结构解决的问题:redis可以部署为一个主节点,多个从节点,从节点提供读服务,主节点提供写服务,将我们的业务进行读写分离。redis如何进行主从同步,其第一次进行主从同时时,其流程如下图:首先从节点执行slaveof ip port命令,让自己成为192.168.1.1的从节
2020-10-28 22:24:58
304
原创 redis的持久化 —— RDB和AOF
一、AOF1.1 redis如何通过AOF进行写日志redis AOF采用的是写后操作,也就是数据先写入内存中,再写入到AOF日志文件中。采用这样的好处是,可以避免当次操作,因为写日志而降低性能,采用写后操作,可以在写入日志时,不需要校验命令的正确性,保证写入到日志的命令都是正确的。坏处是:虽然没有降低当次请求的操作,但是写入日志还是在主线程中进行的,所以会影响到下次命令的性能。1.2AOF日志记录什么在AOF日志中记录的就是操作的命令信息,例如一个操作 set hello wor.
2020-10-24 20:27:05
154
原创 为什么redis这么快
一、使用内存进行存储我们都知道redis是使用内存来进行数据的存储,这也是为什么redis的访问速度要远远快于mysql的主要原因,因为是使用内存存储数据,可以避免频繁的进行写盘操作,大大降低响应时间:内存器 随机访问延迟 Memory 100ns SSD 150us HDD 10ms 二、单线程结构多线程一定比单线程快嘛?虽然我们知道当我们使用多线程的时候,可以加快我们的系统访问,但是在使用多线程的过程中,对于共享变量的访问,会将多线程操作变成单线程
2020-10-19 22:22:29
5446
1
原创 float精度丢失问题详解
今天运行一个程序,发现一个很有意思的情况,可以看到代码如下所示public static void main(String[] args) { float a = 1; for (int i = 0; i<20000000; i++) { a++; } System.out.println(a);}public static void main(String[] args) { floa
2020-08-29 12:26:43
4274
原创 如何写出好代码
要想写出好代码,我们首先要知道,什么样的代码是好代码,代码的批判标准有哪些?1、可维护性(maintainability):易维护代码:在不破坏原有代码设计、不引入新的 bug 的情况下,能够快速地修改或者添加代码;代码不易维护:修改或者添加代码需要冒着极大的引入新 bug 的风险,并且需要花费很长的时间才能完成。2、可读性(readability):软件设计大师 Martin Fowler 曾经说过:“Any fool can write code that a computer can unde
2020-08-10 21:43:29
464
原创 spring源码解读(三) —— 编写自定义标签
在spring中,我们经常使用spring中给我提供的便签来完成很多功能,有的时候当spring提供的标签无法满足我们的开发时,这是,我们就可以使用自定义标签来扩展我们的程序,下面我们就来看看如何使用自定义标签功能。1.首先定义一个实体,用来接收自定义的配置标签public class User { private String userName; private String email; // 省略get/set方法}2.定义一个xsd文件描述组件内容名
2020-07-19 18:00:10
142
原创 spring源码解读(二) —— 如何解析bean元素
bean元素是我们在xml配置文件中,使用到最多的一个元素,当我们在xml中配置了一个bean元素之后,spring帮助我们做了什么事呢?让我们跟进spring的源码来一探究竟。实现配置一个简单的xml文件:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001
2020-07-04 11:08:53
336
原创 spring源码解读(一) —— xml头文件的作用
Spring的核心功能之一就是IOC,也就是一个容器管理功能,那么我们怎么将我们定义的bean注入的Spring容器中,spring中,提供了xml文档,我们将我们的bean定义在xml中,spring中就可以管理我们的对应,xml定义如下:<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://
2020-06-27 20:12:42
920
原创 与架构师一步之差 —— 注解和反射
一、注解简介:注解(Annotation)是java5引入的一种代理辅助工具,它的核心作用是对类、方法】变量、参数和包进行标注,通过反射来访问这些标注信息,以此在运行时改变所注解对象的行为。java中的注解由内置注解和元注解组成。元注解:元注解只要包括四个,用来修饰注解的作用。@Retention定义注解的生命周期:【source -> class -> runtime】主要是作用在runtime时。 @Documented文档注解,会被javadoc工具文档化 @Inherit
2020-06-14 19:47:35
160
原创 一文读懂什么是JMS规范
一、JMS是什么java消息服务(java message service即JMS)应用程序接口是一个java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。java消息服务是一个与具体平台无关的API。对应的API接口就在javax.jms包下面:二、JMS的对象模型ConnectionFactory 连接工厂 Connection 连接 Session 会话 Destination 目.
2020-05-24 11:15:51
461
原创 如何设计消息中间件
什么是消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流;并基于数据通信来进行分布式系统的集成;通过提供消息传递和消息排队模型,它可以在分布式环境下扩展进程间的通信;应用场景:跨系统数据传递,高并发流量削峰、数据异步处理等。常用的消息中间件:ActiveMQ、RabbitMQ、kafka、RocketMQ消息中间件核心设计本质:一种具备接受请求、保存数据、发送数据等功能的网络应用。和一般网络应用的区别是它主要负责数据的接收和传递,所以性能一般高于普通程序。5大核心组成:
2020-05-17 17:10:33
576
原创 了解虚拟机——类加载过程
类加载的整个过程如下图所示:包括加载,验证,准备,解析,初始化,使用,卸载整个流程。一、加载目的:通过一个类的全限定名来获取定义此类的二进制字节流,并将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,并在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。其中获取Class文件可以有如下途径: 1.从zip压缩包中读取; 2.从网络中获取; 3.运行时计算生成; 4.由其他文件生成; ...
2020-05-11 22:47:54
177
原创 详解虚拟机识别的Class类文件结构信息
一、魔数每个class的头4个字节叫做魔数,用来表示这个文件是不是能被虚拟机所识别的文件。这个值就是cafebabe(咖啡宝贝)。二、版本号class文件中,第5和第6个字节表示的是java的此版本好,第7和第8个字节是主版本号,上图中0034表示的是10进制的52,也就是java8的版本。依次类推,JDK7表示51,JDK6表示50。三、常量池常量池可以作为class文件...
2020-05-07 22:34:31
610
原创 详解java程序一个new的过程
在java的世界里,只要当我们去创建一个对象时,都是通过关键字去new的,那么当我们写完这个new之后,我们的程序是怎么帮我们生成这个对象的呢?带着这个问题,我们一起来讨论一下:首先当虚拟机接受到new的字节码指令的时候,先要去常量池中,看能否找到这个类的符号引用信息;当我们没有找到的这个信息的时候,就会去执行这个类的加载信息过程;加载完成后,java虚拟机就会给我们创建的对象去分配内存。...
2020-04-23 22:39:26
598
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人