avatar

目录
mybatis缓存

本文由 简悦 SimpRead 转码, 原文地址 http://www.mybatis.cn/archives/762.html

计算机有两大基本的功能:计算和存储。在存储方面,缓存的设计和实现也是一门学问。这门学问里面包含什么门道呢?不妨研究一下 MyBatis 缓存类 PerpetualCache,一定会大有收获的。

在 MyBatis 里面,存在一个 PerpetualCache,它是一级缓存、二级缓存的最基本实现,但 PerpetualCache 只不过包装了一下 HashMap。Perpetual 是 “永久、不间断” 之意,以 PerpetualCache 为根本,在 cache.decorators 包里面有多种缓存的代理,实现了各种清除策略。

1、PerpetualCache 名字的含义

Perpetual 是 “永久、不间断” 之意,为什么这么命名呢?稍加联系,便能明白。缓存的设计有两个重点问题:如何存储数据和采用何种清除策略。存储的话,用哈希表即可完美解决。对于清除策略而言,往往有多种选择。MyBatis 作者 Clinton Begin 选择 Perpetual 来命名缓存,暗示这是一个最底层的缓存,数据一旦存储进来,永不清除,如果实现清除策略,请把 Perpetual 包装一下。在 cache.decorators 包里面有多种缓存,它们内部串联的主线就是按照 “不同的清除策略” 来贯穿的。

2、PerpetualCache 的实现原理:

PerpetualCache 仅仅是包装了 HashMap,代码如下所示:

plaintext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PerpetualCache implements Cache 

{



private final String id;



private Map<Object, Object> cache = new HashMap<Object, Object>();



}

PerpetualCache 的读取数据,也是通过内部的 HashMap 来实现的,代码如下所示:

plaintext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Override

public void putObject(Object key, Object value) {

cache.put(key, value);

}



@Override

public Object getObject(Object key) {

return cache.get(key);

}



@Override

public Object removeObject(Object key) {

return cache.remove(key);

}



@Override

public void clear() {

cache.clear();

}

3、Key 的设计:CacheKey

在 PerpetualCache 内部使用的 Java 自带的 HashMap:

Map<Object, Object> cache = new HashMap<Object, Object>();

但是,HashMap 的 Key 设计略显单薄,无法适应复杂的缓存场景,需要进行自定义设计。MyBatis 实现了 CacheKey 类,其功能非常的强大。

plaintext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class CacheKey implements Cloneable, Serializable

{

private final int multiplier;

private int hashcode;

private long checksum;

private int count;

private List<Object> updateList;

}

代码分析如下所示:

(1)hashcode,用于表示 CacheKey 的哈希码
(2)checksum,总和校验,当出现复合 key 的时候,分布计算每个 key 的哈希码,然后求总和
(3)count,当出现复合 key 的时候,计算 key 的总个数
(4)updateList,当出现复合 key 的时候,保存每个 key

CacheKey 这个类设计的非常好,个人推荐感兴趣的人可以仔细读一读其源码。其初始化的过程如下所示:

plaintext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public CacheKey(Object[] objects)

{

this();

updateAll(objects);

}



public void updateAll(Object[] objects)

{

for (Object o : objects)

{

update(o);

}

}



public void update(Object object)

{

int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);



count++;

checksum += baseHashCode;

baseHashCode *= count;



hashcode = multiplier * hashcode + baseHashCode;



updateList.add(object);

}



文章作者: thf
文章链接: http://pcbopcbo.github.io/2020/07/07/2020070716/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 漂泊的个人笔记

评论