自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

不忘初心,方得始终

  • 博客(69)
  • 资源 (1)
  • 收藏
  • 关注

原创 字节码:第二篇

字节码的指令集:https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.1例如:aload_<n>指令,从局部变量表中加载第n个槽的引用到当前方法栈帧的栈顶。栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,他是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息。每一个方法从运行开始到执行结束,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程

2021-04-08 21:31:20 171

原创 操作系统导论-内存篇4

以上的所有内容都是讨论有足够的内存页,发生页面错误时,从空闲页列表找到空闲页,把他分配给不在内存的页。但是,内存经常是不足的,操作系统被迫的需要换出一些页,为常用页腾出空间。那么操作系统如何决定从内存中踢出哪些页?这个决定是由操作系统的替换策略做出,替换策略通常会遵循一些通用原则,但是也会包含一些调整,以避免特殊情况的发生。内存只包含系统中所有页的子集,因此可以将其视为操作系统中虚拟内存页的缓存。因此,在为这个缓存选择替换策略时,我们的目标是让缓存未命中(cache miss)最少,使得从磁盘获取页的次

2021-03-07 19:12:36 567

原创 用ASM玩字节码第一天

基本概念AMS库的目标是生成、转换和解析已经编译好的Java类,表现为byte数组(存储在磁盘上,被JVM加载)。为此,ASM提供了比字节更高级的概念来读取、写入和转换此类字节数组的工具,例如:数字常亮,字符串,Java标识符,Java类型,Java类结构元素。特别需要注意的是,ASM库的作用范围仅限于读、写、转换、分析类,类加载过程是超出了这个范围的。ASM库提供了两种API用来生成和转换编译的class:core API提供了基于事件的类表示,tree API提供了基于对象的类表示。在基于事

2021-02-03 23:11:11 298

原创 操作系统导论-内存篇3

明明记得分页已经写过了,怎么找不到了,继续操作系统导论。到目前为止,我们讨论的地址空间都非常小,能够放入物理内存中。事实上,我们假设每个正在运行的进程的地址空间都是放入在内存中。这一篇里,我们放开这些假设,并且假设我们需要支持更多同时运行的巨大地址空间。为了达到这个目的,我们需要在内存层级上再加一层。为了支持更大的地址空间,操作系统需要把当前没有在用的那部分地址空间找个地方存起来。一般来说,这个地方有一个特点,那就是比内存有更大的容量。因此,一般来说也会更慢。那我们的关键问题就是:操作系统如何利用大

2021-01-31 21:49:30 344

原创 TinyLFU: A Highly Efficient Cache Admission Policy

缓存是计算机科学中可以提高系统性能的最基本、最有效的一种方法之一。当完整的数据不适合全部缓存时,通过将一小部分数据存放到更快、更接近应用程序的内存中来提高性能。缓存可以提高性能的最直观原因在于数据的访问都表现出相当程度的“局部性”。更正式的表征这种“局部性”的方式,是通过概率分布来描述所有可能的数据项访问频率,在许多计算机科学的领域内,这种概率都表现出高度偏斜,也就是说少数的数据项会比其他数据项更可能被访问。并且在非常多的场景中,访问模式和概率分布会随着时间而变化,这种现象被称为“时间局部性”。当访问一

2021-01-16 22:39:09 926

原创 操作系统导论-内存篇2

如何管理空闲空间?如果要管理的空间由大小不同的单元构成,例如用户级的内存分配库malloc()和free(),或者操作系统用分段的方式实现虚拟内存。这时候就会出现外部碎片的问题:空闲空间被分割成了不同大小的块,成为碎片,后续请求可能失败,因为没有一块足够大的连续空闲空间,即使这时总的空闲空间超过了请求的大小。要满足变长的分配请求,应该如何管理空闲空间?什么策略可以让碎片最小化?不同的方法时间和空间的开销如何?在深入策略之前,我们先介绍大部分分配程序的通用机制。首先,探索空间分隔与合并的基本知识。

2020-12-27 19:34:02 162

原创 操作系统导论-内存篇1

如何实现高效的内存虚拟化?如何提供应用程序所需的灵活性?如何保持控制应用程序可访问的内存位置,从而确保应用程序的内存访问受到合理的限制?如何高效的实现这一切?我们使用了一种通用的技术,基于硬件的地址转换。硬件对每次内存访问处理,将指令中的虚拟地址转换为数据实际存储的物理地址。当然,仅依靠硬件不足以实现虚拟内存,它只提供了底层机制来提高效率。还需要操作系统的介入,它必须管理物理内存,记录被占用和空闲的内存位置,保持对内存使用的控制。那么操作系统是如何来做内存虚拟化的,我们依旧是先把问题理想化,做假.

2020-12-05 23:48:16 112

原创 操作系统导论-进程调度

最近读经典书籍少了,总是爱看一些水文博客,不用费脑子想,还总有一种学到了的感觉,其实在回味思考下,发现毫无营养。所以开一系列读书笔记,强迫自己读书,从《操作系统导论》开始。坚持每周一部分内容,年前读完。运行任务的底层机制是上下文切换,那上层还需要操作系统的调度。为了理解操作系统调度策略,先把问题理想化,把操作系统中的运行的任务作出如下假设:每一个任务运行时间相同 所有任务同时到达 任务禁止抢占 所有任务只使用CPU,即无I/O操作 每个任务时间是已知的为了比较不同的调度策略,先给出一个衡量

2020-11-29 00:39:17 404

原创 堆外KV存储

有大量数据要存储,堆内放不下,只能选择放堆外。那高性能、线程安全的堆外kv存储怎么做?以下是我实际做的过程。最原始、最容易的,搞一个ConcurrentHashMap,每次写数据时先计算好value的大小,然后申请相应大小的DirectBuffer,写入数据后,插入Map中,value就是这个DirectBuffer。可想而知这性能会有多差,申请DirectBuffer是一个非常耗时的操作,而且大量的DirectBuffer会产生大量的虚引用,在一定程度上影响GC。那么先做池化处理,预先申请一大

2020-10-17 14:58:16 344

原创 R树

先搞明白R树搜索、插入、删除过程。R树是平衡树,可以理解为B树在N维空间上的扩展。R树一定要满足一下要求:1.根节点若非叶子节点,则至少有两个子节点;2.每个非根叶节点和非叶节点包含的实体个数均介于m和M之间;3.所有叶子节点在同一层次;其中m表示拥有子节点的下限,目的是为了提高磁盘利用率,提高搜索效率。如果m=1,所有节点都只有一个子节点,那树就退化为了普通链表。当节点的子节点数量少于m时,则会删除该节点,把该节点的子节点分配到其他节点中;M表示拥有子节点的上限,因为一般情况下,出

2020-08-13 22:34:08 1079 1

原创 怎么查你附近的餐厅

最近在看Martin大神的一本书,叫《Designing Data-Intensive Application》(《设计数据密集型应用》)。里面提到一个概念,叫做多维索引。书中给了一个例子:餐厅搜索网站可能有一个数据库,其中包含每个餐厅的精度和维度。当用户在地图上查看餐厅时,网站需要搜索用户查看的矩形地图区域内的所有餐厅。这就需要一个二维的查询,如下:SELECT * FROM restaurants WHERE latitude > 51.4946 AND latitude < 51

2020-08-10 22:32:20 4253

原创 消息队列之消息过滤

众所周知,RocketMQ是支持消息过滤的,即发送消息时,可以给消息设置一个TAG。订阅主题的时候,可以设置只消费携带某些TAG的消息,起到消息过滤的作用。RocketMQ中是把消息TAG通过哈希转换成了的long型,保存在了消息索引中。在订阅客户端拉取消息时,为了减少协议大小,减低报文长度,拉取协议中也只携带指定的若干TAG的哈希值,服务端接收到拉取请求时,在查找索引时,就直接过滤了不符合条件的索引。这里就会有一个问题,如果出现哈希冲突了,就会有错误的消息被客户端消费到。RocketMQ为了提高性能,

2020-07-18 22:40:23 740

原创 进程调度-1

最近特别有感触,各层面的设计似乎都可以从操作系统中找出相似的设计,操作系统几乎是设计集大成者,所以重新又开始看操作系统相关的书籍。最近可能都是一些记录性的文章,操作系统原理因为是教学课程,所以不会另做笔记。从重读Linux内核开始,记录学习过程。本文均摘自《Linux内核与实现》。因为硬件资源总是有限的,而我们哪个进程可以占用资源投入运行,何时运行以及要运行多长时间,就是调度程序要做的事情。进程调度程序就是可运行态进程之间分配有限的处理器时间资源的内核子系统。首先我们要明确几个概念,多任务系统可

2020-07-04 22:48:33 262

原创 开源框架WPaxos源码浅析

最近WPaxos框架已经开源,WPaxos开源地址。作为旁观者之一,大致简单的梳理一下整体的代码结构,做一个源码浅析,后面有时间再对每一部分做深入的分析。Paxos算法是一个强一致性的算法,最精简的描述应当是Paxos原作者在《Paxos Made Simple》中的描述:Phase 1(a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acc

2020-06-02 16:41:21 637 3

原创 负载均衡-粘性分配与平滑加权轮询

说到负载均衡,我个人习惯分为两种,一种是静态负载均衡,也就是把确定好的、有限的负载按照一定规则分配到不同的工作单元上,这种负载均衡算法只需要计算一次最终分配状态即可。一种是动态负载均衡,即每次把新到来的负载按照一定规则分配到不同的工作单元上,这种负载均衡算法需要实时动态计算,并且大部分需要保留上一次分配的状态。比如说,kafka中一个topic有多个consumer,那每个consumer需要消费哪些partition都是提前计算好的。这里负载就是这个topic的所有partition,是一个确定好的、

2020-06-01 23:30:25 734

原创 一个小伙伴的问题

下午休息的时候,小伙伴突然扔给我一段代码public class GCTest { public static void main(String[] args) { List<GCTest> aa = new ArrayList<>(); for (; ; ) { aa.add(new GCTest()); System.gc(); } }}然后问到:为什么不加System.gc()这一行就会OOM,加上System.gc()就不再OOM了。

2020-05-26 23:06:58 258

原创 work steal and overpartition

工作窃取和超额切分,第一次听到这个概念是从ZGC的Stripe Mark技术,它为了提高垃圾回收的效率,把多个region划分到不同的条纹,然后再把GC线程隔离到自己的条纹内进行垃圾回收。如果有线程处理完了自己的任务,则会加入到其他的条纹上帮助其他的线程来处理任务。这就是和工作窃取是同一种思想。工作窃取,一种分治的思想,最初是一种多指令流多数据流(MIMD)计算任务的线程调度方法,需要工作的处理器需要从其他的处理器上窃取工作任务。一般上层应用层也会用来做多线程任务的调度,来保证线程的活跃来提高任务处理的

2020-05-23 22:47:02 352

原创 怎么做配置下发

配置下发我们做开发,无论是做中间件还是业务都会面临一个问题,我们的客户端或者APP发版本后,需要运行中动态加载一些配置,比如负载均衡、服务发现等,这些配置需要从服务端来获取,并且在配置变更后,客户端可以及时或非及时的得到最新的配置。把问题抽象化,即我们客户端如何获取最新的配置,也就是配置下发的问题。少量用户最开始,配置下发可能会比较简单,无论是采用TCP长连接或者是HTTP短连接等等,我们客户端定时的与服务端进行通信,每次从服务端拉取最新的配置,客户端进行本地更新即可。这是最基.

2020-05-14 23:34:28 3894

原创 调整敏感度

目录一个功能Netty高低水位Java8的Map调整敏感度一个功能最近在做一个功能,消息队列的消费端负载均衡,像kafka、RocketMQ等都可以做到全局消费的负载均衡,但是他们都需要一个中心节点来做统一分配与调整。我们做到了不用集中节点的全局负载均衡,并且模仿kafka的StickAssignor做到了粘性分配,即每次变动最少(纯属为了炫耀,与本文无关)。回归正题,每次对消费端做负载均衡是一个代价很大的操作,因为要停止受影响消费端的消费,收集消费offset,重新分配,所以这

2020-05-13 23:15:39 28911

原创 java并发编程(二)-volatile写操作前为什么不加LoadStore屏障

只要说到并发编程,volatile是永远绕不开的一个点。理解了volatile,基本上也就理解了JMM。Java内存模型中的happens-before、as-if-serial等在前文介绍过,这里只介绍volatile的内存语义实现。在JSR-133之后,volatile可以实现线程之间的通信,加强了volatile的内存语义,即禁止volatile变量与普通变量的重排序,使得volatile的写-读与锁的释放-获取有相同的语义。对于volatile内存语义的描述,几乎都出自于http://gee

2020-05-12 15:17:31 3020 23

原创 java并发编程(一)

目录为什么有并发编程并发涉及的问题锁CAS对象头synchronizedAQSReentrantLocksemaphore未完待续......并发编程发展到如今几乎已经成为了开发人员的必备技能。很多高级工程师、专家,甚至于架构师都站在“山顶”聊并发,讲怎么并发编程。作为一个以Java为主语言的低级开发人员,我也想尝试从“山脚”的角度,仰望一下并发。为...

2020-05-03 10:46:23 305

原创 RocketMQ事务消息

之前提到过,我们自研的消息队列中间件参考了RocketMQ的实现,但是有的细节上考虑得不是很全面。所以最近又拿我们的消息队列与RocketMQ做一些对比,看看有哪些点是当时没理解透,而做出的一些不恰当改动。恰好想到我们还不支持事务消息,而RocletMQ在2018年4.3版本发布时,就已经支持了事务消息。详细可以参考文章:https://mp.weixin.qq.com/s/43wwC4l...

2020-04-27 23:59:42 255

原创 再谈时间轮

时间轮很早前就很流行了,在很多优秀开源框架中都有用到,像kafka、netty。也算是现在工程师基本都了解的一个知识储备了。有幸在工作中造过两次轮子,所以今天聊聊时间轮。时间轮是一种高性能定时器。时间轮,顾名思义,就是一个基于时间的轮子,轮子划分为多个槽,每个槽代表一个时间跨度,槽的数量*时间跨度等于时间轮可以支持的最大延迟时间。在每个槽上挂载若干同一时间跨度内需要执行的任务。随着时间...

2020-04-19 00:27:38 2251 3

原创 再谈MappedByteBuffer与DirectBuffer

去年年底的时候,为我们的分布式消息队列中间件写源码分析系列文章的时候,看到我们的存储部分是参考了RocketMQ的实现。这部分有一个很有意思的内容public AppendMessageResult appendMessage(final Object msg, final AppendMessageCallback cb) throws IOException { ...

2020-04-11 17:35:08 1732

原创 由DCL引发的一次思考

上次群里面试的小伙伴在看完对逃逸分析的说明后,下功夫好好学了HotSpot即时编译的相关知识,信心十足的又去面试了,结果又让回家等消息。看了看他分享的面试题,又在各种高大上的题目里发现了一道有意思的题:请看一个DCL单例模式,并简单说明一下是否正确。这题目过于简单,不像是这种级别的面试题,所以这道题大有深意,很有意思。先上代码:/** * @author liuyan * @...

2020-04-05 00:18:55 277 2

原创 Java对象在堆上分配吗

昨天有个技术群里一个小伙伴分享了一次被虐的面试经历,其中一道题很有意思:Java中对象都会分配在堆上吗?大部分小伙伴都在讨论类似:redis为什么快?怎么设计弹性伸缩的缓存系统?服务降级、服务熔断等等非常高大上的问题。但是在如此高大上的问题里,掺杂了这么看似简单的一道题,说明还是有点意思。问了下小伙伴们,不为少数的小伙伴都会很简单的回答,对象分配在堆上啊,上学没认真听讲吗?但是真的如此...

2020-04-02 22:21:17 297

原创 关于i++与++i的一道题

前几天刷LettCode题,看到评论区有人问了一个有意思的问题,代码如下:public static void main(String[] args) { int a[] = {1, 2, 3, 4, 5}; int num = 3; a[num - 1] = a[num-- - 1]; for (int i : a) { System.out.println(i); }}...

2020-04-01 12:27:28 805

原创 线程模型优化

先说背景,抽象后线程模型为:如上图线程模型,说明解释一下。多个线程接受请求,并发把请求提交到一个合并线程的队列中。提交请求伪代码表示为:request.inTime = nowlock.lockput queueif(check) list = take top 20 require from queue doSomething(list) for require in ...

2019-11-22 22:39:39 178

原创 paxos算法中master有效期与续约依赖机器时间的解决办法

对于paxos算法,一般工程化时,为了提高paxos算法效率,会引入master角色,并且要遵循在同一时刻,paxos集群有且只有一个节点是master角色,或者没有master角色;且只有master角色的节点可以发起propose,这两个原则。这就涉及到了maste的选举与续约。一般的master选举如下图所示:那么master节点认为master的任期为从beMaster操...

2019-11-07 22:07:32 295

原创 我的理解阻塞\非阻塞,同步\异步

要解释I\O的阻塞\非阻塞,同步\异步,实在难以下笔。涉及内容太多,很多知识点我也没有搞清楚,很怕误导别人。算是把看到的认为好的内容搬运过来,整合一下,再把自己不理解的内容抛出来,做个记录,日后想着学懂。说I/O模型,不得不提《UNINX网络编程》这本书,“第六章:I/O复用”中把Uninx可用的I/O模型分为了5种:阻塞式I/O 非阻塞式I/O I/O复用 信号驱动式I/O 异步...

2019-03-16 15:31:10 317

原创 记一次线上FGC排查经历

背景:线上服务,启动后很快必定FGC一次,随后GC变正常。服务器上JDK版本为jdk1.8.0_66。启动参数为:-Xms8g -Xmx8g -Xmn3g -Xss1024K -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC        -XX:+UseCMSCompactAtFullCollection -...

2018-12-09 22:13:14 3154 2

原创 一次Java空指针异常排查经历

同理先说背景:我们的一个注册中心服务,多节点部署,客户端会hash到一个节点,启动定时任务与之通信拉取配置。突然有业务线说客户端大量报超时异常。首先当然赶紧让业务线把异常日志发给我。先分析了一下日志,找到了对应的超时异常,根据堆栈信息分析出是拉取配置任务大量连续超时,再定位到是哪一台服务。因为之前线上出现过超时情况,是因为代码效率太低,每个拉取配置的请求要处理将近750ms,导致了请求队列...

2018-12-05 20:53:17 1742 1

原创 记一次重构经历

背景:最近新接触一个web项目,要求新增加一个审批流程。简化抽象模型,订单分为三种A\B\C。其中AB的审批流程完全一致,简化为审批1-&gt;审批2-&gt;审批后动作。C的审批流程略有不同,简化为审批0-&gt;审批1-&gt;审批2-&gt;审批后动作。现在要做的一个功能是要在订单C上增加一个审批流程变为:审批0-&gt;审批3-&gt;审批1-&gt;审批2-&gt;审批后动作。很简单...

2018-11-25 17:30:45 335

翻译 ZGC窥探(翻译a first look into zgc)

ZGC目的是为了减少空间整理的耗时。像GC的基本算法里,标记清除算法就是不进行空间整理,会产生空间碎片。复制清除和标记整理算法都会进行空间整理,不会产生空间碎片。虽然空间整理减少产生空间碎片,但是需要用户线程全部暂停,也就是我们所说的stop the world现象。只有gc结束之后,用户线程才可以恢复。根据堆空间大小不同,有的停顿时间长达几秒。有几种方法可以减少停顿时间: 多线程并行的...

2018-10-29 17:48:52 725

原创 总结

最终还是离职了,晃晃悠悠毕业两年了,沉淀半年,19年开始写点有深度的文章。加油

2018-06-21 15:06:09 206

原创 数据库主键生成方案

问题产生的背景:数据量到达一定程度时,需要做数据的分库分表(这又是一个很值得讨论的问题,什么量级的数据做分库分表),此时我们需要保证数据库主键的唯一性、单调递增。并且获取唯一主键的服务要保证高可用、高吞吐率。一般常用的方法有snowflake算法、UUID、数据库自增主键等等。因为MySql是聚集存储方式,其存储是按照主键顺序存放的,所以实际生产环境会要求主键递增,所以UUID一般用的比较少。sn...

2018-04-19 22:23:48 1622

原创 JDK赏析-HashMap(二)

终于有电脑了,换了份工作,38天的空档期,没有工作学习的状态了。新同事水平平均很高,我属于拉低平均线的档次了,要继续努力了。最近食言了,没有看并发编程那本书,而是买了两本mysql书,一本是innodb存储引擎,一本是性能优化,目前在看innodb存储引擎,收获很大,等看完全本,把这本书的读书笔记写一下。接上一篇,上一篇讲了hashmap的put和resize方法,接着往下看,可以看到,hashm...

2018-03-11 15:13:07 174

原创 jdk赏析-HashMap(一)

HashMap可以说是日常使用非常频繁的数据结构了,存储k/v结构,可以做对象的映射。提供了所有的相关map的操作,可以允许null值作为key和value,和HashTable的区别就是不同步和允许null。HashMap不保证存储的顺序也不保证操作都是O(1)的,有两个关键性的属性影响操作的性能,初始大小和负载系数。初始大小就是默认的哈希桶的大小,负载系数描述了哈希桶满的程度,决定了什么时间进

2018-01-27 17:19:53 213

原创 jdk欣赏-ArrayList(2)

ArrayList中有两个转换为数组的方法,Object[] toArray()和 T[] toArray(T[] a)。两个方法的唯一区别就是返回的数据类型不同,最终都是这个方法: public static T[] copyOf(U[] original, int newLength, Class newType) { @SuppressWarnings("unc

2018-01-21 16:55:39 221

原创 jdk欣赏-ArrayList(1)

《深入理解java虚拟机》这本书大概看了一遍,收获很大,博客就暂时告于段落,不过学习还是继续,下一本书读《java并发编程实战》,配合之前学习的内容,应该可以串联上。博客新开一个系列,jdk源码系列,读并发和jvm比较枯燥,jdk源码就当做调味品。从集合类开始,最简单的ArrayList类,我们可以看到ArrayList实现了Serializable接口,并且有一个静态的long型变量serial

2018-01-17 22:33:14 212

2019智能家居生态发展白皮书.pdf

2019中国智能家居发展白皮书,完整版,清晰度很高,无水印,良心博主上传。

2019-06-26

空空如也

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

TA关注的人

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