0%

零、本文背景

一个接口的关键指标应该就是响应速度,要想提高响应速度,结果在缓存中最好;
那么怎么确定一个合理的缓存时间,以平衡性能与成本呢?
我们可以通过记录业务请求,看读取缓存的时间分布,比如 99% 的请求都是 1天内;

近期在做日志分析,找到比较理想的一个缓存过期时间,使 90% 的查询都能被缓存覆盖;
发现有些同学不太懂 TP 指标,故写文记录一下。

一、性能指标含义

常见指标:TP50、TP80、TP90、TP99、TP999
正式解释:TP=Top Percentile,Top百分数,是一个统计学术语,与平均数、中位数都是一类;
通俗理解:TP99 100ms,99%的查询都能在100ms内返回;
本质理解:它是一个分位值,看数据的一个分布;

二、性能指标计算

计算方式:拿到所有请求耗时,升序排序,取 99% 位置的数据,就是 TP99;
比如说:拿 100 次请求的耗时,升序排序,取第 99 个的数据,就是TP99的值;

具体的代码方式就是,先算出耗时,放入 List ,然后排序,按指定的下标取值即可;

代码如下:

Read more »

零、本文背景

项目中看到有一个缓存接口存在多个实现类,
但是在代码中使用@Resource注解注入,
之前有了解过@Autowire @Resource的区别,
于是就尝试着搜索@@Resource,于是就有本文的总结了。

一、两个注解

1.1 @Autowire

1.1.1 Spring开发;
1.1.2 按照type来注入;

1.2 @Resource

1.2.1 JDK开发;
1.2.2 按照名称注入,若无,则按type来注入(未指定name的情况下);

二、后记

  1. 做事情要有计划,得主动;
  2. 需要想清楚自己想要什么样的生活,然后朝着目标奋斗;
  3. 使用现成的代码尽量搞清楚来龙去脉,可以学习知识,更能避免被坑;
  4. 每天的学习时间需要保证,坚持很重要;

零、本文由来

感觉从业这么久以来,读取文件路径相关问题一直是一个痛
用的很少,之前也解决过相关的问题
但是得用这种路径

1
src/test/resources/test/test.txt

上面这种路径如果在代码中的话,src/test/resources是不会存在的,会出现问题
本次学到了一个新的方法,Class.getResourceAsStream();
需要的路径在资源文件夹下面即可,填写路径:/test/test.txt
打包最终的路径会在:WEB-INF/classes/test/test.txt

ps:因maven打包配置不同,最终resources资源文件夹下的路径是不同的,注意src的坑即可

一、文件结构

1
2
3
4
5
6
7
│   └── test
│   ├── Java
│   │   └── mq
│   │   └── Test.Java
│   └── resources
│   ├── test
│   │   └── test.txt

二、读取代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/spring-config.xml"})
public class Test {
@Test
public void test() throws IOException {
InputStream inputStream = Test.class.getResourceAsStream("/test/test.txt");
byte[] buffer = new byte[1024];
int len;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = inputStream.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.close();
String res = bos.toString();
System.out.println(res);
}
}

一、volatile是什么

volatile是Java提供的一种轻量级的同步机制
保证变量的修改其它线程立马可见,解决部分并发问题

二、volatile局限性

无法解决复合操作,例如 i++ i–这种操作
原因:i++操作分三步

  1. 读取i=1;
  2. i=i+1=2;
  3. i=2写入主存
    有可能在3写入之前,其它线程已经对i进行了修改,比如改为100了,结果覆盖写入了2

三、volatile原理

volatile底层依靠指令重排序来实现内存可见性的
具体的规则如下

  1. 当第二个操作是voaltile写时,无论第一个操作是什么,都不能进行重排序
  2. 当第一个操作是volatile读时,不管第二个操作是什么,都不能进行重排序
  3. 当第一个操作是volatile写时,第二个操作是volatile读时,不能进行重排序
Read more »

一、为什么用缓存

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. 统计缓存使用过程中命中率、异常率、未命中率等统计数据;
Read more »

一、理论知识

常见参数:

  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倍活跃空间大小
Read more »

一、简单介绍

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

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

二、常见异常

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

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

暂时写这些,日后再完善

一、什么是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

一、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>
  1. 测试类
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成功解决问题

一、名词解释

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模型对比表格

Read more »