首页IT科技java分布式存储框架(用Java写一个分布式缓存——缓存管理)

java分布式存储框架(用Java写一个分布式缓存——缓存管理)

时间2025-06-14 19:59:47分类IT科技浏览5249
导读:前言 之前也用过一些缓存中间件,框架,也想着自己是不是也能用Java写一个出来,于是就有了这个想法,打算在写的过程中同步进行总结...

前言

之前也用过一些缓存中间件            ,框架                  ,也想着自己是不是也能用Java写一个出来       ,于是就有了这个想法         ,打算在写的过程中同步进行总结

源码:weloe/Java-Distributed-Cache (github.com)

本篇代码:

Java-Distributed-Cache/src/main/java/com/weloe/cache/cachemanager at master · weloe/Java-Distributed-Cache (github.com)

Java-Distributed-Cache/src/test/java/com/weloe/cache/cachemanager at master · weloe/Java-Distributed-Cache (github.com)

上篇:

https://www.cnblogs.com/weloe/p/17050512.html

思路

既然是分布式缓存                  ,那么就一定会有缓存管理方面的问题          ,既然是要储存的数据      ,那么就不能让它无限制的存储                  ,就需要设置临界值             ,这个也是需要缓存淘汰的原因            。

而为了对缓存方便管理   ,比如                  ,我们需要缓存的有多个功能                ,我们为了方便区分,可能就需要在key前加上功能前缀               ,这样不仅变得麻烦                   ,同时由于key变大    ,也会增加内存的压力                  。

所以我们就需要把缓存分组进行管理            ,并提供一些方便的对外接口

实现

CacheObj

Java-Distributed-Cache/CacheObj.java at master · weloe/Java-Distributed-Cache (github.com)

在前篇缓存淘汰中                  ,我们确定了我们真正存储数据的是一个k,v结构       ,因此         ,我们需要抽象出这里的k,v                  ,k选择String          ,而v则抽象出一个CacheObj       。

需要注意的是      ,这里的endTime是该缓存到期的时间                  ,一般而言             ,我们都有为目标缓存设定缓存时间的需求   ,这也是缓存淘汰策略中的一种         。实际存储为byte[]则是为了通用性                  。

public class CacheObj { private LocalDateTime endTime; private Class clazz; private int byteSize; // 存储的实际数据 private byte[] data; public CacheObj() { } public CacheObj(LocalDateTime endTime,Class clazz ,int byteSize, byte[] data) { this.endTime = endTime; this.clazz = clazz; this.byteSize = byteSize; this.data = data; } public int getByteSize() { return byteSize; } public byte[] getData() { return data; } public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; } public LocalDateTime getEndTime() { return endTime; } public void setClazz(Class clazz) { this.clazz = clazz; } }

Cache

Java-Distributed-Cache/Cache.java at master · weloe/Java-Distributed-Cache (github.com)

有组管理                  ,也就需要单一的缓存管理

public class Cache { // 最大字节 private int maxByteSize; // 目前使用字节 private int normalByteSize; // 缓存策略 private CacheStrategy<String, CacheObj> cacheStrategy; Lock readLock; Lock writeLock; public Cache(int maxByteSize, CacheStrategy<String, CacheObj> cacheStrategy) { this.maxByteSize = maxByteSize; this.normalByteSize = 0; this.cacheStrategy = cacheStrategy; readLock = new ReentrantReadWriteLock().readLock(); writeLock = new ReentrantReadWriteLock().writeLock(); } public CacheObj add(String key, CacheObj cacheObj) { writeLock.lock(); normalByteSize += cacheObj.getByteSize(); // 缓存上限 while (normalByteSize > maxByteSize) { // 淘汰缓存 CacheObj outCache = cacheStrategy.outCache(); normalByteSize -= outCache.getByteSize(); } // 加入缓存 CacheObj v = cacheStrategy.put(key, cacheObj); writeLock.unlock(); return v; } public CacheObj get(String key) { readLock.lock(); CacheObj v = cacheStrategy.get(key); // 判断是否过期 if (v != null && v.getEndTime() != null && LocalDateTime.now().isAfter(v.getEndTime())) { CacheObj obj = cacheStrategy.outCache(key); return null; } readLock.unlock(); return v; } public CacheObj remove(String key){ return cacheStrategy.outCache(key); } public void clear(){ cacheStrategy.clear(); } public void setMaxByteSize(int maxByteSize) { this.maxByteSize = maxByteSize; } public int getMaxByteSize() { return maxByteSize; } public int getNormalByteSize() { return normalByteSize; } }

Group

Java-Distributed-Cache/Group.java at master · weloe/Java-Distributed-Cache (github.com)

既然需要组管理                ,那么就需要抽象出一个Group类型,这里的getter是需要后期自定义的回调函数          。

public class Group { private String name; private Cache cache; private Getter getter; @FunctionalInterface interface Getter { byte[] get(String k) throws Exception; }

put,get

为了方便管理               ,Group需要提供get                   ,put法

public CacheObj get(String key) { if ("".equals(key) || key == null) { throw new RuntimeException("key不能为空"); } CacheObj cacheObj = cache.get(key); if (cacheObj != null) { return cacheObj; } return load(key); } /** * 通过Getter回调获取数据 * * @param key * @return */ private CacheObj load(String key) { byte[] bytes = null; try { bytes = getter.get(key); } catch (Exception e) { e.printStackTrace(); return null; } if (bytes == null) { return null; } CacheObj cacheObj = BytesUtil.bytes2CacheObj(bytes); cache.add(key, cacheObj); return cacheObj; } public CacheObj putCacheObj(String key,CacheObj cacheObj){ CacheObj obj = cache.add(key, cacheObj); return obj; }

expire

为存储的数据设定存储时间的方法

public CacheObj expire(String key, long num, ChronoUnit timeUnit){ CacheObj cacheObj; try { cacheObj = cache.get(key); cacheObj.setEndTime(LocalDateTime.now().plus(num, timeUnit)); } catch (Exception e) { return null; } return cacheObj; }

setSize

设置缓存临界值的方法

public boolean setMaxSize(int num){ if(num < cache.getNormalByteSize()){ return false; } cache.setMaxByteSize(num); return true; }

delete,clear

清除组缓存的方法    ,从这里也可以看出其方便性            ,即可以清除单一功能(组)的缓存

public CacheObj delete(String key){ CacheObj obj = cache.remove(key); return obj; } public void clear(){ cache.clear(); }

GroupManager

Java-Distributed-Cache/GroupManager.java at master · weloe/Java-Distributed-Cache (github.com)

既然有Group                  ,就需要管理Group       ,也就需要相对应的put,get方法

public class GroupManager { private Map<String, Group> groupMap; public GroupManager(Map<String, Group> groupMap) { this.groupMap = groupMap; } public Group getGroup(String key) { Group group = groupMap.get(key); return group; } public Group put(Group group){ return groupMap.put(group.getName(),group); } }

测试

CacheTest

Java-Distributed-Cache/CacheTest.java at master · weloe/Java-Distributed-Cache (github.com)

class CacheTest { Cache cache; @BeforeEach void setUp() { CacheStrategy<String, CacheObj> lruCache = new LRUCache<>(5); lruCache.setCallback((s1, s2)-> System.out.println("缓存淘汰")); cache = new Cache(1024*1024,lruCache); } @Test void add() { String s = "123"; CacheObj cacheObj = new CacheObj(LocalDateTime.MAX, String.class, 512*1024, s.getBytes(StandardCharsets.UTF_8)); cache.add("test", cacheObj); for (int i = 0; i < 5; i++) { cache.add("test"+i,cacheObj); } } @Test void get() { CacheObj cacheObj = cache.get("123"); Assertions.assertNull(cacheObj); String s = "123"; cacheObj = new CacheObj(LocalDateTime.MAX,String.class, s.getBytes(StandardCharsets.UTF_8).length, s.getBytes(StandardCharsets.UTF_8)); cache.add("test", cacheObj); CacheObj test = cache.get("test"); Assertions.assertNotNull(test); byte[] data = test.getData(); String s1 = BytesUtil.bytes2String(data); System.out.println(s1); } }

GroupTest

Java-Distributed-Cache/GroupTest.java at master · weloe/Java-Distributed-Cache (github.com)

package com.weloe.cache.cachemanager; import com.weloe.cache.outstrategy.CacheStrategy; import com.weloe.cache.outstrategy.LRUCache; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; class GroupTest { Group group; @BeforeEach void setUp() { CacheStrategy<String, CacheObj> lruCache = new LRUCache<>(5); lruCache.setCallback((s1, s2)-> System.out.println("缓存淘汰")); group = new Group("group1", new Cache(1024*1024,lruCache), str -> { System.out.println("group1回调"); return new byte[0]; }); } @Test void get() { group.putCacheObj("1",new CacheObj()); CacheObj cacheObj = group.get("1"); } @Test void getName() { String name = group.getName(); System.out.println(name); } @Test void putCacheObj() { String x = "132"; group.putCacheObj("cache1",new CacheObj(null,String.class,x.getBytes(StandardCharsets.UTF_8).length,x.getBytes(StandardCharsets.UTF_8))); } @Test void expire() { String x = "132"; group.putCacheObj("cache1",new CacheObj(null,String.class,x.getBytes(StandardCharsets.UTF_8).length,x.getBytes(StandardCharsets.UTF_8))); CacheObj cache1 = group.expire("cache1", 2, ChronoUnit.MINUTES); System.out.println(cache1.getEndTime()); System.out.println(group.get("cache1").getEndTime()); Assertions.assertSame(cache1.getEndTime(),group.get("cache1").getEndTime()); } }

GroupManagerTest

Java-Distributed-Cache/GroupManagerTest.java at master · weloe/Java-Distributed-Cache (github.com)

package com.weloe.cache.cachemanager; import com.weloe.cache.outstrategy.LRUCache; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.concurrent.locks.ReentrantLock; class GroupManagerTest { GroupManager groupManager; @BeforeEach void setUp() { Group group1 = new Group("group1", new Cache(1024*1024, new LRUCache<>(5,(s1, s2)-> System.out.println("group1缓存淘汰"))), str -> {System.out.println("group1未获取缓存的回调");return new byte[0];} ); Group group2 = new Group("group2", new Cache(1024*1024, new LRUCache<>(5,(s1, s2)-> System.out.println("group2缓存淘汰"))), str -> {System.out.println("group2未获取缓存的回调");return new byte[0];} ); groupManager = new GroupManager(new HashMap<>(),new ReentrantLock()); groupManager.put(group1); groupManager.put(group2); } @Test void getGroup() { System.out.println(groupManager.getGroup("")); System.out.println(groupManager.getGroup("group1")); System.out.println(groupManager.getGroup("group2").getName()); } @Test void put() { Group group3 = new Group("group3", new Cache(1024*1024, new LRUCache<>(5,(s1, s2)-> System.out.println("group3缓存淘汰"))), str -> {System.out.println("group3未获取缓存的回调");return new byte[0];} ); groupManager.put(group3); System.out.println(groupManager.getGroup("group3").getName()); } }

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
win10 录屏 软件(Win10录屏软件哪个好用_3款最好用的录屏神器推荐) 百度蜘蛛收录(百度蜘蛛爬几次网站能收录)