Java Nio

最近在看Netty的源码,顺便了解了一下Java的Nio, 结合JDK源码过了一遍Java NIO Tutorial。下面对其中的一些知识点做下总结。

Java Nio 有三个关键的组件,Channel, Buffer, Selector.

Channel and Buffer

主要包括以下几种Channel和Buffer

  • FileChannel (文件)
  • DatagramChannel (UDP)
  • SocketChannel (TCP)
  • ServerSocketChannel (TCP Server)

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer

Channel 和 Buffer 之间的数据传输

Spring事务管理

最新又重新学习了一遍Spring的事务,这里做点总结,不做如何一步步配置的流水账。

1. 关键类

1
2
3
4
5
6
public interface PlatformTransactionManager {
TransactionStatus getTransaction(
TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}

事务真正的开始、提交、回滚都是通过PlatformTransactionManager这个接口来实现的,例如,我们常用的org.springframework.jdbc.datasource.DataSourceTransactionManager

TransactionDefinition用于获取事务的一些属性,Isolation, PropagationTimeoutRead-only,还定义了事务隔离级别,传播属性等常量。
TransactionStatus用于设置和查询事务的状态,如是否是新事务,是否有保存点,设置和查询RollbackOnly等。

MySQL事务学习总结

关于事务,常看到的概念就是ACID,从单机发展到分布式后,又出现了CAP原理和BASE思想。这里将我最近学习的单机事务做个总结,方便温故知新,后面所有的内容都是基于MySQL/InnoDB的。

隔离级别 脏读 不可重复读 幻象读 第一类更新丢失 第二类更新丢失
READ UNCOMMITED 不会
READ COMMITED 不会 不会
REPEATABLE READ 不会 不会 不会 不会
SERIALIZABLE 不会 不会 不会 不会 不会

ANSI/ISO SQL 92标准定义上面4种隔离级别,以及每种隔离级别要达到什么标准。注意,这里是SQL 92的标准,实际数据库的实现和表格中列的是有出入的。例如,对于REAPEATABLE READ隔离级别,Wikipedia上是这么描述的:
Repeatable reads[edit]
In this isolation level, a lock-based concurrency control DBMS implementation keeps read and write locks (acquired on selected data) until the end of the transaction. However, range-locks are not managed, so phantom reads can occur.
但是对于MySQL/InnoDB, 在 REPEATABLE READ隔离级别下,是不会出现幻象读的,它是通过一种GAP间隙锁来实现的,后面再详细总结。

缓存使用总结

缓存是提高系统性能的利器,我们开发中常用的就是本地缓存和分布式缓存,对于单机的、数据量不大的数据,可以用HashMap自己实现一个简单的缓存,也可以用Guava cache来实现。对于分布式缓存,现在业界常用的都是基于redis, memcached,还有阿里的tair来做的。下面总结一下使用分布式缓存的时候要考虑的问题。

更新策略

  • LRU/FIFO等,对数据一致性要求不高;
  • 超时淘汰,对数据一致性要求也不是很高,实现简单,像redis的话,直接对key设置一个timeout就可以了;
  • 主动更新,对数据一致性要求较高。后面的总结都是针对这种主动更新来说的。

分布式ID

干货都在参考文献里,我只是总结了一下我自己吸收的。

分布式ID

分布式ID,可以理解为分布式系统的数据的唯一标识。概况起来,通常需要满足以下几个条件:

  • 唯一性
  • 有序
    对数据库中的数据按时间进行排序是很常见的需求,通常在表中有GMT_CREATE和GMT_MODIFIED字段,通过在这些字段上建立普通索引(non-cluster index),可以在一定程度上加快排序的速度。但相比聚集索引,普通索引的访问效率还是比较慢的,所以可以通过在主键上建立聚集索引来实现排序。
  • 有意义的
    比如,ID中可能会包含一些业务信息,用于标识所属业务

动态解决Maven依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-aether</artifactId>
<version>0.7.19</version>
</dependency>

GroovyShell永久区内存泄露

今天想在项目中用一下Groovy,主要是为了动态的执行用户配置的命令。代码大致如下:

1
2
3
4
Binding binding = new Binding();
binding.setVariable("R",new RuleFunc());
GroovyShell shell = new GroovyShell(,binding);
shell.evaluate("Groovy Command");

终于搞清楚Java的日志了

Java的日志框架很多,JUL, Log4J, Lobback, JCL, SLF4J等,之前也都大概知道它们是干什么的,网上也有各种讲怎么去配置的。但总觉得不得要领,这周结合官网文档和网上一些文章,把JUL, Log4J, JCL, SLF4J的源码过了一遍,爽。