当前位置: 首页 > article >正文

从零手写实现redis(三)内存数据如何重启不丢失?

1、api

public interface ICacheLoad<K, V> {

    /**
     * 加载缓存信息
     * @param cache 缓存
     * @since 0.0.7
     */
    void load(final ICache<K,V> cache);

}

为了便于后期拓展,定义 ICacheLoad 接口。

2、自定义初始化策略

public class MyCacheLoad implements ICacheLoad<String,String> {

    @Override
    public void load(ICache<String, String> cache) {
        cache.put("1", "1");
        cache.put("2", "2");
    }

}

我们在初始化的时候,放入 2 个固定的信息。

3、测试

ICache<String, String> cache = CacheBs.<String,String>newInstance()
        .load(new MyCacheLoad())
        .build();

Assert.assertEquals(2, cache.size());

只需要在缓存初始化的时候,指定对应的加载实现类即可。

上面先介绍初始化加载,其实已经完成了 cache 持久化的一半。

我们要做的另一件事,就是将 cache 的内容持久化到文件或者数据库,便于初始化的时候加载。

4、接口定义

public interface ICachePersist<K, V> {

    /**
     * 持久化缓存信息
     * @param cache 缓存
     * @since 0.0.7
     */
    void persist(final ICache<K, V> cache);

}

为了便于灵活替换,我们定义一个持久化的接口。

5、简单实现

public class CachePersistDbJson<K,V> implements ICachePersist<K,V> {

    /**
     * 数据库路径
     * @since 0.0.8
     */
    private final String dbPath;

    public CachePersistDbJson(String dbPath) {
        this.dbPath = dbPath;
    }

    /**
     * 持久化
     * key长度 key+value
     * 第一个空格,获取 key 的长度,然后截取
     * @param cache 缓存
     */
    @Override
    public void persist(ICache<K, V> cache) {
        Set<Map.Entry<K,V>> entrySet = cache.entrySet();

        // 创建文件
        FileUtil.createFile(dbPath);
        // 清空文件
        FileUtil.truncate(dbPath);

        for(Map.Entry<K,V> entry : entrySet) {
            K key = entry.getKey();
            Long expireTime = cache.expire().expireTime(key);
            PersistEntry<K,V> persistEntry = new PersistEntry<>();
            persistEntry.setKey(key);
            persistEntry.setValue(entry.getValue());
            persistEntry.setExpire(expireTime);

            String line = JSON.toJSONString(persistEntry);
            FileUtil.write(dbPath, line, StandardOpenOption.APPEND);
        }
    }

}

6、定时执行

public class InnerCachePersist<K,V> {

    private static final Log log = LogFactory.getLog(InnerCachePersist.class);

    /**
     * 缓存信息
     * @since 0.0.8
     */
    private final ICache<K,V> cache;

    /**
     * 缓存持久化策略
     * @since 0.0.8
     */
    private final ICachePersist<K,V> persist;

    /**
     * 线程执行类
     * @since 0.0.3
     */
    private static final ScheduledExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadScheduledExecutor();

    public InnerCachePersist(ICache<K, V> cache, ICachePersist<K, V> persist) {
        this.cache = cache;
        this.persist = persist;

        // 初始化
        this.init();
    }

    /**
     * 初始化
     * @since 0.0.8
     */
    private void init() {
        EXECUTOR_SERVICE.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    log.info("开始持久化缓存信息");
                    persist.persist(cache);
                    log.info("完成持久化缓存信息");
                } catch (Exception exception) {
                    log.error("文件持久化异常", exception);
                }
            }
        }, 0, 10, TimeUnit.MINUTES);
    }

}

上面定义好了一种持久化的策略,但是没有提供对应的触发方式。

我们就采用对用户透明的设计方式:定时执行。

7、测试

ICache<String, String> cache = CacheBs.<String,String>newInstance()
        .load(new MyCacheLoad())
        .persist(CachePersists.<String, String>dbJson("1.rdb"))
        .build();
Assert.assertEquals(2, cache.size());
TimeUnit.SECONDS.sleep(5);

我们只需要在创建 cache 时,指定我们的持久化策略即可。


http://www.kler.cn/a/472555.html

相关文章:

  • 计算机网络(第8版)第3章--PPP课后习题
  • 【阅读笔记】基于FPGA的红外图像二阶牛顿插值算法的实现
  • [Linux]redis5.0.x升级至7.x完整操作流程
  • flutter 专题二十四 Flutter性能优化在携程酒店的实践
  • C#使用MVC框架创建WebApi服务接口
  • STM32-笔记35-DMA(直接存储器访问)
  • Spring Boot 项目自定义加解密实现配置文件的加密
  • ceph集群配置
  • IDEA的常用设置
  • LabVIEW软件Bug的定义与修改
  • HTML 音频(Audio)
  • IDEA 字符串拼接符号“+”位于下一行的前面,而不是当前行的末尾
  • 导航技术的分类
  • Swoole v6 正式发布
  • 软件架构的康威定律:AI如何重构团队协作模式
  • 【VUE+ElementUI】通过接口下载blob流文件设置全局Loading加载进度
  • 在 CentOS 上安装 Docker 和 Docker Compose(可指定版本或安装最新版本)
  • MySQL安装,配置教程
  • 如何设计一个能根据任务优先级来执行的线程池
  • 计算机的错误计算(二百零五)
  • RPM包的制作
  • HTML5实现好看的中秋节网页源码
  • 《浮岛风云》V1.0中文学习版
  • 接口项目uuid算法开发及验证-thinkphp6-rabbitmq
  • 大模型(LLM)面试全解:主流架构、训练目标、涌现能力全面解析
  • 20250108-实验+神经网络