自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(171)
  • 收藏
  • 关注

原创 手撸一个叫hangu-register的注册中心

一个peer-peer的去中心化注册中心。

2024-03-30 15:21:52 984

原创 手写Java序列化工具

以上是一个非常简单的实现,我们可以看到针对每种数据类型,它的序列化方式是不一样的,所以其实。我们可以使用策略模式加以改造,比如定义一个接口,加一个参数上下文,根据不同的数据类型实现。假设给一个java bean,让你按照 json 的格式打印出来,你会怎么做?比如这个java bean 长这样,并且创建了一个叫宝儿姐的朋友。

2023-10-08 08:57:59 149 1

翻译 raft算法

Raft 是一种为了管理复制日志的一致性算法。它提供了和 Paxos 算法相同的功能和性能,但是它的算法结构和 Paxos 不同,使得 Raft 算法更加容易理解并且更容易构建实际的系统。为了提升可理解性,Raft 将一致性算法分解成了几个关键模块,例如领导人选举、日志复制和安全性。同时它通过实施一个更强的一致性来减少需要考虑的状态的数量。一项用户研究的结果表明,对于学生而言,Raft 算法比 Paxos 算法更加容易学习。

2023-09-26 11:35:18 105 1

原创 手撸一个叫hangu-rpc的轻量级rpc框架

hangu-rpc为rpc原理学习者提供了一个思路,一个非常简单的轻量级rpc代码示例,代码中没有使用什么高级的设计(比如SPI),也没有高级的用法,服务的调用直接用的反射,没有像dubbo一样,使用字节码生成直接调用代码来提高性能,注册中心实现了redis哨兵与zookeeper版本。如果你是一个对rpc原理好奇的人,你可以很快了解rpc的核心实现,至于想要了解更高级的设计,可以阅读dubbo源码。hangu 是函谷的拼音。为什么取这个名字呢?

2023-08-11 09:02:15 357

原创 五、配置文件的解析

本文分析了logback是如何解析配置文件的,配置文件的标签大部分是有对应的action处理的,除了一些通过反射动态设置的action,如果读者自己本身有扩展logback的需求,比如就拿springboot来说,它为了从spring的环境中获取属性,使用 SpringBootJoranConfigurator去解析配置文件,并扩展了springProperty标签,对应的action为SpringPropertyAction,当然logback本身还有一个newRule标签可以。...

2022-08-12 11:26:26 716

原创 四、encoder与layout分析

d{yyyy-MM-dd HH:mm:ss.SSS}-----%logger,那么解析出来的Converter是这样的 DateConventer -> LiteralConverter -> LoggerConverter。我们的日志要输出到不同的appender,有点时候有编码要求,比如GBK,UTF-8等,就需要encoder,另外,我们的日志是需要一定的格式的,而不是随意。从上面的代码可以看出,它使用的是 PatternLayout,那么它是怎么对消息进行格式化的呢?logger输出类。......

2022-08-11 21:12:18 732

原创 三、appender分析

我们选了logback中最常用的Appender进行分析,了解了一个日志是怎么输出的,但在这个日志输出之前我们还需要做些处理,比如根据用户配置的格式进行输出,根据用户设置的编码进行编码,下面我们再来分析下Encoder的实现方式。...

2022-08-11 21:11:02 770

原创 二、快速开始

这一章主要是从一个小例子开始去了解我要打印一个日志需要哪些个组件,当了解了需要什么组件之后,那么我们就可以知道哪些组件是可以定制的,从而引出通过配置化的方式去定制组件。额外的,在 LogbackDemo3Test.java 这个例子我们直接深入Appender基本上实现打印出了日志,让我们对后边分析Appender源码有一个大致的印象,从而更快速的去理解它的运作方式。......

2022-08-11 11:20:17 684

原创 一、什么是日志

什么是日志

2022-08-11 11:19:36 3347

原创 4、JVM调优

1、堆大小设置:根据每次gc后的活跃对象计算大小,新生代为活跃对象的2倍,老年代也为2到3倍,元数据也为2倍2、继续根据gc的日志做调整3、使用一些jvm命令工具做优化,比如jmap4、jvm参数,比如开启tlab,逃逸分析,双层编译,如果是cms垃圾收集器,那么可开启full gc多少次进行压缩整理,腾出连续空间5、根据需求选择垃圾回收器,如果需要低延时,确定延时就用gc或cms...

2022-04-02 13:23:19 257

原创 2、springcloud注册中心

前提:spring版本 -》1.2.6.RELEASE一、注册中心的搭建1.1 启动类@EnableEurekaServer@SpringBootApplicationpublic class EurekaServer { public static void main(String[] args) { new SpringApplicationBuilder(EurekaServer.class).web(true).run(args); }}1.2 配置# 应用服务名sp

2022-01-10 13:17:35 545

原创 1、springcloud客户端的创建

前提:spring版本 -》1.2.6.RELEASE一、基础组件可以看到这个配置类引入注入了很多其他的bean,那么这些bean是哪里注册进来的呢?我们在构建注册中心的时候会引入一个包<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-eureka-client</artifactId></depe

2022-01-08 17:45:38 774

原创 基于数据库版本的分布式定时任务调度中心

一、需求构建一个统一的调度系统,用于触发定时任务的调度。二、方案设计2.1 方案1:快速迭代方案-基于数据库的集群调度编写一个基于数据库锁(定时任务 id 做唯一键)与公司rpc框架相结合的轻量级定时任务调度中心2.2 方案2:基于master选举的分布式定时任务调度方案(可使用开源项目框架,但目前基本都是ZK的,受限与公司现状,可自行开发redis版本) -》分布式任务调度:https://blog.csdn.net/qq_27785239/article/details/120578171?

2021-10-17 22:29:33 982

原创 分布式任务调度

一、master任务分配模式选举一台机器作为master,master除了需要处理任务之外,赋予额外的能力,比如检测活跃机器,然后根据分配策略分配任务以及失败,超时任务重新调度等能力。1.1 架构设计1.2 模块设计1.2.1 master选举master选举采用最简单的实现方式,就是抢占分布式锁,master选举成功之后,任务的切分由用户通过SPI实现,该组件可单独用于master选举,但依然要注意机器假死产生的脑裂问题。出现脑裂问题时,问题机器应该拥有快速检测到自己与外部网络不通的问题,或者

2021-10-01 15:34:51 442

转载 DDD(领域驱动设计)总结

基本概念:领域驱动设计(简称 ddd)概念来源于2004年著名建模专家eric evans发表的他最具影响力的书籍:《domain-driven design –tackling complexity in the heart of software》(中文译名:领域驱动设计—软件核心复杂性应对之道)一书。,书中提出了“领域驱动设计(简称 ddd)”的概念。 领域驱动设计一般分为两个阶段: 1. 以一种领域专家、设计人员、开发人员都能理解的“通用语言”作为相互交流的工具,在不断交流

2021-09-05 11:19:49 301

原创 RocketMQ总结

一、架构设计RocketMQ 中文官方文档:https://github.com/apache/rocketmq/blob/master/docs/cn/architecture.md二、总结2.1 发送消息1、先从本地缓存中获取对应topic发布信息(消息队列列表),如果本地没有那么从nameserver中获取对应topic的发布信息,如果这个topic是不存在的并且配置了 autoCreateTopicEnable=true 那么会使用一个默认的 topic =》TBW102 获取队列列表。p

2021-09-05 11:02:23 290

原创 1、时间轮

一、什么是时间轮?作为一个粗人,咱不扯什么高级的词汇,直接上图:上面是一张时间轮的示意图,可以看到,这个时间轮就像一个钟表一样,它有刻度,图中画了9个格子,每个格子表示时间精度,比如每个格子表示1s,那么转一圈就是9s,对于钟表上的秒针来说它的最小刻度是1s,秒针转一圈就是60s。时间轮上每个格子储存了一个双向链表,用于记录定时任务,当指针转到对应的格子的时候,会检查对应的任务是否到期,如果到期就会执行链条上的任务。二、为什么使用时间轮?我认为这个世界上任何事物的出现都有它的原因,只是大部分事

2020-07-25 14:15:44 4719 3

原创 1、docker for mac 搭建ftp

一、准备工作1.1 安装dockerdocker下载地址:https://www.docker.com/get-started1.2 设置加速器地址首先注册阿里云容器镜像服务地址:https://cr.console.aliyun.com/cn-hangzhou/instances/repositories注册好之后选择镜像加速,操作如下:复制加速地址,然后打开docker的 Preferences -》Docker Engine ,编辑json在原来的json串中添加 registr

2020-07-04 22:22:30 700

转载 java获取txt文件的编码格式

/** * txt转html * @param s * @return */ public static String txtToHtml(String s) { try { StringBuilder builder = new StringBuilder(); File file=new File(s); if(file.isFile() && fil.

2020-07-04 18:51:10 1216

原创 13、Netty内存池之PooledByteBufAllocator

一、PooledByteBufAllocator的创建PooledByteBufAllocator顾名思义,就是一个用于分配PooledByteBuf的分配器现在有以下例子程序public class Test { public static void main(String[] args) { PooledByteBufAllocator allocator =...

2020-05-03 23:24:15 1500

原创 12、Netty的内存池之PoolArena

一、简介PoolArena从功能上来讲综合了PoolThreadCache与PoolChunk,就像一个门面一样。PoolArenaMetric//当前PoolArean所管理的内存池已被多少个线程缓存int numThreadCaches();//返回tiny类型的数组的长度,默认就是32int numTinySubpages();//返回small类型数组的长度,默认是4...

2020-05-03 19:56:02 605

原创 11、Netty的内存池之PoolThreadCache

一、PoolThreadLocalCache在申请池化内存时,netty并不会直接从内存池中申请,而是先从PoolThreadLocalCache获取,同样的release一个ByteBuf时并不会直接归还到内存池,而是先缓存在PoolThreadLocalCache中PoolThreadLocalCache继承了FastThreadLocal,FastThreadLocal类似JDK的Th...

2020-05-03 16:06:22 1414

原创 10、Netty内存池之PoolChunk与PoolSubPage

一、原理请移步到《netty的内存池设计》二、PoolChunk与PoolSubPage2.1 PoolChunk2.1.1 简介PoolChunk表示一个内存块,默认16M,用于管理分配内存,以下为PoolChunk的类图PoolChunkMetric:接口,usage方法用于获取PoolChunk的使用率;chunkSize方法返回PoolChunk的大小;freeBytes方...

2020-05-02 18:44:47 899 2

原创 9、Netty的内存池设计

一、简介netty作为一款优秀的通信框架,不可避免的需要面对频繁的数据读入与写出,此时肯定会导致大量ByteBuf对象的创建,为了减少频繁申请内存带来的开销与gc,netty设计了内存池。二、内存池设计的演化假设让你设计一个内存池,你会怎么设计?也许你会创建一个字节数组,然后分配一定的大小,像下面这样//分配16M的字节数组byte[] memoryPool = new byte[1...

2020-05-01 18:58:30 1914 1

原创 1、Linux系统下Idea无法输入中文小记

一、起因刚入职某家公司,这家公司给我配置的电脑是一台安装了Linux系统的台式电脑,于是我上去就是一通噼里啪啦的环境搭建,搭建好后,准备读读公司自研的rpc(其实和dubbo之类的原理是一样的,有点重复造轮子了,对于个人而言,那是兴趣,对于公司而言其实我觉的没必要花费精力,人力,财力在造轮子上,别人造轮子是为了适合公司的快速迭代,通常也只是修改框架,不会从头到尾,包括协议,注册中心都是自研的),...

2020-05-01 10:08:40 1670

原创 8、Netty的对象池

一、什么是对象池?顾名思义,就是有一个池子装着一群对象。我们需要对象的时候就从池子中取一个出来,用完之后就把对象放回池子中去。这样可以复用对象并且减少创建一个对象的开销,也可以避免申请对象太多导致的频繁gc。从设计模式上来讲,它是一种享元模式。二、netty的对象池netty为了避免过多的创建对象和频繁的gc使用了对象池,在需要创建ByteBuf的时候,从对象池中找,如果没有才会去创建一个...

2020-04-28 23:39:57 877

原创 7、Netty的零拷贝之CompositeChannelBuffer

一、类图ChannelBuffer:接口,用于定义设置读索引,写索引,获取字节数据等方法。AbstractChannelBuffer:模板类,实现了操作索引的方法,具体的读取数据的方法交由子类实现。二、字段说明2.1 AbstractChannelBuffer//读索引private int readerIndex;//写索引private int writerIndex;...

2020-04-24 22:59:51 241

原创 19、ThreadLocal

一、简介ThreadLocal可用于解决多线程并发的问题,其原理是每个线程都有一个代表其自身的Thread对象,每个Thread对象内部都有一个ThreadLocalMap字段,这个ThreadLocalMap是用于保存数据的容器。另一方面ThreadLocal也可以解决跨层跨方法传通用值的问题。二、字段说明//这个值等于下面两个字段相加的结果 nextHashCode.getAndAdd...

2020-04-06 12:25:17 216 1

原创 6、压缩列表

一、简介压缩列表(ziplist)是列表键和哈希键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,那么Redis就会使用压缩列表来做列表键的底层实现。比如:redis> rpush lst 1 3 5 10086 "hello" "world"(integer) 6redis> OBJECT ENCODING lst...

2020-04-02 19:44:29 1519

原创 5、整数集合

一、简介整数集合(intset)是集合键的底层实现之一, 当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。比如:redis> SADD numbers 1 3 5 7 9(integer) 5redis> OBJECT ENCODING numbers"intset"二、重点2.1 结构体typedef st...

2020-04-02 19:41:33 922

原创 4、跳跃表

一、简介跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且因为跳跃表的实现比平衡树要来得更为简单,所以有不少程序都使用跳跃表来代替平衡树。Redis使用跳跃表作为有序集合键的...

2020-04-02 19:40:58 128

原创 3、字典

一、简介Redis的字典使用哈希表作为底层实现,一个哈希表里面可以有多个哈希表节点,而每个哈希表节点就保存了字典中的一个键值对。1.1 结构体1.1.1 字典typedef struct dict { // 类型特定函数 dictType *type; // 私有数据 void *privdata; // 哈希表,通常使用ht[0],在re...

2020-04-02 19:39:55 80

原创 2、链表

一、简介1.1 结构体1.1.1 链表每个节点的结构体typedef struct listNode { // 前置节点 struct listNode *prev; // 后置节点 struct listNode *next; // 节点的值 void *value; } listNode;可以看到这个节点有两个指针,一个prev...

2020-04-02 19:38:41 109

原创 1、redis的简单动态字符串

一、简介1.1 结构体struct sdshdr { //记录buf数组中已使用字节的数量 int len; //记录还未使用的长度 int free; //用于存放具体的字符串值 char buf[]; };redis为什么要定义自己的字符串,而不是使用c自带的字符数组?首先c自带的字符数组在获取其字符串的长度的时间复杂度是O(n),...

2020-04-02 19:36:14 131

原创 18、Phaser

一、Phaser1.1 字段说明//用于记录parties,phase//高32用于记录当前正在等待释放线程执行的阶段//低32的高16位表示每一阶段可arrived的parties数量//低32的低16位表示当前还剩多少parties未arrivedprivate volatile long state;//表示最大可arrived的parties数private stati...

2020-04-01 18:41:51 135

原创 12、tomcat自检题目

一、tomcat原理篇1.1 为什么tomcat需要自定义线程池org.apache.catalina.core.StandardThreadExecutor?实际上其内部执行任务的仍然是JDK的ThreadPoolExecutor从继承结果上来看,tomcat的线程池实现了Lifecycle,Executor, ResizableExecutor,其中JDK的线程池是没有实现Lifecy...

2020-03-19 16:13:37 284

原创 2、Scheduler调度过程

一、回顾public class Test { public static void main(String[] args) { Scheduler scheduler = new Scheduler(); scheduler.schedule("*/1 * * * *", new Task() { @Override ...

2019-12-21 13:22:37 1099

原创 1、基础

一、例子下面是一个简单的例子,它表示每分钟执行一次public class Test { public static void main(String[] args) { //创建调度器 Scheduler scheduler = new Scheduler(); //设置需要调度的任务 scheduler.schedu...

2019-12-21 13:21:49 180

原创 17、ForkJoinPool之工作线程的启动与任务的fork以及join

一、工作线程的启动ForkJoinPool创建的工作线程类型为ForkJoinWorkerThread,下面是它的run方法1.1 启动扫描任务public void run() { if (workQueue.array == null) { // only run once Throwable exception = null; try { ...

2019-12-04 21:57:34 1362

原创 16、ForkJoinPool之外部任务的提交与创建工作线程

一、前言在第15节中我们讲解了ForkJoinPool的实现原理和与之相关的类,为我们学习ForkJoinPool的实现打下了基础。二、原理实现2.1 ForkJoinPool字段说明//低16位掩码,这也是WorkQueue在工作队列组中的最大索引值static final int SMASK = 0xffff; // short bits == max ...

2019-12-04 21:53:53 801

空空如也

空空如也

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

TA关注的人

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