锁定读, 一致性非锁定读

锁定读, 一致性非锁定读 http://ju.outofmemory.cn/entry/275548 锁定读 (Locking Reads) 在一个事务中查询数据时,普通的SELECT语句不会对查询的数据进行加锁,其他事务仍可以对查询的数据执行更新和删除操作。因此,InnoDB提供了两种类型的锁定读来保证额外的安全性: - SELECT … LOCK IN SHARE MODE - SELECT … FOR UPDATE SELECT … LOCK IN SHARE MODE: 对读取的行添加S锁,其他事物可以对这些行添加S锁,若添加X锁,则会被阻塞。 SELECT … FOR UPDATE: 会对查询的行及相关联的索引记录加X锁,其他事务请求的S锁或X锁都会被阻塞。 当事务提交或回滚后,通过这两个语句添加的锁都会被释放。 注意: 只有在自动提交被禁用时, SELECT FOR UPDATE 才可以锁定行, 若开启自动提交, 则匹配的行不会被锁定。 一致性非锁定读 (Consistent Nonlocking Reads) MySQL官方文档对弈一致性读的定义: > A consistent read means that InnoDB uses multi-versioning to present to a query a snapshot of the database at a point in time. 就是说: 一致性读意味着InnoDB使用多版本控制来实现一个查询,这个查询所依赖的数据是基于某个时间点的数据库快照。 注意: 是数据库的快照,而不是要查询的那个表的快照。 在事务隔离级别设置为READ COMMITTED和REPEATABLE READ时,默认情况下InnoDB是通过一致性读来处理SELECT语句的。一致性读不会对它访问的表设置任何锁,因此,在一个表上进行一致性读的同时,其他session可以随意修改这些表。 一致性读是使用基于时间点的快照信息来呈现查询结果的读取操作,而不管其他事务在同一时间产生的变更。如果查询的数据已被其他事务改变,InnoDB会基于undo log的内容来重建最初的数据。 两种事务隔离级别下,读取的快照数据的区别: - 在REPEATABLE READ事务隔离级别下,同一事务内的所有一致性读都会读取到该事务中第一个一致性读建立的快照。通过提交当前事务并发起一个新的查询,可以看得到新的快照。 - 在READ COMMITTED事务隔离级别下,同一事务内的每个一致性读总是读取本次一致性读建立的快照。(即,快照的时间点是基于本次一致性读的时间点,也就是最新的数据) 假设当前事务隔离级别为REPEATABLE READ,当发出一个一致性读(也就是一个普通的SELECT语句)时,InnoDB会根据这个查询给此事务分配一个时间点。若其他事务在此时间点之后删除了一行并提交,那么此事务不会看到其他事务产生的影响(即,还是会看到被删除的行)。插入和更新操作也一样。

2017-05-09 · 1 min · 87 words · -

MVCC, Multiversion Concurrency Control, 多版本并发控制

MVCC, Multiversion Concurrency Control, 多版本并发控制 http://donghui.blog.51cto.com/2709336/692586 多版本并发控制技术已经被广泛运用于各大数据库系统中,如 Oracle, MS SQL Server 2005+, Postgresql, Firebird, Maria 等等, 开源数据库 MySQL 中流行的 INNODB 引擎也采用了类似的并发控制技术.本文就将结合实例来解析不同事务隔离等级下 INNODB 的 MVCC 实现原理. 1.1 MVCC 简介 MVCC (Multiversion Concurrency Control), 即多版本并发控制技术, 它使得大部分支持行锁的事务引擎, 不再单纯的使用行锁来进行数据库的并发控制, 取而代之的是, 把数据库的行锁与行的多个版本结合起来, 只需要很小的开销, 就可以实现非锁定读, 从而大大提高数据库系统的并发性能. 1.2 实现原理 MVCC 可以提供基于某个时间点的快照, 使得对于事务看来, 总是可以提供与事务开始时刻相一致的数据, 而不管这个事务执行的时间有多长. 所以在不同的事务看来, 同一时刻看到的相同行的数据可能是不一样的, 即一个行可能有多个版本. 是否听起来不可思议呢? 原来, 为了实现 mvcc, innodb 对每一行都加上了两个隐含的列, 其中一列存储行被更新的"时间", 另外一列存储行被删除的"时间". 但是 innodb 存储的并不是绝对的时间, 而是与时间对应的数据库系统的版本号, 每当一个事务开始的时候, innodb 都会给这个事务分配一个递增的版本号, 所以版本号也可以被认为是事务号. 对于每一个"查询"语句, innodb 都会把这个查询语句的版本号同这个查询语句遇到的行的版本号进行对比, 然后结合不同的事务隔离等级, 来决定是否返回该行. ...

2017-05-09 · 5 min · 859 words · -

Locked ownable synchronizers

Locked ownable synchronizers An ownable synchronizer is a synchronizer that may be exclusively owned by a thread and uses AbstractOwnableSynchronizer (or its subclass) to implement its synchronization property. ReentrantLock and ReentrantReadWriteLock are two examples of ownable synchronizers provided by the platform. http://stackoverflow.com/questions/41300520/what-is-locked-ownable-synchronizers-in-thread-dump

2017-05-05 · 1 min · 42 words · -

java jps

java jps jps位于jdk的bin目录下,其作用是显示当前系统的java进程情况,及其id号。 jps相当于Solaris进程工具ps。不象"pgrep java"或"ps -ef grep java",jps并不使用应用程序名来查找JVM实例。因此,它查找所有的Java应用程序,包括即使没有使用java执行体的那种 (例如,定制的启动 器) 。另外,jps仅查找当前用户的Java进程,而不是当前系统中的所有进程。 -h: help -l: 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名 -m: 输出传递给main 方法的参数,在嵌入式jvm上可能是null, 在这里,在启动main方法的时候,我给String[] args传递两个参数。hollis,chuang,执行jsp -m: -v: 输出传递给JVM的参数 在这里,在启动main方法的时候,我给jvm传递一个参数: -Dfile.encoding=UTF-8,执行jps -v: 位置 我们知道,很多Java命令都在jdk的JAVA_HOME/bin/目录下面,jps也不例外,他就在bin目录下,所以,他是java自带的一个命令。 功能 jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。 原理 jdk中的jps命令可以显示当前运行的java进程以及相关参数,它的实现机制如下: java程序在启动以后,会在java.io.tmpdir指定的目录下,就是临时文件夹里,生成一个类似于hsperfdata_User的文件夹,这个文件夹里 (在Linux中为/tmp/hsperfdata_{userName}/) ,有几个文件,名字就是java进程的pid,因此列出当前运行的java进程,只是把这个目录里的文件名列一下而已。 至于系统的参数什么,就可以解析这几个文件获得。 hollis@hos:/tmp/hsperfdata_hollis$ pwd /tmp/hsperfdata_hollis hollis@hos:/tmp/hsperfdata_hollis$ ll total 48 drwxr-xr-x 2 hollis hollis 4096 4月 16 10:54 ./ drwxrwxrwt 7 root root 12288 4月 16 10:56 ../ ...

2017-05-05 · 2 min · 222 words · -

自旋锁/Spin lock

自旋锁/Spin lock public class SpinLock { private AtomicReference<Thread> sign =new AtomicReference<>(); public void lock(){ Thread current = Thread.currentThread(); while(!sign.compareAndSet(null, current)){ } } public void unlock (){ Thread current = Thread.currentThread(); sign.compareAndSet(current, null); } } // another spin lock for (;;) { if (condition == true) break; } 自旋锁是为实现保护共享资源而提出一种锁机制。其实,自旋锁与互斥锁比较类似,它们都是为了解决对某项资源的互斥使用。无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一个保持者,也就说,在任何时刻最多只能有一个执行单元获得锁。但是两者在调度机制上略有不同。对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态。但是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁,“自旋"一词就是因此而得名。 自旋锁适用于锁保护的临界区很小的情况,临界区很小的话,锁占用的时间就很短。 自旋锁一般原理 跟互斥锁一样,一个执行单元要想访问被自旋锁保护的共享资源,必须先得到锁,在访问完共享资源后,必须释放锁。如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即得到锁;如果在获取自旋锁时锁已经有保持者,那么获取锁操作将自旋在那里,直到该自旋锁的保持者释放了锁。由此我们可以看出,自旋锁是一种比较低级的保护数据结构或代码片段的原始方式,这种锁可能存在两个问题: 死锁和过多占用cpu资源。 自旋锁适用情况 ...

2017-05-04 · 1 min · 72 words · -

kafka config, server, producer

kafka config, server, producer 大体上来说,用户首先构建待发送的消息对象ProducerRecord,然后调用KafkaProducer#send方法进行发送。KafkaProducer接收到消息后首先对其进行序列化,然后结合本地缓存的元数据信息一起发送给partitioner去确定目标分区,最后追加写入到内存中的消息缓冲池(accumulator)。此时KafkaProducer#send方法成功返回。 KafkaProducer中还有一个专门的Sender IO线程负责将缓冲池中的消息分批次发送给对应的broker,完成真正的消息发送逻辑。 基本设计特点 结合源代码,笔者认为新版本的producer从设计上来说具有以下几个特点(或者说是优势): 总共创建两个线程: 执行KafkaPrducer#send逻辑的线程——我们称之为"用户主线程";执行发送逻辑的IO线程——我们称之为"Sender线程" 不同于Scala老版本的producer,新版本producer完全异步发送消息,并提供了回调机制(callback)供用户判断消息是否成功发送 batching机制——“分批发送"机制。每个批次(batch)中包含了若干个PRODUCE请求,因此具有更高的吞吐量 更加合理的默认分区策略: 对于无key消息而言,Scala版本分区策略是一段时间内(默认是10分钟)将消息发往固定的目标分区,这容易造成消息分布的不均匀,而新版本的producer采用轮询的方式均匀地将消息分发到不同的分区 底层统一使用基于 Selector 的网络客户端实现, 结合 Java 提供的 Future 实现完整地提供了更加健壮和优雅的生命周期管理。 其实,新版本 producer 的设计优势还有很多, 诸如监控指标更加完善等这样的就不一一细说了。总之, 新版本producer更加地健壮,性能更好~ Kafka新版本clients在设计底层网络库时采用了Java的Selector机制,而后者在 Linux上的实现机制就是 epoll;但是在 Windows平台上,Java NIO的 Selector 底层是使用 select模型而非IOCP 实现的,只有 Java NIO2才是使用 IOCP 实现的。因此在这一点上,在 Linux 上部署Kafka要比在Windows上部署能够得到更高效的I/O处理性能。 properties props = new Properties(); props.put("bootstrap.servers", "localhost:9092"); props.put("acks", "all"); props.put("retries", 0); props.put("batch.size", 16384); props.put("linger.ms", 1); props.put("buffer.memory", 33554432); props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); Producer<String, String> producer = new KafkaProducer<>(props); for(int i = 0; i < 100; i++) producer.send(new ProducerRecord<String, String>("my-topic", Integer.toString(i), Integer.toString(i))); producer.close(); bootstrap.servers 配置kafka 查询集群 metadata 服务的地址, 建立连接时,kafa producer向 bootstrap.servers 发 metadata 请求, 从 返回 的metadata response里得到kafka 集群的地址,再建立连接 ...

2017-05-04 · 4 min · 739 words · -

systemtap

systemtap http://www.cnblogs.com/hazir/p/systemtap_introduction.html 内核探测工具systemtap简介 systemtap是内核开发者必须要掌握的一个工具,本文我将简单介绍一下此工具,后续将会有系列文章介绍systemtap的用法。 什么是systemtap 假如现在有这么一个需求: 需要获取正在运行的 Linux 系统的信息,如我想知道系统什么时候发生系统调用,发生的是什么系统调用等这些信息,有什么解决方案呢? 最原始的方法是,找到内核系统调用的代码,加上我们需要获得信息的代码、重新编译内核、安装、选择我们新编译的内核重启。这种做法对于内核开发人员简直是梦魇,因为一遍做下来至少得需要1个多小时,不仅破坏了原有内核代码,而且如果换了一个需求又得重新做一遍上面的工作。所以,这种调试内核的方法效率是极其底下的。 之后内核引入了一种Kprobe机制,可以用来动态地收集调试和性能信息的工具,是一种非破坏性的工具,用户可以用它跟踪运行中内核任何函数或执行的指令等。相比之前的做法已经有了质的提高了,但Kprobe并没有提供一种易用的框架,用户需要自己去写模块,然后安装,对用户的要求还是蛮高的。 systemtap 是利用Kprobe 提供的API来实现动态地监控和跟踪运行中的Linux内核的工具,相比Kprobe,systemtap更加简单,提供给用户简单的命令行接口,以及编写内核指令的脚本语言。对于开发人员,systemtap是一款难得的工具。 下面将会介绍systemtap的安装、systemtap的工作原理以及几个简单的示例。 systemtap 的安装 我的主机 Linux 发行版是32位 Ubuntu13.04,内核版本 3.8.0-30。由于 systemtap 运行需要内核的调试信息支撑,默认发行版的内核在配置时这些调试开关没有打开,所以安装完systemtap也是无法去探测内核信息的。 下面我以两种方式安装并运行 systemtap: 方法一 编译内核以支持systemtap 我们重新编译内核让其支持systemtap,首先你想让内核中有调试信息,编译内核时需要加上 -g 标志;其次,你还需要在配置内核时将 Kprobe 和 debugfs 开关打开。最终效果是,你能在内核 .config 文件中看到下面四个选项是设置的: CONFIG_DEBUG_INFO CONFIG_KPROBES CONFIG_DEBUG_FS CONFIG_RELAY 配置完之后,按照之前你编译内核的步骤编译即可。 获取systemtap源码 从此地址 https://sourceware.org/systemtap/ftp/releases下载已经发布的systemtap的源代码,截至目前 (2013.9.17) 最新版本为systemtap-2.3。下载完之后解压。 当然你还可以使用 git 去克隆最新的版本 (2.4) ,命令如下: git clone git://sources.redhat.com/git/systemtap.git 编译安装systemtap 如果你下载的是最新版本的systemtap,那么你需要新版的 elfutils,可以从https://fedorahosted.org/releases/e/l/elfutils/ 下载elfutils-0.156 版本。下载之后解压缩到适合的目录 (我放在~/Document/ 下) ,不需要安装,只要配置systemtap时指定其位置即可。 进入之前解压systemtap的目录,使用下面命令进行配置: ./configure -with-elfutils=~/Document/elfutils-0.156 以这里方法配置之后,你只需要再运行 make install 即完成systemtap的编译安装。如果需要卸载的话,运行 make uninstall。 ...

2017-05-04 · 2 min · 258 words · -

gomock

gomock go install github.com/golang/mock/mockgen@v1.6.0 mockgen -source feeds/feeds.go -destination feeds/mocks/feeds_mock.go -package mocks -source:设置需要模拟 (mock)的接口文件 -destination:设置 mock 文件输出的地方,若不设置则打印到标准输出中 -package:设置 mock 文件的包名,若不设置则为 mock_ 前缀加上文件名 (如本文的包名会为 mock_person)

2017-05-04 · 1 min · 23 words · -

内核空间, 用户空间; kernel mode/user mode, User space/Kernel space

内核空间, 用户空间; kernel mode/user mode, User space/Kernel space User space & Kernel space 现代操作系统会把内存划分为2个区域,分别为Use space(用户空间) 和 Kernel space(内核空间)。用户的程序在User space执行,系统内核在Kernel space中执行。 用户的程序没有权限直接访问硬件资源,但系统内核可以。比如读写本地文件需要访问磁盘,创建socket需要网卡等。因此用户程序想要读写文件,必须要向内核发起读写请求,这个过程叫system call。 内核收到用户程序system call时,负责访问硬件,并把结果返回给程序。 FileInputStream fis = new FileInputStream("/tmp/test.txt"); byte[] buf = new byte[256]; fis.read(buf); 简单说,Kernel space 是 Linux 内核的运行空间,User space 是用户程序的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。 Kernel space 可以执行任意命令,调用系统的一切资源;User space 只能执行简单的运算,不能直接调用系统资源,必须通过系统接口 (又称 system call) ,才能向内核发出指令。 str = “my string” // 用户空间 x = x + 2 file.write(str) // 切换到内核空间 y = x + 4 // 切换回用户空间 上面代码中,第一行和第二行都是简单的赋值运算,在 User space 执行。第三行需要写入文件,就要切换到 Kernel space,因为用户不能直接写文件,必须通过内核安排。第四行又是赋值运算,就切换回 User space。 ...

2017-04-25 · 2 min · 387 words · -

openjdk

openjdk https://openjdk.org/projects/jdk/ https://jdk.java.net windows install openjdk https://github.com/ojdkbuild/ojdkbuild winget install Microsoft.OpenJDK.21 linux https://github.com/ojdkbuild/contrib_jdk8u-ci https://github.com/ojdkbuild/ojdkbuild/releases/download/java-1.8.0-openjdk-1.8.0.242-1.b08/java-1.8.0-openjdk-1.8.0.242-1.b08.ojdkbuild.windows.x86_64.msi ## archlinux install openjdk # openjdk sudo pacman -S jdk-openjdk sudo pacman -S openjdk-src # jdk8 sudo pacman -S jdk8-openjdk openjdk8-src sudo pacman -S jdk11-openjdk # 查看已经安装的 jdk archlinux-java status sudo archlinux-java set java-11-openjdk sudo pacman -S jdk17-openjdk openjdk17-src 切换 jdk 版本 archlinux-java help archlinux-java status archlinux-java set java-14-openjdk 查看当前 java 版本 java -version sudo archlinux-java status ubuntu openjdk # 安装默认版本, 最新的 TLS 版本 sudo apt update sudo apt install default-jdk # 验证安装 java -version javac -version sudo apt install openjdk-21-jdk sudo apt install openjdk-8-jdk sudo apt install openjdk-8-source # openjdk 17, depends libc6 (>= 2.33) sudo sudo apt update && sudo apt install openjdk-17-jdk openjdk-17-source # 默认目录 ls -l /usr/lib/jvm/ # 查看 sudo update-java-alternatives -l # 切换 jdk sudo update-alternatives --config java 手动安装 openjdk download jdk JDK ...

2017-04-21 · 2 min · 275 words · -

MySQL 共享锁 排他锁

‘MySQL 共享锁 排他锁’ http://www.hollischuang.com/archives/923 共享锁(Share Lock) 共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改 (获取数据上的排他锁) ,直到已释放所有共享锁。 如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。 用法 SELECT … LOCK IN SHARE MODE; 在查询语句后面增加LOCK IN SHARE MODE,MySQL会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。 排他锁 (eXclusive Lock) 排他锁又称写锁,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。 用法 SELECT … FOR UPDATE; 在查询语句后面增加FOR UPDATE,MySQL会对查询结果中的每行都加排他锁,当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。 意向锁 意向锁是表级锁,其设计目的主要是为了在一个事务中揭示下一行将要被请求锁的类型。InnoDB中的两个表锁: 意向共享锁 (IS) : 表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁 意向排他锁 (IX) : 类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。 意向锁是InnoDB自动加的,不需要用户干预。 对于insert、update、delete,InnoDB会自动给涉及的数据加排他锁 (X) ;对于一般的Select语句,InnoDB不会加任何锁,事务可以通过以下语句给显示加共享锁或排他锁。 共享锁: SELECT … LOCK IN SHARE MODE; 排他锁: SELECT … FOR UPDATE;

2017-04-12 · 1 min · 58 words · -

MySQL INNODB

MySQL INNODB InnoDB 由 Innobase Oy 公司所开发, 发音为 “in-no-db” http://wulijun.github.io/2012/09/29/MySQL-innodb-intro.html InnoDB是MySQL下使用最广泛的引擎, 它是基于 MySQL 的高可扩展性和高性能存储引擎, 从5.5版本开始, 它已经成为了默认引擎。 InnODB 引擎支持众多特性: 支持ACID,简单地说就是支持事务完整性、一致性; 支持行锁,以及类似ORACLE的一致性读,多用户并发; 独有的聚集索引主键设计方式,可大幅提升并发读写性能; 支持外键; 支持崩溃数据自修复; InnoDB有这么多特性,比MyISAM来的优秀多了,还犹豫什么,果断的切换到InnoDB引擎吧 🙂 InnoDB 配置 可以选择官方版本, 或者 Percon a的分支, 如果不知道在哪下载, 就google吧。安装完MySQL后,需要适当修改下 my.cnf 配置文件, 针对 InnoDB 相关的选项做 一些调整, 才能较好的运行InnoDB。 相关的选项有: #InnoDB存储数据字典、内部数据结构的缓冲池,16MB 已经足够大了。 innodb_additional_mem_pool_size = 16M #InnoDB用于缓存数据、索引、锁、插入缓冲、数据字典等 #如果是专用的DB服务器,且以InnoDB引擎为主的场景,通常可设置物理内存的50% #如果是非专用DB服务器,可以先尝试设置成内存的1/4,如果有问题再调整 #默认值是8M,非常坑X,这也是导致很多人觉得InnoDB不如MyISAM好用的缘故 innodb_buffer_pool_size = 4G #InnoDB共享表空间初始化大小,默认是 10MB,也非常坑X,改成 1GB,并且自动扩展 innodb_data_file_path = ibdata1:1G:autoextend #如果不了解本选项,建议设置为1,能较好保护数据可靠性,对性能有一定影响,但可控 innodb_flush_log_at_trx_commit = 1 #InnoDB的log buffer,通常设置为 64MB 就足够了 innodb_log_buffer_size = 64M #InnoDB redo log大小,通常设置256MB 就足够了 ...

2017-04-11 · 2 min · 289 words · -

archlinux, tensorFlow, golang

archlinux, tensorFlow, golang build tensorflow git clone https://github.com/tensorflow/tensorflow sudo pacman -S bazel sudo pacman -S python-numpy docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow docker run -it gcr.io/tensorflow/tensorflow bash https://www.tensorflow.org/install/install_linux#InstallingDocker https://www.tensorflow.org/get_started/get_started

2017-04-04 · 1 min · 29 words · -

iowait

iowait iowait 表示在一个采样周期内有百分之几的时间属于以下情况: CPU空闲、并且有仍未完成的 I/O 请求。 对 %iowait 常见的误解有两个: 一是误以为 %iowait 表示 CPU不能工作的时间, 二是误以为 %iowait 表示 I/O有瓶颈。 首先 %iowait 升高并不能证明等待 I/O的进程数量增多了, 也不能证明等待 I/O的总时间增加了。 例如, 在 CPU繁忙期间发生的 I/O, 无论IO是多还是少, %iowait都不会变;当 CPU繁忙程度下降时, 有一部分 IO落入CPU空闲时间段内, 导致%iowait升高。 再比如, IO的并发度低, %iowait就高;IO的并发度高, %iowait可能就比较低。 可见 %iowait是一个非常模糊的指标, 如果看到 %iowait 升高 ,还需检查I/O量有没有明显增加, avserv/avwait/avque 等指标有没有明显增大, 应用有没有感觉变慢,如果都没有,就没什么好担心的。 iowait 的含义为有进程在等 io操作结束 (备份进程) , 并且在等待 io操作结束的过程中, 无其他进程占用cpu, cpu处于空闲状态, 故根据iowait参数无从判断io负载情况,还需要通过iostat来判断备份期间io负载情况 (如备份期间磁盘写性能是否已达瓶颈等) %iowait = (cpu idle time)/(all cpu time) 说明: 高速cpu会造成很高的 iowait值,但这并不代表磁盘是系统的瓶颈。唯一能说明磁盘是系统瓶颈的方法,就是很高的read/write时间,一般来说超过20ms,就代表了不太正常的磁盘性能。为什么是20ms呢?一般来说,一次读写就是一次寻到+一次旋转延迟+数据传输的时间。由于,现代硬盘数据传输就是几微秒或者几十微秒的事情,远远小于寻道时间 (seek time) 220ms和旋转延迟48ms,所以只计算这两个时间就差不多了,也就是15~20ms。只要大于20ms,就必须考虑是否交给磁盘读写的次数太多,导致磁盘性能降低了。 ...

2017-03-31 · 1 min · 154 words · -

Guava cache

Guava cache http://www.cnblogs.com/peida/p/Guava_Cache.html 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用。在日常开发的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们发现我们的系统这个数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现。缓存的作用就是将这些来自不易的数据保存在内存中,当有其他线程或者客户端需要查询相同的数据资源时,直接从缓存的内存块中返回数据,这样不但可以提高系统的响应时间,同时也可以节省对这些数据的处理流程的资源消耗,整体上来说,系统性能会有大大的提升。 缓存在很多系统和架构中都用广泛的应用,例如: 1.CPU缓存 2.操作系统缓存 3.本地缓存 4.分布式缓存 5.HTTP缓存 6.数据库缓存 等等,可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。 Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好。 Guava Cache有两种创建方式: cacheLoader callable callback 通过这两种方法创建的cache,和通常用map来缓存的做法比,不同在于,这两种方法都实现了一种逻辑——从缓存中取key X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值。但不同的在于cacheloader的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值load value的方法。而callable的方式较为灵活,允许你在get的时候指定。 cacheLoader方式实现实例: @Test public void TestLoadingCache() throws Exception{ LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() .build(new CacheLoader<String, String>(){ @Override public String load(String key) throws Exception { String strProValue=“hello “+key+”!”; return strProValue; } }); System.out.println(“jerry value:"+cahceBuilder.apply(“jerry”)); System.out.println(“jerry value:"+cahceBuilder.get(“jerry”)); System.out.println(“peida value:"+cahceBuilder.get(“peida”)); System.out.println(“peida value:"+cahceBuilder.apply(“peida”)); System.out.println(“lisa value:"+cahceBuilder.apply(“lisa”)); cahceBuilder.put(“harry”, “ssdded”); System.out.println(“harry value:"+cahceBuilder.get(“harry”)); } 输出: jerry value:hello jerry! ...

2017-03-31 · 3 min · 467 words · -

vmstat

vmstat vmstat -SM 1 vmstat 1 10 # vmstat每2秒采集数据,一直采集,直到结束程序 vmstat 2 # 2表示每两秒采集一次服务器状态,1表示只采集一次。 vmstat 2 1 vmstat命令是最常见的 Linux/Unix 监控工具, 可以展现给定时间间隔的服务器的状态值, 包括服务器的 CPU 使用率, 内存使用, 虚拟内存交换情况, IO读写情况。 相比 top, vmstat 可以看到整个机器的 CPU,内存,IO 的使用情况,而不是单单看到各个进程的 CPU 使用率和内存使用率(使用场景不一样)。 -S: 输出信息的单位, (k: 1000, K:1024 , m: 1000000, M: 1048576) bytes, -S, --unit CHAR -a: 显示活动内页 -f: 显示启动后创建的进程总数; -m: 显示slab信息; -n: 头信息仅显示一次 -s: 以表格方式显示事件计数器和内存状态; -d: 报告磁盘状态; -p: 显示指定的硬盘分区状态; 一般vmstat工具的使用是通过两个数字参数来完成的,第一个参数是采样的时间间隔数,单位是秒,第二个参数是采样的次数,如: 输出的字段 r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。 b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。 swpd swap 的使用量 虚拟内存已使用的大小, 如果大于0, 表示你的机器物理内存不足了, 如果不是程序内存泄露的原因, 那么你该升级内存了或者把耗内存的任务迁移到其他机器。 ...

2017-03-31 · 2 min · 251 words · -

Runtime freeMemory,totalMemory,maxMemory

Runtime freeMemory,totalMemory,maxMemory http://blog.csdn.net/zy_27_ok/article/details/8462385 最近在网上看到一些人讨论到Java.lang.Runtime类中的freeMemory(),totalMemory(),maxMemory ()这几个方法的一些题目,很多人感到很迷惑,为什么,在java程序刚刚启动起来的时候freeMemory()这个方法返回的只有一两兆字节,而随着 java程序往前运行,创建了不少的对象,freeMemory()这个方法的返回有时候不但没有减少,反而会增加。这些人对freeMemory()这 个方法的意义应该有一些误解,他们以为这个方法返回的是操纵系统的剩余可用内存,实在根本就不是这样的。这三个方法反映的都是java这个进程的内存情 况,跟操纵系统的内存根本没有关系。下面结合totalMemory(),maxMemory()一起来解释。 maxMemory()这个方法返回的是java虚拟机 (这个进程) 能构从操纵系统那里挖到的最大的内存,以字节为单位,假如在运行java程 序的时 候,没有添加-Xmx参数,那么就是64兆,也就是说maxMemory()返回的大约是64*1024*1024字节,这是java虚拟机默认情况下能 从操纵系统那里挖到的最大的内存。假如添加了-Xmx参数,将以这个参数后面的值为准,例如java -cp ClassPath -Xmx512m ClassName,那么最大内存就是512*1024*0124字节。 totalMemory()这个方法返回的是java虚拟机现在已经从操纵系统那里挖过来的内存大小,也就是java虚拟机这个进程当时所占用的 所有 内存。假如在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操纵系统那里挖的,基本上是用多少挖多少,直 挖到maxMemory()为止,所以totalMemory()是慢慢增大的。假如用了-Xms参数,程序在启动的时候就会无条件的从操纵系统中挖- Xms后面定义的内存数,然后在这些内存用的差未几的时候,再往挖。 freeMemory()是什么呢,刚才讲到假如在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的 从操 作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存,实际上就是 freeMemory(),所以freeMemory()的值一般情况下都是很小的,但是假如你在运行java程序的时候使用了-Xms,这个时候由于程 序在启动的时候就会无条件的从操纵系统中挖-Xms后面定义的内存数,这个时候,挖过来的内存可能大部分没用上,所以这个时候freeMemory()可 能会有些大。 把下面的源代码编译以后,在class文件所在的目录里面,分别用java -cp . Untitled1 和java -cp . -Xms80m -Xmx80m Untitled1 运行,看看结果如何,有助于理解上面的阐述。 public?class?Untitled1?{?????? ??public?Untitled1()?{}?????? ??public?static?void?main(String[]?args)?{?? ????System.out.println(Runtime.getRuntime().freeMemory());?? ????System.out.println(Runtime.getRuntime().totalMemory());?? ????System.out.println(Runtime.getRuntime().maxMemory());?? ????long?t?=?System.currentTimeMillis();?? ????try?{?? ??????Thread.sleep(30000);?? ????}?catch?(Exception?ee)?{?? ??????ee.printStackTrace();?? ????}?? ????String[]?aaa?=?new?String[2000000];?? ????System.out.println(Runtime.getRuntime().freeMemory());?? ????System.out.println(Runtime.getRuntime().totalMemory());?? ????System.out.println(Runtime.getRuntime().maxMemory());?? ????try?{?? ??????Thread.sleep(30000);?? ????}?catch?(Exception?ee)?{?? ??????ee.printStackTrace();?? ????}?? ????for?(int?i?=?0;?i?<?2000000;?i++)?{?? ??????aaa[i]?=?new?String(“aaa”);?? ????}?? ????System.out.println(Runtime.getRuntime().freeMemory());?? ????System.out.println(Runtime.getRuntime().totalMemory());?? ????System.out.println(Runtime.getRuntime().maxMemory());?? ????try?{?? ??????Thread.sleep(30000);?? ????}?catch?(Exception?ee)?{?? ...

2017-03-31 · 1 min · 74 words · -

jvm thread DestroyJavaVM

jvm thread DestroyJavaVM DestroyJavaVM is a thread that unloads the Java VM on program exit. Most of the time it should be waiting, until apocalypse of your VM. Signal Dispatcher is a thread that handles the native signals sent by the OS to your jvm. Finalizer threads pull objects from the finalization queue and calls it finalize method. Reference Handler is a high-priority thread to enqueue pending References. Its defined in java.lang.ref.References.java This happens because most applications are run in threads. ...

2017-03-30 · 2 min · 272 words · -

Java 获取 进程PID

Java 获取 进程PID String name = ManagementFactory.getRuntimeMXBean().getName(); // get pid String pid = name.split("@")[0]; logger.info("PID:{}", pid); 之前并不知道Java中如何能够获取当前进程 (也就是包含当前Java程序的JVM所在进程) 的进程ID,还以为要通过JNI或者通过Runtime.exec执行shell命令等方式才能获取到当前进程的进程ID,今天在偶然中看到一种在Java程序里,获取当前进程ID的方法,记录下来,以后应该会用到: ) 首先,从JDK1.5之后,Java开始提供包: java.lang.management java.lang.management 提供了一系列的用来在运行时管理和监督JVM和OS的管理接口。 今天我将用到的就是这个包中的一个类: ManagementFactory。 当然,这只是java.lang.management包中的一个小功能,该包还提供了很多其他的管理接口,参照java doc如下: Interface Summary ClassLoadingMXBean The management interface for the class loading system of the Java virtual machine. CompilationMXBean The management interface for the compilation system of the Java virtual machine. GarbageCollectorMXBean The management interface for the garbage collection of the Java virtual machine. ...

2017-03-30 · 1 min · 142 words · -

JVM编译器

JVM编译器 即时编译器 Java虚拟机中内置了两个即时编译器,分别为Client和Server或则叫C1和C2. C1编译器将字节码编译为本地代码,进行简单可靠的优化,C2编译器则会启动一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。C1和C2都是编译一些热点代码 (多次调用的方法或者多次执行的循环体) ,因此在编译前,首先要进行热点探测,HotSpot虚拟机中使用的是基于计数器的热点探测方法。 它为每个方法都准备了两个计数器,方法调用计数器和回边计数器。 方法调用计数器统计的并不是方法被调用的绝对次数,而是一个相对的执行频率,即一段时间内方法被调用的次数。当超过一定的时间限度,如果方法调用次数仍然不足以让它提交给即时编译器,那这个方法的调用计数器就会衰减一般,这个过程称为方法调用计数器热度的衰减。 回边计数器统计的是一个方法中循环体代码执行的次数,它没有热度衰减。建立回边计数器统计的目的是为了处罚OSR编译,OSR即栈上替换,也就是编译发生在方法执行过程之中。 http://blog.csdn.net/tingfeng96/article/details/52261219 http://blog.csdn.net/zhuyijian135757/article/details/38391785 https://cyberdak.github.io/jvm/2017/03/25/jvm-restart-cause-high-load

2017-03-30 · 1 min · 12 words · -