堆内缓存:
- LinkedHashMap:Java自带类,内置LRU驱逐策略的实现(access-order);多线程访问需要自己实现同步。
- Guava Cache:Google Guava工具包中的缓存实现,支持LRU驱逐策略;支持多线程并发访问,支持按时间过期,但只有在访问时才清除过期数据。
- Ehcache:支持多种驱逐策略:LFU、LRU、FIFO,支持持久化和集群。性能跟Guava Cache比相当。
- Caffeine:支持W-TinyLFU驱逐策略,Benchmark测试读写性能是Guava Cache的6倍左右。
堆外缓存:
- OHCache:支持缓存驱逐和过期(Cassandra使用的缓存库)
- ChronicleMap:支持Hash结构,性能好,不支持缓存驱逐
- MapDB:支持Tree结构,可顺序扫描,不支持缓存驱逐
- Ehcache3:BigMemory收费
当缓存数据量非常大时,GC压力过大会导致服务响应慢甚至崩溃,在HugeGraph图数据库中为了缓解该问题,需引入堆外缓存,选择了使用OHCache。
OHCache对外缓存总结
开源:https://github.com/snazy/ohc
特性:
- 底层有2种实现:linked实现,适用于中大entry场景,默认实现,大部分feature只在该实现中才支持;chunked实现,适用于小entry场景,通过设置chunkSize或者fixedEntrySize启用。
- 通过eviction()来设置缓存驱逐策略,支持:LRU, W_TINY_LFU, NONE共3种,后两种仅在linked实现中支持。
- 通过capacity()来指定缓存的容量,单位是字节,注意不是条数。
- 通过hashTableSize()来设置每个hash_table最大存放的entry个数数量(默认是0.75的factor)。
- 必须指定自定义的keySerializer、valueSerializer系列化器,重载实现系列化serialize()方法与反序列化deserialize()方法;需要注意的是还需要重载serializedSize()方法,且该方法返回值必须和实际写入的内容大小完全一样,否则会报错或数据不对。
- 支持缓存条目过期机制,通过timeouts()开启;允许通过defaultTTLmillis()设置一个默认过期时间,也可以在put()的时候单独设置expireAt过期时间。注意:过期机制仅linked实现才支持,因为chunked实现是以chunk为单位进行缓存驱逐的,无法精确到entry粒度;而且并没有独立的线程来回收过期条目,只会在get或put操作时进行检查(见get()或者ensureFreeSpaceFo