LSM-Tree (日志结构合并树)

     LSM-Tree(日志结构合并树)是一种高效处理写操作的存储结构,广泛应用于NoSQL数据库如LevelDB和RocksDB。其核心思想是将随机写入转换为顺序写入,提升吞吐量。以下是其原理及Java实现示例:

### **LSM-Tree 原理**
1. **结构组成**:
   - **MemTable**:内存中的有序结构(如跳表),用于快速写入。
   - **Immutable MemTable**:MemTable写满后转为只读,准备刷盘。
   - **SSTable(Sorted String Table)**:磁盘上的有序文件,由MemTable刷入生成,多个SSTable分层存储。

2. **写入流程**:
   - 数据先写入MemTable。
   - MemTable满后转为Immutable MemTable,异步刷入磁盘生成SSTable。
   - 磁盘SSTable按层级组织,通过合并(Compaction)消除冗余数据。

3. **读取流程**:
   - 依次查找MemTable、Immutable MemTable和各层SSTable。
   - 使用布隆过滤器减少无效磁盘访问。

4. **合并(Compaction)**:
   - 合并多个SSTable,保留最新数据,减少文件数量,提升读取效率。

---

### **Java 示例代码**
```java
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListMap;

public class LSMTree {
    private ConcurrentSkipListMap<String, String> memTable = new ConcurrentSkipListMap<>();
    private ConcurrentSkipListMap<String, String> immutableMemTable = null;
    private List<File> sstables = new ArrayList<>();
    private static final int MAX_MEMTABLE_SIZE = 1000;

    // 写入数据
    public synchronized void put(String key, String value) {
        memTable.put(key, value);
        if (memTable.size() >= MAX_MEMTABLE_SIZE) {
            switchMemTable();
        }
    }

    // 切换MemTable并刷盘
    private void switchMemTable() {
        immutableMemTable = memTable;
        memTable = new ConcurrentSkipListMap<>();
        flushToSSTable(immutableMemTable);
        immutableMemTable = null;
    }

    // 将数据写入SSTable文件
    private void flushToSSTable(ConcurrentSkipListMap<String, String> data) {
        String filename = "sstable_" + System.currentTimeMillis() + ".txt";
        File file = new File(filename);
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            for (Map.Entry<String, String> entry : data.entrySet()) {
                writer.write(entry.getKey() + "," + entry.getValue());
                writer.newLine();
            }
            sstables.add(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 读取数据
    public String get(String key) {
        String value = memTable.get(key);
        if (value != null) return value;

        if (immutableMemTable != null) {
            value = immutableMemTable.get(key);
            if (value != null) return value;
        }

        // 从最新SSTable开始查找
        for (int i = sstables.size() - 1; i >= 0; i--) {
            value = searchInSSTable(sstables.get(i), key);
            if (value != null) return value;
        }
        return null;
    }

    // 在SSTable中查找键
    private String searchInSSTable(File file, String key) {
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split(",", 2);
                if (parts[0].equals(key)) {
                    return parts.length > 1 ? parts[1] : null;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 合并SSTable文件
    public void compact() {
        if (sstables.size() < 2) return;

        List<File> oldFiles = new ArrayList<>(sstables);
        sstables.clear();
        TreeMap<String, String> mergedData = new TreeMap<>();

        // 按旧到新顺序合并,保留最新值
        for (File file : oldFiles) {
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    String[] parts = line.split(",", 2);
                    String key = parts[0];
                    String value = parts.length > 1 ? parts[1] : null;
                    mergedData.put(key, value);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 写入新文件并清理旧文件
        String filename = "sstable_merged_" + System.currentTimeMillis() + ".txt";
        File mergedFile = new File(filename);
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(mergedFile))) {
            for (Map.Entry<String, String> entry : mergedData.entrySet()) {
                writer.write(entry.getKey() + "," + entry.getValue());
                writer.newLine();
            }
            sstables.add(mergedFile);
            for (File f : oldFiles) {
                f.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        LSMTree lsm = new LSMTree();
        // 示例操作
        lsm.put("key1", "value1");
        lsm.put("key2", "value2");
        System.out.println(lsm.get("key1")); // 输出 value1
    }
}
```

### **代码说明**
1. **写入优化**:使用跳表(`ConcurrentSkipListMap`)作为MemTable,写满后转为Immutable并刷盘。
2. **读取流程**:依次检查内存表和SSTable文件,确保获取最新数据。
3. **合并策略**:简单合并所有SSTable,生成新文件并删除旧文件,保留最新键值。

### **优化方向**
- **分层存储**:引入层级结构,每层数据量逐层递增,合并策略更精细。
- **布隆过滤器**:快速判断键是否存在于SSTable,减少IO。
- **索引优化**:为SSTable维护内存索引,加速查找。

LSM-Tree通过顺序写入和定期合并,在高写入场景下表现优异,适合日志系统、时序数据库等应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【玩转 Postman 接口测试与开发2_020】(完结篇)DIY 实战:随书示例 API 项目本地部署保姆级搭建教程(含完整调试过程)

《API Testing and Development with Postman》最新第二版封面 文章目录 最新版《Postman 接口测试与开发实战》示例 API 项目本地部署保姆级搭建教程1 前言2 准备工作3 具体部署3.1 将项目 Fork 到自己名下3.2 创建虚拟环境并安装依赖3.3 初始运行与项目调试 4 示例项目的用法…

3-提前结束训练

一、核心类 class EarlyStopping:# YOLOv5 simple early stopperdef __init__(self, patience30):self.best_fitness 0.0 # i.e. mAPself.best_epoch 0self.patience patience or float(inf) # epochs to wait after fitness stops improving to stopself.possible_stop …

若依 ruoyi-vue 根据角色切换路由菜单权限 SAAS

后端根据角色查询相应的菜单&#xff08;角色对应管理的系统&#xff09; /*** 获取路由信息根据角色&#xff08;系统类型&#xff09;** return 路由信息*/GetMapping("getRoutersBySystemType")public AjaxResult getRoutersBySystemType(String systemType) {Lon…

2024最新版鸿蒙纯血原生应用开发教程文档丨学习ArkTS语言-基本语法

ArkTS是HarmonyOS的主要应用开发语言&#xff0c;在TypeScript基础上进行了扩展&#xff0c;保留了其基本风格&#xff0c;并通过增强静态检查和分析来提高程序的稳定性和性能。本教程将帮助开发者掌握ArkTS的核心功能、语法及最佳实践&#xff0c;以便高效地构建高性能移动应用…

使用插件 `vue2-water-marker`添加全局水印

使用插件 vue2-water-marker添加全局水印 效果图 1、安装插件 npm install vue2-water-marker --save2、全局注册 // main.js import Vue from vue import Vue2WaterMarker from vue2-water-markerVue.use(Vue2WaterMarker)3、在组件中使用 <template><div id&q…

docker安装etcd:docker离线安装etcd、docker在线安装etcd、etcd镜像下载、etcd配置详解、etcd常用命令、安装常见问题总结

官方网站 官方网址&#xff1a;etcd 二进制包下载&#xff1a;Install | etcd GitHub社区项目&#xff1a;etcd-io GitHub GitHub社区项目版本历史&#xff1a;Releases etcd-io/etcd GitHub 一、镜像下载 1、在线下载 在一台能连外网的linux上执行docker镜像拉取命令…

探索浮点数在内存中的存储(附带快速计算补码转十进制)

目录 一、浮点数在内存中的存储 1、常见的浮点数&#xff1a; 2、浮点数存储规则&#xff1a; 3、内存中无法精确存储&#xff1a; 4、移码与指数位E&#xff1a; 5、指数E的三种情况&#xff1a; 二、快速计算补码转十进制 1、第一种方法讨论&#xff1a; 2、第二种方…

第25周JavaSpringboot实战-电商项目 4.商品分类管理

商品分类模块开发笔记 模块功能概述 实现分类数据的 增删改查 功能核心难点&#xff1a; 分类的父子级目录结构递归实现多级分类查找列表展示顺序控制&#xff08;从父级向子级递归&#xff09; 接口说明 后台接口 1. 添加分类 请求地址: /admin/category/add 请求方法: …

【星云 Orbit-F4 开发板】03g. 按键玩法七:矩阵键盘单个触发

【星云 Orbit-F4 开发板】03g. 按键玩法七&#xff1a;矩阵键盘单个触发 引言 矩阵键盘是一种常见的输入设备&#xff0c;广泛应用于各种嵌入式系统中。通过矩阵键盘&#xff0c;用户可以通过按键输入字符或控制信号。本文将详细介绍如何使用STM32F407的GPIO引脚实现矩阵键盘的…

Milvus x DeepSeek 搭建低成本高精度 RAG 实战

为什么手握海量数据&#xff0c;却用不出真正的“智能”&#xff1f;要么 AI 模型学艺不精&#xff0c;答非所问&#xff1b;要么技术门槛太高&#xff0c;让普通开发者望而却步。现在&#xff0c;使用阿里云 Milvus 向量检索服务、DeepSeek 大模型和 PAI LangStudio 开发工具&…

每日一题——两数之和

两数之和 问题描述示例提示思路分析代码实现代码解析1. 哈希表结构体定义2. 初始化哈希表3. 释放哈希表内存4. 主函数 twoSum5. 返回结果复杂度分析 第二种解法代码功能概述代码详细注释1. 哈希表结构体定义2. 哈希表指针3. 查找函数4. 插入函数5. 两数之和函数 6. 主函数&…

2025年SCI1区TOP:真菌生长优化算法FGO,深度解析+性能实测

目录 1.摘要2.算法原理3.结果展示4.参考文献5.代码获取 1.摘要 本文提出了一种新型的自然启发元启发式算法——真菌生长优化算法&#xff08;FGO&#xff09;&#xff0c;灵感来源于真菌在自然界中的生长行为。真菌的生长行为包括菌丝生长、分枝和孢子萌发&#xff0c;菌丝生长…

穿越AI边界:深度集成DeepSeek API与云平台的实践之路

云边有个稻草人-CSDN博客 随着人工智能技术的日益发展&#xff0c;深度学习和自然语言处理&#xff08;NLP&#xff09;已经在很多领域得到了广泛的应用。DeepSeek作为一款领先的大型语言生成模型&#xff0c;凭借其强大的推理和生成能力&#xff0c;已经被越来越多的开发者和…

动态表头导出EasyExcel

在 Spring Boot 中结合 EasyExcel 实现动态表头导出&#xff08;无实体类&#xff0c;表头和字段&#xff08;前端传表名&#xff0c;字段值动态查询&#xff0c;返回List<Map<String,Object>>&#xff09;由前端传递&#xff09;可以通过以下步骤实现。以下是完整…

1 | 从零开始解密数据库:数据库基础概念

❤个人主页&#xff1a;折枝寄北的博客 ❤专栏位置&#xff1a;数据库专栏 目录 前言1. 数据&#xff08;data&#xff09;2. 数据库(DB)3. 数据库管理系统(DBMS)4. 数据库系统(DBS) 感谢您的阅读支持 前言 【前言】 在万物互联的数字时代&#xff0c;数据已成为驱动社会运转…

Web自动化之Selenium下Chrome与Edge的Webdriver常用Options参数

目录 引言 说明 Add_argument() 添加方式 常用参数 Add_experimental_option() 添加方式 常用方法 任务结束后仍然保持浏览器打开 禁用“Chrome 正受到自动测试软件的控制”提示 设置下载路径 禁用弹窗拦截 禁用图片加载 禁用 JavaScript 注意 引言 …

AI提示词的种类与适合的任务

以下是提示词的主要种类及其适用任务&#xff0c;基于大模型特性与最佳实践总结&#xff1a; 一、基础提示词 零样本提示&#xff08;Zero-shot Prompting&#xff09; 形式&#xff1a;直接输入任务指令&#xff0c;不提供示例&#xff08;如“翻译以下句子&#xff1a;Hello …

FTP 实验(ENSP模拟器实现)

目录 FTP 概述 FTP实验 FTP的报文交互 FTP 概述 FTP&#xff08;File Transfer Protocol&#xff0c;文件传输协议&#xff09;是一种用于在网络上进行文件传输的标准协议。它允许用户在两台计算机之间上传和下载文件。 1、FTP采用客户端-服务器模型&#xff0c;客户端通过…

Windows前端开发IDE选型全攻略

Windows前端开发IDE选型全攻略 一、核心IDE对比矩阵 工具名称最新版本核心优势适用场景推荐指数引用来源VS Code2.3.5轻量级/海量插件/跨平台/Git深度集成全栈开发/中小型项目⭐⭐⭐⭐⭐14WebStorm2025.1智能提示/框架深度支持/企业级调试工具大型项目/专业前端团队⭐⭐⭐⭐47…

鸿蒙5.0实战案例:har和hsp的转换

往期推文全新看点&#xff08;文中附带全新鸿蒙5.0全栈学习笔录&#xff09; ✏️ 鸿蒙&#xff08;HarmonyOS&#xff09;北向开发知识点记录~ ✏️ 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ ✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景&#…