- 博客(29)
- 收藏
- 关注
原创 如何排查线上内存飙高问题
标题常用的监控和诊断内存工具工欲善其事,必先利其器。平时排查内存性能瓶颈时,我们往往需要用到一些 Linux 命令行或者 JDK 工具来辅助我们监测系统或者虚拟机内存的使用情况,下面我就来介绍几种好用且常用的工具。Linux 命令行工具之 top 命令top 命令是我们在 Linux 下最常用的命令之一,它可以实时显示正在执行进程的 CPU 使用率、内存使用率以及系统负载等信息。其中上半部分显示的是系统的统计信息,下半部分显示的是进程的使用率统计信息。除了简单的 top 之外,我们还可以通过 to
2022-05-19 11:59:40
1345
原创 深入理解JVM之四:程序计数器(PC寄存器)
PC寄存器JVM 的程序计寄存器中。Register的命名源自CPU的寄存器,寄存器存储指令相关的现场信息,CPU只有把数据装载到寄存器才能够运行。这里,并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加则贴(也称为程序钩子),并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC 存器的一种抽象模拟。PC寄存器用来存储指令向下一条指令的地址,也即将要执行的执行代码,由执行引擎读取下一条指令。它是一块很小的内存空间,几平可以忽略不记。也是运行速度最快的有储区域
2022-05-19 11:21:12
205
原创 深入理解JVM之三:运行时数据区内部结构
内存是十分重要的系统资源,是硬盘和CPU的中间仓库及桥梁,承载着操作系统和应用程序的实时运行,JVM内存布局规定了java在运行过程中内存申请,分配,管理的策略,保证了JVM的高效稳定运行,不同的JVM对于内存的划分方式和管理机制存在着部分差异。结合JVM虚拟机规范,来探讨下经典的JVM内存布局。JVM定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程的开始和结束而创建和销毁。线程私有
2022-05-17 16:30:46
151
原创 如何写出高性能SQL语句
MySQL 数据库是互联网公司使用最为频繁的数据库之一,不仅仅因为它开源免费,MySQL 卓越的性能、稳定的服务以及活跃的社区都成就了它的核心竞争力。我们知道,应用服务与数据库的交互主要是通过 SQL 语句来实现的。在开发初期,我们更加关注的是使用 SQL 实现业务功能,然而系统上线后,随着生产环境数据的快速增长,之前写的很多 SQL 语句就开始暴露出性能问题。在这个阶段中,我们应该尽量避免一些慢 SQL 语句的实现。但话说回来,SQL 语句慢的原因千千万,除了一些常规的慢 SQL 语句可以直接规避,其
2022-05-10 23:07:17
743
原创 深入理解JVM之二:类加载器以及双亲委派机制
类加载器JVM支持两种类型的类加载器,分别为引导类加载器(BootStrap ClassLoader)和自定义类加载器(User-Defined ClassLoader)从概念上讲,自定义加载器一般指的是程序中由开发人员自定义的一类类加载器。但是Java 虚拟机规范却没有这么定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义类加载器。 //获取系统类加载器 ClassLoader systemClassLoader = ClassLoader.g
2022-05-06 16:12:29
140
原创 InnoDB的七种锁介绍
共享/排他锁InnoDB实现了两种标准的行级锁:共享锁(简称S锁)、排他锁(简称X锁)。共享锁:简称为S锁,在事务要读取一条记录时,需要先获取该记录的S锁。排他锁:简称X锁,在事务需要改动一条记录时,需要先获取该记录的X锁。...
2022-05-06 15:25:03
1989
原创 深入理解JVM之一:JVM内存结构以及加载过程
概述首先先看一个简要图:其中loadClass的类加载过程有如下几步:加载 >> 验证 >> 准备 >> 解析 >> 初始化 >> 使用 >> 卸载加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口验证:校验字节码文件的正确性准备:给类的静态变量分配
2022-05-06 10:29:56
155
原创 记一次线上SQL死锁事故
先分享个小故事,或能从中获得一点启发。之前我参与过一个项目,在项目初期,我们是没有将读写表分离的,而是基于一个主库完成读写操作。在业务量逐渐增大的时候,我们偶尔会收到系统的异常报警信息,DBA 通知我们数据库出现了死锁异常。按理说业务开始是比较简单的,就是新增订单、修改订单、查询订单等操作,那为什么会出现死锁呢?经过日志分析,我们发现是作为幂等性校验的一张表经常出现死锁异常。我们和 DBA 讨论之后,初步怀疑是索引导致的死锁问题。后来我们在开发环境中模拟了相关操作,果然重现了该死锁异常。接下来我们就通
2022-05-04 15:52:53
192
原创 如何设计更优的分布式锁
目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题。在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。有的时候,我们需要保证一个方法在同一时间内只能被同一个线程执行。实现分布式锁的方式主要有这三种方式:基于数据库实现分布式锁;基于缓存(Redis等)实现分布式锁;基于Zookeeper实现分布式锁;那我们就逐步看下这三种方式是如何实现的。基于数据库实现分布式锁首先,我们应该创建一个锁表,通过创建
2022-05-02 22:36:24
265
原创 剑指offer:链表反转
问题描述:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL限制:0 <= 节点个数 <= 5000这里有两种方式可以解决:迭代的方式:package com.involution.algorithm.reverse;public class ReverseList { stat
2022-05-02 22:16:44
52
原创 java 并发编程工具类之 CountDownLatch
CountDownLatch可以使一个获多个线程等待其他线程各自执行完毕后再执行。CountDownLatch 定义了一个计数器,和一个阻塞队列, 当计数器的值递减为0之前,阻塞队列里面的线程处于挂起状态,当计数器递减到0时会唤醒阻塞队列所有线程,这里的计数器是一个标志,可以表示一个任务一个线程,也可以表示一个倒计时器,CountDownLatch可以解决那些一个或者多个线程在执行之前必须依赖于某些必要的前提业务先执行的场景。public class CountDownLatchTest {
2020-07-01 10:16:18
136
原创 死磕Java并发编程系列之happens-before
happens-before原则定义如下:1. 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。2. 两个操作之间存在happens-before关系,并不意味着一定要按照happens-before原则制定的顺序来执行。如果重排序之后的执行结果与按照happens-before关系来执行的结果一致,那么这种重排序并不非法。下面是happens-before原则规则:程序次序规则:一个线程内,按照代码顺序
2020-07-01 10:04:08
169
原创 死磕Java并发编程系列之volatile
一、基本概念可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉。通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情。为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制。 可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线
2020-06-30 21:35:29
105
原创 java 并发编程工具类之 Semaphore
Semaphore也叫信号量,在JDK1.5被引入,可以用来控制同时访问特定资源的线程数量,通过协调各个线程,以保证合理的使用资源。Semaphore内部维护了一组虚拟的许可,许可的数量可以通过构造函数的参数指定。访问特定资源前,必须使用acquire方法获得许可,如果许可数量为0,该线程则一直阻塞,直到有可用许可。 访问资源后,使用release释放许可。Semaphore和ReentrantLock类似,获取许可有公平策略和非公平许可策略,默认情况下使用非公平策略。应用场景Semaphor
2020-06-30 15:52:30
119
原创 你所不知道的select 、poll、 epoll
select、poll、epoll 这三个函数是Linux系统中I/O复用的系统调用函数。这三个函数可以同时监听多个文件描述符。 系统没有select,poll,epoll处理方式的时候,socket, 一个线程或进程调用accept进行阻塞监听,来了一个连接后,会创建新的线程或进程对应该连接,有新文件描述符产生,本身负责连接通信,然而,连接上但客户端没有发来数据,这条线程或进程就会一直处于阻塞状态,读取文件描述符单没有数据,无法返回,这样的情况多了,就会有大量进程或线程都处于阻塞状态,就会耗费...
2020-06-30 10:32:03
162
原创 JVM垃圾收集底层算法实现之三色标记
在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。这里我们引入“三色标记”来给大家解释下,把Gcroots可达性分析遍历对象过程中遇到的对象, 按照“是否访问过”这个条件标记成以下三种颜色:黑色: 表示对象已经被垃圾收集器访问过, 且这个对象的所有引用都已经扫描过。 黑色的对象代表已经扫描过, 它是安全存活的, 如果有其他对象引用指向了黑色对象, 无须重新扫描一遍。 黑色对象不可能直接(不经过灰色对象) 指向某个白色对象。灰色: 表示...
2020-06-28 17:22:16
1688
原创 Java 集合容器概述
什么是集合集合框架:用于存储数据的容器。集合框架是为表示和操作集合而规定的一种统一的标准的体系结构。任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。接口:表示集合的抽象数据类型。接口允许我们操作集合时不必关注具体实现,从而达到“多态”。在面向对象编程语言中,接口通常用来形成规范。实现:集合接口的具体实现,是重用性很高的数据结构。算法:在一个实现了某个集合框架中的接口的对象身上完成某种有用的计算的方法,例如查找、排序等。这些算法通常是多态的,因为相同的方法可以在
2020-06-23 21:29:10
210
原创 (五)Redis开发规范与性能优化
一、键值设计1. key名设计(1)【建议】: 可读性和可管理性。以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:idtrade:order:1(2)【建议】:简洁性。保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如:user:{uid}:friends:messages:{mid} 简化为 u:{uid}:fr:m:{mid}(3)【强制】:不要包含特殊字符。反例:包含空格、换行、单双引号以及其他转义字符2. val.
2020-06-22 15:55:12
110
原创 (四)Redis开发规范与性能优化
一、键值设计1. key名设计(1)【建议】: 可读性和可管理性。以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:idtrade:order:1(2)【建议】:简洁性。保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如:user:{uid}:friends:messages:{mid} 简化为 u:{uid}:fr:m:{mid}(3)【强制】:不要包含特殊字符。反例:包含空格、换行、单双引号以及其他转义字符2. ...
2020-06-22 15:54:05
184
原创 设计模式之工厂模式
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。实现interface Shape { void draw();}class Rectangle implements Shape { @Override public void draw() { .
2020-06-21 22:16:01
78
原创 设计模式之单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。实现1、懒汉式描述:延迟加载, 只有在真正使用的时候,才开始实例化。编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化 的实例,可以通过添加volatile 关键字进行修饰
2020-06-21 19:55:11
101
原创 设计模式目录
设计模式的分类总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。接下来我会为每个设计模式写一篇文章,来详细解释每个设计模式的用法,以及具体的应用场景。...
2020-06-21 19:25:30
73
原创 (三)Redis缓存设计与性能优化
缓存穿透缓存穿透是指查询一个根本不存在的数据, 缓存层和存储层都不会命中, 通常出于容错的考虑, 如果从存储层查不到数据则不写入缓存层。缓存穿透将导致不存在的数据每次请求都要到存储层去查询, 失去了缓存保护后端存储的意义。造成缓存穿透的基本原因有两个:第一, 自身业务代码或者数据出现问题。第二, 一些恶意攻击、 爬虫等造成大量空命中。缓存穿透问题解决方案:1、缓存空对象String get(String key) { // 从缓存中获取数据 String cache.
2020-06-21 18:19:58
153
原创 (二) Redis持久化
1Redis持久化RDB快照(snapshot)在默认情况下, Redis 将内存数据库快照保存在名字为dump.rdb的二进制文件中。对 Redis 进行设置, 让它在“N秒内数据集至少有M个改动”这一条件被满足时, 自动保存一次数据集。还可以手动执行命令生成RDB快照,进入redis客户端执行命令save或bgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。save是同步命令,bgsave是异步命令,b...
2020-06-21 13:24:41
87
原创 (一)Redis 的安装,原理以及数据结构
一 Redis 安装下载地址:http://redis.io/download安装步骤:# 安装gccyum install gcc# 把下载好的redis-5.0.3.tar.gz放在/usr/local文件夹下,并解压wget http://download.redis.io/releases/redis-5.0.3.tar.gztar xzf redis-5.0.3.tar.gzcd redis-5.0.3# 进入到解压好的redis-5.0.3目录下,进行编译与安装ma.
2020-06-17 21:24:28
121
原创 Spring循环依赖及解决方式
什么是循环依赖?循环依赖其实就是循环引用,也就是两个或者两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图:注意,这里不是函数的循环调用,是对象的相互依赖关系。循环调用其实就是一个死循环,除非有终结条件。Spring中循环依赖场景有:(1)构造器的循环依赖(2)field属性的循环依赖其中,构造器的循环依赖问题无法解决,只能拋出BeanCurrentlyInCreationException异常,在解决属性循环依赖时,spring采用的是提前暴露..
2020-05-21 17:09:47
280
原创 K8S 编排YML 文件解析
# yaml格式的pod定义文件完整内容:apiVersion: v1 #必选,版本号,例如v1kind: Pod #必选,Podmetadata: #必选,元数据 name: string #必选,Pod名称 namespace: string #必选,Pod所属的命名空间 labels: #自定义标签 - name: string #自定义标签名字 annotations: #自定义注释列表
2020-05-12 00:24:36
1116
原创 Docker 概述
2013年发布至今, Docker 一直广受瞩目,被认为可能会改变软件行业。但是,许多人并不清楚 Docker 到底是什么,要解决什么问题,好处又在哪里?今天就来详细解释,帮助大家理解它,还带有简单易懂的实例,教你如何将它用于日常开发。Docker简介Docker是一个开源的容器引擎,它有助于更快地交付应用。 Docker可将应用程序和基础设施层隔离,并且能将基础设施当作程序一样进行管理。使...
2020-05-08 17:29:55
143
原创 JVM类加载机制深度剖析
1、类加载过程多个java文件经过编译打包生成可运行jar包,最终由java命令运行某个主类的main函数启动程序,这里首先需要通过类加载器把主类加载到JVM。主类在运行过程中如果使用到其它类,会逐步加载这些类。注意,jar包里的类不是一次性全部加载的,是使用到时才加载。类加载到使用整个过程有如下几步:加载 >> 验证 >> 准备 >> 解析 >...
2020-05-01 22:19:52
150
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人