HiSEN

Personal Technology Blog


  • 归档

  • 分类

  • 标签

  • 书单

  • 关于

  • 搜索
close
HiSEN

缓存那些事儿 - 从组件到实践

发表于 2019-04-29 | 分类于 java

一、为什么用缓存

1.1 空间换时间:

缓存是针对读多写少的场景典型的以空间换时间的操作
空间:内存
时间:读内存速度快(相对于读磁盘)

1.2 局部性原理:

这个世界很多事情都符合 2/8 原则
把热点数据缓存起来就大大提高系统效率

二、缓存组件介绍

2.1 Ehcache

  1. 快速,针对大型高并发系统场景,Ehcache 的多线程机制有相应的优化改善;
  2. 简单,很小的 jar 包,简单配置就可直接使用,单机场景下无需过多的其他服务依赖;
  3. 支持多种的缓存策略,灵活;
  4. 缓存数据有两级:内存和磁盘,与一般的本地内存缓存相比,有了磁盘的存储空间,将可以支持更大量的数据缓存需求;
  5. 具有缓存和缓存管理器的侦听接口,能更简单方便的进行缓存实例的监控管理;
  6. 支持多缓存管理器实例,以及一个实例的多个缓存区域;

2.2 Guava

  1. 自动将 entry 节点加载进缓存结构中;
  2. 当缓存的数据超过设置的最大值时,使用 LRU 算法移除;
  3. 具备根据 entry 节点上次被访问或者写入时间计算它的过期机制;
  4. 缓存的 key 被封装在 WeakReference 引用内;
  5. 缓存的 Value 被封装在W eakReference 或 SoftReference 引用内;
  6. 统计缓存使用过程中命中率、异常率、未命中率等统计数据;
    阅读全文 »
HiSEN

Java GC - 理论与实践 - 附优化案例

发表于 2019-04-29 | 分类于 java

一、理论知识

常见参数:

  1. -Xms 堆初始化 例如:-Xms256m
  2. -Xmx 堆最大值 例如:-Xmx512m
  3. -Xmn 堆新生代 例如:-Xmn100m
  4. -XX:NewRatio 新生代与老年代的比例
  5. -XX:SurvivorRatio 新生代区域比例,默认8,代表Eden:From Survivor:To Survivor = 8:1:1

垃圾回收器:

  1. Serial/Serial Old 新生代/老年代,古老,单线程,暂停所有用户线程,复制算法/标记整理算法
  2. ParNew 1的多线程版本
  3. Parallel Scavenge 新生代,多线程,不需要暂停用户线程,复制算法
  4. Parallel Old 老年代,多线程,不需要暂停用户线程,标记整理算法
  5. CMS(Current Mark Sweep,详情)老年代,与ParNew配合使用,牺牲吞吐量获得最短停顿,标记整理算法
  6. G1 并行与并发收集器,可预测的停顿时间

二、实践案例

  1. Full GC 之前进行 Minor GC 避免扫描过多的对象, 配置:CMSScavengeBeforeRemark
  2. Xms和Xmx设置为相同,这样可以减少内存自动扩容和收缩带来的性能损失
  3. JVM调优是最后的稻草,进行JVM调优之前应该先优化架构和代码
  4. 调优是一个复杂的过程,根据具体的场景结合对垃圾回收器的深入理解进行调优,才可能事半功倍。

各个区大小比例建议

1
2
3
4
5
# 活跃空间大小:Full GC后堆中老年代占用空间的大小
空间 倍数
总大小 3-4倍活跃空间大小
新生代 1-1.5倍活跃空间大小
老年代 2-3倍活跃空间大小

阅读全文 »
HiSEN

Java受检异常和非受检异常 - uncheckedException checkedException

发表于 2019-04-29 | 分类于 java

一、简单介绍

除了runtimeException以外的异常,都属于checkedException。

CheckedException(受检异常):编译器会检查这类异常,需要强制捕获,否则无法编译通过。
UnCheckedException(非受检异常):编译器不会检查这类异常,可以不用捕获,可以编译通过。

二、常见异常

受检:IOException、SQLException、NumberFormatException、IllegalArgumentException
非受检:OutOfMemoryError、StackOverflowError、NullPointerException、IndexOutOfBoundsException

点击查看所有jdk8 api文档
进去可以看到java.lang.RuntimeException下有很多子类异常

暂时写这些,日后再完善

HiSEN

Curator - 封装分布式锁等 | ZooKeeper目前最好用的客户端

发表于 2019-04-25 | 分类于 java

一、什么是Curator

Apache Curator is a Java/JVM client library for Apache ZooKeeper, a distributed coordination service.
It includes a highlevel API framework and utilities to make using Apache ZooKeeper much easier and more reliable.
It also includes recipes for common use cases and extensions such as service discovery and a Java 8 asynchronous DSL.

特别说明:Guava is to Java What Curator is to ZooKeeper

二、常见用法

后期补上自己的一些demo,其实官方文档已经介绍很全了
http://curator.apache.org/getting-started.html

三、其它说明

了解这个客户端是在《从Paxos到Zookeeper:分布式一致性原理与实战》这本书里面看到的(书单)
Curator号称是世界上最好用的zk客户端,相比zkClinet来说拥有更好的封装
让我想起Redisson和Jedis的模样

昨天一个做移动端的前同事截图问我那些代码什么意思,用的就是Curator封装的分布式锁

相比于Redis分布式存在超时问题,zookeeper分布式锁利用临时节点可以避免

目前dubbo master上使用的是Curator 4.0.1

HiSEN

Guice Demo | solve NoSuchMethodError

发表于 2019-04-24 | 分类于 java

一、Guice简介

Google公司的Bob lee开发的轻量级IoC容器,其特点是:

  1. 速度快,号称是spring的100倍速度
  2. 无配置文件,实用JDK5.0的annotation描述组件依赖,简单,而且有编译器检查和重构支持
  3. 简单,代码量很少

二、简单样例

  1. 详细代码:https://github.com/hisenyuan/IDEAPractice/tree/master/src/main/java/com/hisen/jars/guice
  2. 依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>4.2.2</version>
    </dependency>
  3. 测试类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class HelloApp extends BaseServer {
    @Inject
    private HelloServiceImpl hello;

    @Test
    public void testSayHello() {
    // 方式一
    Injector injector = Guice.createInjector();
    HelloService helloService = injector.getInstance(HelloService.class);
    helloService.sayHello("hisen");

    // 方式二 其实是在BaseServer中做了方式1的事情 【类似Spring的方式】
    hello.sayHello("1");
    }
    }

三、解决问题

1
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V

github有人遇到同样的问题:https://github.com/SeleniumHQ/selenium/issues/3880

把本地的guava版本由19.0改为21.0成功解决问题

HiSEN

认识Java I/O | BIO NIO AIO | 同步与异步 | 阻塞与非阻塞 | I/O多路复用

发表于 2019-04-13 | 分类于 java

一、名词解释

1.1 同步与异步

同步与异步主要是针对CPU来说的

  1. 同步:CPU必须等着结果返回,这期间不能干别的;
  2. 异步:CPU不必等着结果返回,这期间可以干别的;

1.2 阻塞与非阻塞

阻塞与非阻塞主要是针对I/O来说的

  1. 阻塞:I/O线程会挂起,需等待结果;
  2. 非阻塞:I/O线程不必挂起,不等待结果;

1.3 伪异步I/O

本质上还是同步阻塞I/O
不过是在服务器把socket链接封装成Task提交给线程池处理
因为有队列,所以可以突破C:S=1:1的比例

1.4 I/O多路复用

通过把多个I/O的阻塞复用到一个阻塞上,从而使得系统在单线程情况下可以处理多个客户端的请求。
类似于linux的epoll、select

1.5 多路复用器

Selector,核心是通过Selector来轮询注册在其上的Channel
当发现有Channel就绪就返回Channel的选择键集合,进行I/O操作;

二、不同I/O模型对比表格

阅读全文 »
HiSEN

聊聊MySQL的隔离级别 | MySQL隔离级别原理

发表于 2019-04-13 | 分类于 sql

这是之前的一个帖子:oracle - mysql - 数据库事务隔离级别介绍
写的不全面, 按现在的理解,重新写一个;

一、名词解释

脏读:在一个查询事务过程中,读到了其它事务没有提交的数据;
不可重复读:一个事务查询过程中,多次查询得到了不一致的结果,原因是:有别的更新事务提交了;
幻读:一个事务查询过程中,多次查询得到了不一致的结果,原因是:有别的删除事务/插入事务提交了;

二、数据库隔离级别

name名称脏读不可重复读幻读加锁读
Read uncommitted读未提交YesYesYesNo
Read committed读已提交NoYesYesNo
Repeatable read可重复读NoNoYesNo
Serializable序列化NoNoNoYes

默认的隔离级别为:RR,原因:5.1之后版本,如果Binlogog开启语句级别,必须为RR,RC可能会导致Binlog数据错误(详情);

三、控制方式

读未提交:每次都是读数据最新的版本(包括事务未提交的数据);
读已提交:MVCC控制;
可重复读:MVCC控制;
序列化:在读取的每一行上加锁,只能按顺序进行读写;

四、InnoDB MVCC(多版本并发控制)原理

阅读全文 »
HiSEN

Linux 日志分析出现次数前10的数据 | awk sort uniq

发表于 2019-04-10 | 分类于 linux

一、命令组合

1
2
3
4
$ more sort.log | awk '{print $1}' | sort | uniq -c | sort -k1nr | head -3
4 5
3 1
2 2

二、命令详解

more:一次读取少量的数据,避免一次性载入大文件,比cat好些
awk ‘{print $1}’:以awk默认的分隔符,并且打印第一列
sort:把上一步的结果按ASCII排序
uniq -c:如果重复那么计数,uniq命令可以组合很多其它参数
sort -k1nr:根据第一列的数据进行排序,n是按数值大小排序,r是倒序排序
head -3:显示前面三行数据

三、原始数据

阅读全文 »
HiSEN

Unix文件超过大小限制移动到某目录

发表于 2019-04-08 | 分类于 linux

某个文件夹下面有n个文件,需要移动大于10M的文件到/tmp/目录下

实现命令

1
find . -type f -size +100M -exec mv {} /tmp/ \;

find 查找
. 当前目录
-type 文件类型:f 文件,d 目录
-size 文件大小:+100M +:大于 -:小于 空:等于
-exec 管道命令,将前面的查询结果传递给后面的命令
{} 指前面传递过来的的查询结果
\; 结束管道命令

HiSEN

Java对象的一生 | 从new到被回收

发表于 2019-04-08 | 分类于 java

一、出生过程

这里讲述的是第一次出生的过程,即之前class没有被加载。

1.1 类初始化

1.1.1 加载

1.1.1.1 通过类的全限定名获取定义此类的二进制字节流(可以从zip包、网络、运行时动态生成);
1.1.1.2 将这个字节流所代表的静态存储结构转化为方法去运行时数据结构;
1.1.1.3 在内存(方法区)中生成一个代表这个类的java.lang.Class对象,作为方法区这个类各种数据访问的入口;

1.1.2 验证

1.1.2.1 文件格式验证

1.1.2.1.1 魔数是否以0xCAFEEBABE开头(咖啡宝贝)
1.1.2.1.2 主、次版本号是否在当前虚拟机处理的范围之内(不同的jdk版本编译出来的版本不一致,可向前兼容)
1.1.2.1.3 常量池是否有不被支持的类型(检查常量tag标志)
1.1.2.1.4 指向常量的各种索引值是否指向不存在或者不符合类型的常量
1.1.2.1.5 CONSTANT_Utf8_info型的常量中是否有不符合UTF-8编码的数据
1.1.2.1.6 Class文件中各个部分以及文件本身是否有被删除或者附加的其它信息
…
这些操作是为了确保Class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身安全

1.1.2.2 元数据验证

1.1.2.2.1 是否有父类(Object除外)
1.1.2.2.2 是否继续了不允许继承的类(被final修饰的)
1.1.2.2.3 如果当前不是抽象类,是否实现了其父类或接口中要求实现的所有方法
1.1.2.2.4 类中的字段、方法是否与父类产生矛盾(如覆盖父类final字段、不合法的重载)
这些操作是对字节码进行语义分析,确保符合Java语言规范要求

1.1.2.3 字节码验证

1.1.2.3.1 确保操作数栈的数据类型与指令代码序列能完美配合(反例:操作数栈为int,使用的时候按long加载)
1.1.2.3.2 确保跳转指令不会跳转到方法体以外的字节码指令上
1.1.2.3.3 确保方法体重点类型转换是有效的
这些操作主要是通过数据流和控制流分析,确定程序的语义是合法的、符合逻辑的。
JDK1.6之后有一个优化,利用StackMapTable来验证是否合法

1.1.2.4 符号引用验证

1.1.2.4.1 符号引用中通过字符串描述的全限定名是否能找到对应的类
1.1.2.4.2 符号引用中的类、字段、方法是否可以被当前类访问
在将符号引用转化为直接引用的时候触发符号引用验证

阅读全文 »

1…789…27
hisenyuan

hisenyuan

Java R & D

266 日志
33 分类
112 标签
GitHub Weibo
Links
  • 科技爱好者周刊
  • 美团技术团队
  • duanple(老师木)
  • 当然我在扯淡(王垠)
  • 段永平的博客
  • 梦殇国际
© 2016 - 2024 hisenyuan
由 Hexo 强力驱动
您是第  个访问者    |   
主题 - NexT.Mist